personal · infrastructure · 2026-09-12

Status page and privacy-first usage analytics for a self-hosted server

It probes 15 services and 3 bots every 30 s using up to five signals each, keeps 90 days of history, and adds first-party analytics that count only active screen time. Zero npm dependencies. Built and deployed on 2026-09-12.

problemconstraintswhat I builtoutcomestackredacted screenshot

Problem

Fifteen services and three bots ran on one box with no view of their health, so an outage was found only by using the thing that had broken. The analytics half answers a separate question: what to build next.

Constraints

What I built

fig 1. Two small services with no dependencies, behind one trust boundary.

Outcome

dateresult
2026-09-12Deployed: 18 of 18 checks healthy, certificate issued, 401 without credentials
2026-09-12A stopped container turned its row red within five seconds
2026-09-12The first deploy failed on a reverse-proxy log-ownership trap and the existing sites stayed up. Fixed
2026-09-12Analytics deployed. A real visit was stored with identity attributed server-side

15 services + 3 bots · 30 s interval · 90-day hourly history · 180-day analytics retention · 0 npm dependencies

Stack

Node.js 22node:sqlitesystemdDockerCaddyinline SVG

Redacted screenshot

fig 2. Mock dashboard with generic names and invented numbers. Hosts, units, ports and IPs are redacted.
evidence: brain/projects/status-page.md · status-page/context.md · brain/cv.md