Production Deployment

Tally is designed for production use with minimal operational overhead. This guide covers security hardening, backups, monitoring, and scaling considerations.

Security checklist

Reverse proxy setup

Tally listens on a single port. Use a reverse proxy for TLS, domain routing, and rate limiting:

Caddy (recommended — automatic HTTPS)

tally.example.com {
  reverse_proxy localhost:3000
}

nginx

server {
    listen 443 ssl;
    server_name tally.example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Backups

Tally stores all data in a single SQLite file. To back up:

# Safe backup (SQLite hot backup)
sqlite3 /app/data/analytics.db ".backup /backups/tally-$(date +%Y%m%d).db"

# Or simply copy the file (works if the server is stopped)
cp /app/data/analytics.db /backups/tally-$(date +%Y%m%d).db

SQLite in WAL mode is crash-safe. For production, set up a daily cron job that runs the .backup command.

Monitoring

The Docker image includes a health check:

# The built-in health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3   CMD wget -qO- http://localhost:3000/ || exit 1

Monitor the / endpoint for uptime. The server returns 200 if healthy.

Resource requirements

Tally is extremely lightweight:

GeoIP updates

MaxMind updates GeoLite2 databases weekly. To update, restart the container or download the new database file and replace the existing one. The server will pick up the new file on next startup.

# Manual update
curl -fsSL "https://download.maxmind.com/geoip/databases/GeoLite2-City/download?suffix=tar.gz"   -u "$MAXMIND_ACCOUNT_ID:$MAXMIND_LICENSE_KEY"   | tar -xzf - --strip-components=1 -C /app/data/ GeoLite2-City_*/GeoLite2-City.mmdb

Updating Tally

docker pull tally:latest
docker compose down
docker compose up -d

SQLite handles schema migrations automatically on startup. No manual migration steps needed.

Scaling

Tally is designed for single-instance deployment. SQLite handles concurrent reads efficiently via WAL mode. For most personal and small-business sites, a single instance handles millions of pageviews without issue.

If you need to scale beyond a single instance, consider: