Warning
Deprecated and unmaintained. The original hosted instance was retired on July 15, 2026, and this repository is preserved as a read-only reference. It receives no maintenance, support, or security updates. You are welcome to fork it and continue development under the MIT License, but review and update its dependencies and security controls before deploying it.
BufferDash is a self-hosted, first-party web analytics dashboard with traffic-quality signals and optional application-runtime metrics. One installation can track multiple sites.
- Multi-site tracking with public site keys
- Tiny public
/tracker.jsscript - Page views, sessions, bounce rate, unique visitors, referrers, browsers, OS, devices, locations, and live visitors
- Selectable 24-hour, 7-day, 30-day, and 90-day analytics ranges
- Secure IP handling with optional anonymization and hashed IPs
- Bot, unknown-path, failed-login, and rate-limit security signals
- Protected admin dashboard with signed HTTP-only sessions and CSRF checks
- Background retention cleanup, Caddy HTTP diagnostics, and explicit VPS-host metrics
- Docker Compose setup with PostgreSQL
BufferDash should run behind Caddy at an HTTPS hostname such as https://analytics.example.com. PostgreSQL remains inside Docker, while the app binds only to loopback.
git clone https://github.com/1337lean/bufferdash.git
cd bufferdash
cp .env.example .env
chmod 600 .envConfigure .env before starting:
LOCAL_ONLY=false
APP_URL=https://analytics.example.com
BIND_ADDRESS=127.0.0.1
TZ=America/New_York
DATABASE_URL=postgresql://bufferdash:YOUR_DATABASE_PASSWORD@postgres:5432/bufferdash
POSTGRES_PASSWORD=YOUR_DATABASE_PASSWORD
SESSION_SECRET=YOUR_RANDOM_SESSION_SECRET
TRACKING_SECRET=YOUR_DIFFERENT_RANDOM_TRACKING_SECRET
ADMIN_EMAIL=you@example.com
ADMIN_PASSWORD_HASH='$2b$12$YOUR_BCRYPT_HASH'
ADMIN_PASSWORD=
TRUST_PROXY=true
ANONYMIZE_IP=true
ENFORCE_TRACKING_ORIGIN=trueGenerate separate secrets and a password hash on a trusted machine after npm ci:
openssl rand -base64 48
openssl rand -base64 48
read -s ADMIN_PASSWORD; export ADMIN_PASSWORD
node -e 'require("bcryptjs").hash(process.env.ADMIN_PASSWORD, 12).then(console.log)'
unset ADMIN_PASSWORDRun the production preflight, deploy, and verify:
scripts/production-check.sh .env
scripts/deploy-production.sh .env
docker compose ps
curl -fsS http://127.0.0.1:3001/healthThe deploy command takes a database backup before updating an existing installation, applies migrations, waits for the app, worker, and database to become healthy, and fails if any production guardrail is missing.
See DEPLOYMENT.md for Caddy, firewall, update, backup, and final verification guidance.
After signing in, open /sites, create a site with its exact domain, and copy the generated public site key. Add the tracker directly or expose a same-origin loader from the tracked application:
BUFFERDASH_URL=https://analytics.example.com
BUFFERDASH_SITE_ID=example-com-generated-keyRestart or redeploy the tracked application after changing its configuration.
For a local installation, set LOCAL_ONLY=true, use APP_URL=http://localhost:3000, keep BIND_ADDRESS=127.0.0.1, and set TRUST_PROXY=false. Local mode accepts ADMIN_PASSWORD; hosted production requires ADMIN_PASSWORD_HASH.
npm install
npx prisma migrate dev
npm run devThe development server binds only to 127.0.0.1.
npm run db:backupRestore a dump:
docker compose stop app worker
npm run db:restore -- backups/bufferdash-YYYYMMDDTHHMMSSZ.dump
docker compose up -dFor production, schedule backups and copy them off the VPS. Test restoration periodically.
The generated snippet looks like:
<script defer src="https://analytics.example.com/tracker.js" data-site-id="example-com-generated-key"></script>Custom events are supported:
window.bufferdash.track("tool_used", {
tool: "ping-checker"
});The convenience API is equivalent:
window.bufferdash.trackTool("ping-checker", { mode: "tcp" });For interactive elements, declarative tracking emits exactly one tool_used event per activation:
<button data-bufferdash-tool="dns-lookup">Run lookup</button>BufferDash does not infer tool usage from arbitrary clicks. Each tracked application must mark its primary tool action or call trackTool() explicitly.
The tracker excludes form inputs, cookies, localStorage contents, passwords, URL fragments, and query strings by default. Add data-include-query only after auditing every tracked URL.
When TRUST_PROXY=true, BufferDash uses trusted Cloudflare or Vercel location headers when present. Cloudflare's Add visitor location headers managed transform supplies city and region without a separate lookup provider. Set IPINFO_TOKEN for server-side enrichment or fallback when appropriate. IPINFO_TIER=lite provides country and ASN data; core also provides city and region.
GeoIP sends visitor IPs to the configured provider. Leave the token empty if that does not fit your privacy policy.
LOCAL_ONLYAPP_URLBIND_ADDRESSTZDATABASE_URLandPOSTGRES_PASSWORDSESSION_SECRETandTRACKING_SECRETADMIN_EMAILandADMIN_PASSWORD_HASHTRUST_PROXYANONYMIZE_IPENFORCE_TRACKING_ORIGINIPINFO_TOKENandIPINFO_TIERENABLE_LOG_INGESTION,ENABLE_HTTP_INGESTION,ENABLE_HOST_INGESTION, andINGESTION_SECRETSERVER_METRICS_SOURCE=host|container|disabled(ENABLE_SERVER_METRICSis a temporary compatibility fallback)DATA_RETENTION_DAYS
- Hosted production rejects HTTP app URLs, placeholder secrets, missing bcrypt hashes, and weak database credentials.
- The app stays bound to loopback behind the HTTPS reverse proxy.
- PostgreSQL is not published on a host port.
- Admin sessions are signed, HTTP-only, SameSite cookies.
- UI mutations require CSRF tokens.
- Tracking requests are origin-checked and rate-limited.
- Query strings and fragments are excluded by default.
- Client-submitted IP, country, browser, OS, and device values are not trusted.
BufferDash can log IP addresses and user agents. Set ANONYMIZE_IP=true and disclose analytics collection in the privacy policy for every tracked site.