DEV Community

selfhosting.sh
selfhosting.sh

Posted on • Originally published at selfhosting.sh

Shynet

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Start the stack:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Initial Setup

After the containers start, create your admin account:

docker exec -it shynet ./manage.py registeradmin your-email@example.com
Enter fullscreen mode Exit fullscreen mode

You'll be prompted to set a password. Then set the instance name:

docker exec -it shynet ./manage.py whitelabel "My Analytics"
Enter fullscreen mode Exit fullscreen mode

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:

  1. Click "Create a Service" in the dashboard
  2. Enter your site name and URL
  3. Copy the tracking pixel (<img> tag) or JavaScript snippet
  4. 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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Related

Top comments (0)