The image creates DB_BACKUP_DIR owned by the app user, so an install that
runs it without the backups volume could write there, and every nightly and
pre-migration dump landed in the container's own layer. The next update
threw them away while the admin page, the boot line and the readiness card
called them kept on this server.
A dump directory now counts as kept only when it survives the container:
inside a container (Docker, Podman, Kubernetes, a container cgroup or an
overlay root) the directory must sit on a mount of its own that is not a
tmpfs, read from /proc/self/mountinfo with a device-number fallback;
outside one, a writable directory is a disk. Otherwise no dump is written
there: the nightly run uploads off-host only and records not_persistent,
the pre-migration dump is skipped with a warning, the boot line says the
directory is inside the container, the backups page stops promising local
dumps and ignores local-only ledger rows, and readiness fails with no
bucket and notes the bucket-only setup otherwise.
The Unraid template gains a path for the dumps, the Unraid and TrueNAS
pages say why it is needed, and the restore drill first runs the stack
without the volume and checks that nothing is kept or claimed.
The key backup sections become "Save the recovery kit": which keys the kit lists and why, the fingerprint of the token key, and the readiness card with its Backup health notification.
Fix two dead anchors (the MCP trust model, the README quick start) and the
statements that no longer match the app: a guardian can connect a managed
profile's services, the environment module is on by default and reaches the
air-quality host too, its readable location columns were dropped in 0409,
settings sections carry their current names, the Withings card lives on
/settings/integrations, the TrueNAS start period matches the image, the
deploy check names HEALTHLOG_PROD_URL, and the docs index describes what
self-hosting/ and integrations/ hold.
Every configured key id now has a canary in encryption_key_canaries,
checked at boot. A key that cannot open its canary, or existing data
written before the canary existed, puts the process in a refusal state:
every API route answers 503 encryption.key_mismatch, /api/health reports
reason encryption_key_mismatch, the pages render one explanation, and
neither the queue producer nor the worker starts. The process stays up
so the reason is visible instead of hiding in a crash loop.
The admin Encryption page gains a "Back up your encryption key" step:
key id and fingerprint (never the key), where the key lives per
platform, a check of a pasted copy that is compared and discarded, and
a confirmation bound to the active key id and fingerprint. The overview
gets a tile and admins get a dashboard banner while it is due.
HEALTHLOG_PLATFORM picks the platform the step opens on. Adds the
TrueNAS self-hosting page and key backup sections in the docs.
- geolite2: quote the real commented compose mount (./geolite2 to
/opt/geolite2, the GEOLITE2_DIR default, so no env var is needed for
the default path)
- getting-started: healthcheck probes /api/health, not /api/version;
the environment module reaches archive-api and geocoding-api
.open-meteo.com, relevant for egress allowlists
- mcp: the module is opt-in and off by default, but no longer the only
such module
- reverse-proxy: the Coach stream is SSE over plain HTTP, not
WebSockets; note that TRUST_PROXY_HOPS is not on the bundled compose
whitelist and must be added by hand
- scaling: /api/health healthcheck; worker liveness is in-memory and
invisible across a web/worker split; pool sizing now goes through
getConnectionBudget with DB_CONNECTION_LIMIT as the compose knob and
a 2-connection pg-boss share
- sso: the native SSO handoff shipped, OIDC_ONLY works with app builds
that carry it
- unraid: geo databases are baked in only when the build had a licence
key, or mounted; replaceable either way
Surface the load-bearing first-run vars in docker-compose.yml and the README
quick-start: secret generation, the SESSION_COOKIE_SECURE=false LAN note, the
single persistent volume, and a /api/version verify step. Add an Unraid
Community Applications template plus a NAS walkthrough covering the external
Postgres setup, and a Portainer app template referencing the compose stack.