Configuration

Tally is configured entirely through environment variables. No config files, no UI settings — just environment variables, the way infrastructure should be.

Required

ADMIN_PASSWORD    # Dashboard login password (min 16 chars in production)
SITES             # JSON map of sites: {"domain.com":{"token":"secret"}}

Production safety: If NODE_ENV=production , the server refuses to start with the default password or any password shorter than 16 characters.

Server

PORT              # HTTP port (default: 3000)
DB_PATH           # SQLite database path (default: ./data/analytics.db)
GEOLITE2_PATH     # MaxMind GeoLite2-City.mmdb path (default: ./data/GeoLite2-City.mmdb)
TRUSTED_PROXIES   # Comma-separated IPs/CIDRs whose forwarding headers are trusted (default: none)
API_KEY           # API authentication key. No fallback: unset means API auth is disabled

API authentication: API_KEY is never derived from ADMIN_PASSWORD . When it is unset, bearer-token API access is disabled entirely — generate one with, e.g., openssl rand -hex 32 .

Reverse proxies

Client IP resolution (rate limiting, analytics) uses the socket peer address by default; X-Forwarded-For and X-Real-IP are ignored unless the direct peer is listed in TRUSTED_PROXIES (exact IPs or IPv4 CIDR ranges, e.g. TRUSTED_PROXIES=127.0.0.1,10.0.0.0/8 ). Behind a trusted proxy, the forwarded chain is parsed from the trusted end, so a client cannot forge its identity by sending its own X-Forwarded-For header.

TRUST_PROXY_AUTH is separate: it trusts Remote-User/Proxy-Secret headers for authentication in front-door SSO setups.

Sites configuration

The SITES variable is a JSON object mapping site IDs to their tokens. The site ID is passed via the data-site attribute on the tracker script. The token is passed via data-token and used for origin validation.

SITES='{
  "blog.example.com": { "token": "sk-blog-abc123" },
  "docs.example.com": { "token": "sk-docs-def456" }
}'

GeoIP (optional)

MAXMIND_ACCOUNT_ID    # MaxMind account ID for GeoLite2 downloads
MAXMIND_LICENSE_KEY   # MaxMind license key

If both are provided, the Docker entrypoint automatically downloads the GeoLite2 City database on first start. Without GeoIP, country/city/region data will be unavailable.

Origin validation

The ALLOWED_ORIGINS variable controls which origins can send events:

ALLOWED_ORIGINS="https://example.com,https://www.example.com"

If empty, the server accepts events from any origin (useful for development). In production, set this to your site's origins.

Defaults (no configuration needed)

These work out of the box: