Ramblings of an aging IT geek
← Ramblings of an aging IT geek
homelab

one compose file to run the house

Consolidating the household's self-hosted services into a single Docker Compose stack, and the trade-offs of putting all the eggs in one file.

A server rack

The house runs on about a dozen small services. DNS-level ad blocking, a media server, a few dashboards, a thing that watches the solar inverter, the usual homelab accretion. For a long time each lived its own life: this one started by hand, that one a half-remembered docker run in my shell history, another a unit file I'd forgotten the syntax of. When the server rebooted I spent twenty minutes rediscovering how to bring it all back. So I put the whole house in one Compose file.

why compose and not something cleverer

The honest reason is that I don't have a household-scale problem. Kubernetes is a wonderful answer to a question my home does not ask. I have one machine and a dozen containers that need to start in a sane order and find each other on a network. That is precisely the job Docker Compose was built for, and reaching past it for an orchestrator would be solving for a scale I'll never reach at home.

Everything now lives in one docker-compose.yml in a git repo. The services, their volumes, their networks, the lot. docker compose up -d and the house comes alive. docker compose pull && docker compose up -d and everything updates. The whole configuration is one file I can read top to bottom, version, and roll back.

A homelab setup

the bits worth getting right

A few things separated "works" from "works when I'm on holiday and the power blips."

  • restart: unless-stopped on everything. The server reboots, the stack comes back, I don't get a phone call. This is the single most valuable line in the file.
  • Named volumes, not bind mounts to random paths. When the data location is explicit and declared, backing it up is one job rather than a treasure hunt across the filesystem.
  • A .env file for secrets, kept out of git. The Compose file is in version control; the API keys and passwords are not. The repo has a committed .env.example so future-me knows what to fill in.
  • An internal network, only the front door exposed. The services talk to each other over a private Compose network and reach me through a single reverse proxy. The only published ports are the ones that genuinely need to face the LAN.

the obvious objection

Yes, it's one file and one machine, and that's a single point of failure for the whole house. If the box dies, everything dies together. I've made my peace with that for two reasons. First, the entire state is a git repo plus a backup of the named volumes, so recovery is git clone, restore volumes, compose up, and I'm back. Second, this is a home, not a hospital. If the ad-blocking is down for an hour while I restore, the consequence is some adverts and a mildly annoyed family, not an incident.

What I've actually bought is legibility. The whole household stack is one readable file, in git, that starts with one command and comes back by itself after a reboot. The midden of forgotten docker run commands is gone. When something breaks I know where to look, because there is now exactly one place to look, and that alone has been worth the afternoon it took.