The homelab had reached the stage where I no longer knew what was running. Containers started by hand months ago, half of them with the run command lost to shell history, port numbers I had to docker ps to remember. The day I rebooted the host and spent twenty minutes reconstructing what was meant to come back up, I admitted it had to become a file.
Everything now lives in one docker-compose.yml. Not because Compose is clever, it's deliberately not, but because the whole stack being declared in one place I can read, diff, and commit to git is worth more than any feature. The host can burn down and I can bring the entire house back with one command.
The pattern that made it click was putting a reverse proxy in front of everything and giving the services a shared network. Traefik watches the Docker socket and configures itself from labels on each container, so adding a new service is a few lines, no editing a central config, no remembering which port was free.
version: "3.7"
services:
traefik:
image: traefik:v2.0
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- web
grafana:
image: grafana/grafana
restart: unless-stopped
volumes:
- grafana-data:/var/lib/grafana
labels:
- traefik.enable=true
- traefik.http.routers.grafana.rule=Host(`grafana.house`)
networks:
- web
networks:
web:
volumes:
grafana-data:
A few things I learned the boring way. Name your volumes and never bind-mount data into a path you might docker-compose down -v by accident, because that flag deletes volumes and it does not ask twice. Set restart: unless-stopped on everything you want surviving a reboot, but not always, or a container in a crash loop will fight you. And pin image tags. latest is a promise that something will silently change underneath you on a Tuesday, and you will spend the evening working out which thing.
The real win isn't any one service, it's that the config is now reviewable. When I add Pi-hole or swap a database image, it's a commit with a diff I can read before applying. The homelab stopped being a pile of pets I tended by hand and became a thing I could describe in a file, which means future me can understand it without archaeology. That, more than uptime, is what self-hosting at home should buy you.