Replace the grep-docker-logs notifier panel with a per-node UP/DOWN stat
driven by the app's new tag=heartbeat log line (count_over_time over 20m;
0 beats => DOWN/red). Update the README now that the app emits heartbeats.
A containerized Alloy agent can't reach the host's 127.0.0.1, so even the
beta-local agent must push to beta's wg0 address (10.10.0.2:3100), not
127.0.0.1. Fix the beta example in the README and the agent compose header.
- Grafana served at dashboard.thermograph.org (the record now points at beta)
- Google OAuth (OIDC) login, env-gated (OAUTH_ENABLED + GOOGLE_CLIENT_ID/SECRET);
allow_sign_up=false so access is locked to pre-provisioned accounts, with a
break-glass local admin fallback
- README: Google Cloud OAuth client setup with the redirect URIs for both
Grafana and Forgejo, plus the Forgejo add-oauth command
A central Grafana + Loki stack (on beta) fed by a Grafana Alloy agent on
every node, replacing the old SSH-tailed single-host scripts/dashboard.py.
- docker-compose.yml: central Loki (mesh-only :3100) + Grafana (Caddy-fronted)
- loki/config.yml: single-binary, filesystem storage, 30-day retention
- alloy/config.alloy + docker-compose.agent.yml: per-node collector — every
container's stdout/stderr via the Docker socket, Caddy host logs, and the
app's structured JSON logs (errors/access/audit), each line tagged by node
- grafana/: auto-provisioned Loki datasource + a fleet-logs dashboard
(volume by service, error rate, upstream 429s, Caddy 5xx, notifier liveness,
live tail), with a per-node selector
- caddy-grafana.conf, README, .env.example