
One URL for Everything: the Family Dashboard
By March the platform had grown past the point where “just remember the URL” worked as a family navigation strategy. Mail, webmail, calendar, password manager on the way, admin panels for me. The fix is old-fashioned and effective: a start page. Homepage now gives the family a start page: every service as a tile with live status, grouped sensibly, behind the same single sign-on as everything else.
The fastest epic of the project
The dashboard epic completed in a single session: five stories, deployed to production, verified. Not because it was trivial, but because by March the platform had patterns. The Ansible role is a near-copy of the blog role: upstream container, Tailscale sidecar, Traefik router, numbered playbook. The Terraform story turned out to be verification-only, because apps1 and its wiring already existed; the TLS story likewise confirmed rather than created. Two of five stories changed zero code and just proved things worked.
I want to defend that explicitly, because process purists would call those stories padding. They weren’t: each one produced a verification script and a concrete answer to “is this actually configured the way we believe?”. Honest verification beats artificial busywork, and it also beats skipping the check. The retrospective’s phrasing became a team agreement: story boundaries serve the work, not the other way around.
The dashboard itself is deliberately family-shaped: services in tidy groups, and every tile checked by an HTTP monitor so a dead service shows as dead instead of luring someone into a broken login page. The whole thing sits behind Authelia’s forward auth with two-factor, because a page enumerating every service you run, with status, is a reconnaissance gift if left open.
Status tiles without the socket
The interesting engineering hid in one feature: container status. Homepage can show Docker state per tile, running or stopped or unhealthy, but the obvious implementation mounts the Docker socket into the dashboard container. The Docker socket is root on the host wearing a REST costume. An internet-facing dashboard with root on the host is not a tile, it’s a liability.
The design that shipped, a couple of months after the dashboard itself: every host runs a docker-socket-proxy, a filtering proxy that exposes a read-only subset of the Docker API. Each proxy sits behind its own Tailscale sidecar and answers at dockerproxy-<host>.cumps.internal:2375 on the mesh. No host publishes port 2375 on any real interface; ss -ltnp on the hosts shows nothing listening. It isn’t quite hermetic. The proxy shares the sidecar’s network namespace, and that namespace also holds an eth0 on the host’s default Docker bridge, so a container already running on the same host could reach it. It is not reachable from the internet or the LAN, and on the tailnet side the Headscale ACL is what keeps it honest. Homepage, from apps1, reads container status for all five hosts across the tailnet. Read-only and per-host: the blast radius of a compromised dashboard went from “root everywhere” to “reads container metadata”, which still isn’t nothing, but it no longer keeps me up at night.
The recurring guest
This epic also forced a reckoning with an old acquaintance. The sidecar race condition, where recreating a Tailscale sidecar leaves its service container pointing at a dead network namespace until someone runs docker restart, hit again during both the Homepage and Authelia deploys. Third epic in a row. The workaround was always a manual restart, and workarounds that survive three epics stop being workarounds and start being unpaid debt.
The decision came out of the retrospective as another agreement: known issues get fixed before they compound, and this one got fixed properly in the sidecar role before the next epic started. The socket proxies later gained their own self-healing for a related failure mode, because anything whose network lives in another container’s namespace has opinions about restarts. The full sidecar saga gets its own post in the fleet era; consider this the second act.
Next week: passwords leave the browser’s keychain and move into the family’s own vault.
You May Also Like

Email for a Nine-Year-Old
Family accounts on self-hosted infrastructure: onboarding, self-service passwords, 2FA, and what parental visibility looks like in Sieve.

Traefik as the Front Door
One reverse proxy design for the whole fleet, with its routing table in Valkey and its certificates feeding the mail server.

A Mesh of My Own: Headscale and Container Sidecars
Private networking between data centers with a self-hosted control plane, and a Tailscale sidecar for every container.



