What Is Shynet?
Shynet is a privacy-focused, cookie-free web analytics platform that tracks page views and sessions without JavaScript (it uses a tracking pixel by default, with an optional JS snippet for richer data). It replaces Google Analytics for users who want accurate visitor counts without compromising privacy. Built with Django and open-source under the Apache 2.0 license, Shynet provides a clean dashboard showing page views, sessions, referrers, and device information — all without cookies or fingerprinting.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 512 MB of free RAM (minimum)
- 2 GB of free disk space
- A domain name (optional, for remote access)
Docker Compose Configuration
Create a directory for your Shynet deployment:
mkdir -p ~/shynet && cd ~/shynet
Create a docker-compose.yml file:
services:
shynet:
image: milesmcc/shynet:v0.14.0
container_name: shynet
depends_on:
db:
condition: service_healthy
environment:
# Database connection
DB_NAME: shynet
DB_USER: shynet
DB_PASSWORD: ${DB_PASSWORD}
DB_HOST: db
DB_PORT: "5432"
# Django settings — CHANGE the secret key
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY}
# Your domain (no trailing slash)
ALLOWED_HOSTS: ${SHYNET_HOST:-*}
CSRF_TRUSTED_ORIGINS: ${CSRF_ORIGINS:-https://analytics.example.com}
# Application settings
PORT: "8080"
PERFORM_CHECKS_AND_SETUP: "True"
SCRIPT_USE_HTTPS: "True"
ACCOUNT_SIGNUPS_ENABLED: "False"
TIME_ZONE: "UTC"
ports:
- "8080:8080"
restart: unless-stopped
networks:
- shynet-net
db:
image: postgres:16-alpine
container_name: shynet-db
environment:
POSTGRES_DB: shynet
POSTGRES_USER: shynet
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- shynet_db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U shynet"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- shynet-net
volumes:
shynet_db:
networks:
shynet-net:
driver: bridge
Create a .env file alongside it:
# Database password — CHANGE THIS to a strong random value
DB_PASSWORD=change-me-to-a-strong-random-password
# Django secret key — generate with: python3 -c "import secrets; print(secrets.token_urlsafe(50))"
DJANGO_SECRET_KEY=change-me-to-a-long-random-string
# Your Shynet domain (used for ALLOWED_HOSTS and CSRF)
SHYNET_HOST=analytics.example.com
CSRF_ORIGINS=https://analytics.example.com
Start the stack:
docker compose up -d
Initial Setup
After the containers start, create your admin account:
docker exec -it shynet ./manage.py registeradmin your-email@example.com
You'll be prompted to set a password. Then set the instance name:
docker exec -it shynet ./manage.py whitelabel "My Analytics"
Access the web UI at http://your-server-ip:8080 and log in with the email and password you just created.
To add a site for tracking:
- Click "Create a Service" in the dashboard
- Enter your site name and URL
- Copy the tracking pixel (
<img>tag) or JavaScript snippet - Add it to your website's HTML
| Tracking Method | Pros | Cons |
|---|---|---|
Tracking pixel (<img>) |
No JavaScript needed, works everywhere | No session duration or page load times |
| JavaScript snippet | Session data, page load metrics, SPA support | Requires JS execution |
Configuration
Email Notifications (Optional)
Add SMTP settings to receive alerts about your analytics:
environment:
EMAIL_HOST: smtp.example.com
EMAIL_PORT: "587"
EMAIL_HOST_USER: analytics@example.com
EMAIL_HOST_PASSWORD: ${SMTP_PASSWORD}
EMAIL_USE_TLS: "True"
SERVER_EMAIL: analytics@example.com
Multi-Instance Scaling with Redis
For high-traffic sites, add Redis for caching and Celery task processing:
services:
redis:
image: redis:7-alpine
container_name: shynet-redis
restart: unless-stopped
networks:
- shynet-net
shynet:
environment:
REDIS_CACHE_LOCATION: redis://redis:6379/0
CELERY_BROKER_URL: redis://redis:6379/1
CELERY_TASK_ALWAYS_EAGER: "False"
Key Environment Variables
| Variable | Default | Description |
|---|---|---|
ACCOUNT_SIGNUPS_ENABLED |
False |
Allow public account registration |
SCRIPT_USE_HTTPS |
True |
Use HTTPS in tracking scripts |
PERFORM_CHECKS_AND_SETUP |
True |
Auto-run migrations on startup |
SHOW_SHYNET_VERSION |
True |
Display version in footer |
TIME_ZONE |
UTC |
Dashboard timezone |
Reverse Proxy
Place Shynet behind a reverse proxy for SSL termination. With Nginx Proxy Manager:
-
Scheme:
http -
Forward Hostname:
shynet(container name) or your server IP -
Forward Port:
8080 - Enable SSL and force HTTPS
Set CSRF_TRUSTED_ORIGINS to your public URL (e.g., https://analytics.example.com). See our Reverse Proxy Setup guide for detailed configuration.
Backup
Back up the PostgreSQL database regularly:
docker exec shynet-db pg_dump -U shynet shynet > shynet_backup_$(date +%Y%m%d).sql
The shynet_db volume contains all persistent data. Include it in your backup strategy.
Troubleshooting
CSRF Verification Failed
Symptom: 403 Forbidden error when logging in.
Fix: Ensure CSRF_TRUSTED_ORIGINS matches your exact public URL including the protocol (https://analytics.example.com). Restart the container after changing it.
Tracking Pixel Not Recording Visits
Symptom: Dashboard shows zero hits despite pixel placement.
Fix: Verify the pixel URL is reachable from the client browser. Check that ALLOWED_HOSTS includes your domain. If using HTTPS, set SCRIPT_USE_HTTPS=True.
Database Connection Refused
Symptom: Shynet fails to start with "could not connect to server" errors.
Fix: Ensure the db container is healthy (docker compose ps). The depends_on with health check should handle startup order, but PostgreSQL may need more time on first run.
Admin Account Locked Out
Symptom: Forgot admin password.
Fix: Reset via Django management command:
docker exec -it shynet ./manage.py changepassword your-email@example.com
Resource Requirements
- RAM: ~150 MB idle, ~300 MB under moderate load
- CPU: Low — Django handles analytics ingestion efficiently
- Disk: ~500 MB for application, plus database growth (~1 GB per million page views)
Verdict
Shynet is an excellent choice if you want dead-simple, privacy-respecting analytics without the complexity of Matomo or the JavaScript dependency of Plausible. The tracking pixel approach means it works on sites where JavaScript is blocked or unwanted. The trade-off is fewer features — no funnel analysis, no real-time dashboards, no custom events. For most personal sites and small projects, that's a fair trade. If you need product analytics or advanced segmentation, look at PostHog instead.
Frequently Asked Questions
How does Shynet compare to Plausible or Umami?
Shynet is simpler and lighter — it can track visits with just a tracking pixel (no JavaScript required), while Plausible and Umami require JavaScript snippets. The trade-off is fewer features: no real-time dashboard, no custom events, no UTM campaign tracking. Choose Shynet for dead-simple privacy analytics on personal sites; Plausible or Umami for more comprehensive visitor insights.
Does Shynet use cookies or JavaScript?
Neither by default. Shynet's tracking pixel approach uses a 1x1 image tag that records page views without cookies, JavaScript, or fingerprinting. An optional JavaScript snippet adds richer data (session duration, page load times, SPA navigation) but is not required.
Can Shynet track multiple websites?
Yes. Create a separate "Service" in the dashboard for each website you want to track. Each service gets its own tracking pixel/script and independent analytics dashboard. There's no limit on the number of services.
Is Shynet still actively maintained?
Development has slowed significantly. The last major release was v0.13.1, and GitHub activity is minimal. The project is stable and functional for its intended use case, but don't expect new features. If you need an actively maintained alternative, Umami or Plausible have larger communities and regular updates.
How much disk space does Shynet use?
The application itself is small (~500 MB including PostgreSQL). Database growth depends on traffic — roughly 1 GB per million page views. For most personal sites and small projects, disk usage is negligible.
Can I use Shynet without PostgreSQL?
No. Shynet requires PostgreSQL as its database backend. There's no SQLite option. This makes the minimum deployment two containers (Shynet + PostgreSQL), which is more than some alternatives like GoatCounter that use embedded databases.
Top comments (0)