Skip to content
Ali Akbari
Menu

ADR-0020 · accepted · 12 October 2026

Analytics dashboard at stats.aliakbari.dev behind Cloudflare Access

Context

ADR-0018 made the Umami dashboard reachable only through an SSH tunnel. The owner wants it at https://stats.aliakbari.dev, from any browser, without weakening what ADR-0018 protects: visitor data stays private and the dashboard is not exposed to the internet. Umami 3.4.0 has open upstream vulnerabilities (docs/testing.md), so its login page must not be the only barrier.

Decision

  • Cloudflare Access (Zero Trust, free plan) protects the hostname. Only the owner's e-mail is admitted (one-time code); a second Access application bypasses Access for /.well-known/acme-challenge/ only, so certificate renewals work unattended.
  • The origin verifies Access's token. nginx sends every request through auth_request to access-gate, a small Go service (services/api/cmd/access-gate, shipped in the signed API image). It accepts only RS256 tokens signed by a key of the team's published key set, with the application's audience, the team's issuer, a valid time window, type app, and an allowed e-mail. A request that reaches the server without passing through Access (sent straight to its address, or with a forged header or cookie) gets 403. Without configuration, or before keys are loaded, it refuses everything.
  • Umami's own login remains as the third layer; the SSH tunnel (port 8091) remains as a fallback when Cloudflare is unavailable.
  • Own certificate lineage. stats.aliakbari.dev has its own Let's Encrypt certificate, loaded per handshake, so a renewal problem or a missing certificate affects only the dashboard; the site's certificate and nginx's startup do not depend on it. The renewal hook fixes key permissions for whichever lineage renewed.
  • The hostname is classified as internal by the ledger (int), so dashboard use never appears in the site's published operational figures. The WAF is not applied: everything that reaches Umami has passed Access and the token check.

Consequences

  • The dashboard is reachable from any browser after an e-mail code, and not by anyone else.
  • access-gate needs outbound HTTPS to <team>.cloudflareaccess.com (it is on the edge network); every other application container still has no internet route.
  • Setup needs the owner once: a DNS record, two Access applications, a certificate (sudo), and the Access settings in /srv/aliakbari/secrets/access.env (runbook, "Analytics dashboard").

Source: docs/adr/0020-analytics-dashboard-behind-cloudflare-access.md

← All decisions