homelab-compose
What it does
This is the whole configuration for the small server under my desk that runs things I use daily: Jellyfin for media, Paperless for scanned documents, a Gitea mirror of a few of my repos, Grafana + Prometheus + node_exporter for graphs nobody but me cares about, and Uptime Kuma to tell me which of these is broken.
It is not a “homelab framework.” It is a bunch of docker-compose.yml files grouped by purpose, a Caddyfile that reverse-proxies them with Let’s Encrypt, and a scripts/ folder with cron-driven backup and prune logic.
Why I made it
I kept rebuilding the same setup every 18 months when I moved or bought a new disk. This time I wrote it down.
Keeping it in a repo also forces me to think twice before doing “just one docker run” — which used to be how half my homelab historically accumulated.
How it works
Each service folder has its own docker-compose.yml. A top-level Makefile has targets like make media up, make infra pull, make backup run. Caddy reverse-proxies based on subdomain. Backups are a restic call with a local repo + Backblaze B2 offsite, scheduled via systemd timer, retained 7 daily / 4 weekly / 6 monthly.
Secrets live in a secrets/ directory that’s gitignored. There’s a secrets.example/ with a README telling me (future me) exactly what to put where.
Install
# copy the tree from /src/homelab-compose/ into ~/homelab
cd ~/homelab
cp .env.example .env # fill these in
make infra up
make media up
Roadmap
- Swap Uptime Kuma for something I can also use to page myself (probably ntfy + a Prometheus alertmanager config)
- Figure out a sensible zfs snapshot strategy and stop pretending
resticis enough - Maybe move Caddy to Traefik, though honestly Caddy is great and I keep failing to justify this migration