Documentation and Automation: Repo as Blueprint

I treat the homelab repo as the single source of truth. Everything that can be described or configured in files lives there, with placeholders for secrets. Here’s how that works and what I run to keep it honest.


Why it’s worth it


Placeholders and values

Every doc and config that needs a hostname, IP, domain, or path uses a placeholder like <HOST_01_IP>, detellem.com, <NGINX_VIP>, <SUBNET>. The names match keys in a values file. I keep one file, values.yaml.local, with the real values (gitignored). No other file in the repo contains those values.

When I need to:


Audit: does live match the repo?

I run an audit script that SSHs into the VMs (and optionally the router, APs, TrueNAS, Windows) and:

So “make generate-configs, then compare live to dist” tells me if I’ve edited something on the server and not updated the repo (or the other way around). I run a “thorough” mode periodically; it takes a few minutes and spits out a report. Drift isn’t automatically fixed—I either change the server to match the repo or update the repo to match the server, then re-run.


What lives in the repo

No Ansible or Terraform; just “generate from template + copy + reload” and “audit to compare.” Simple enough that I can fix it when it breaks.


Workflow in practice

  1. Edit a doc or config in the repo (with placeholders).
  2. Run make test so I don’t commit a value from values.yaml.local.
  3. When I’m ready to deploy that config, run make generate-configs, then copy the relevant files from dist/ to the right hosts and reload (e.g. nginx, systemd).
  4. Periodically run the audit (quick or thorough) to see if anything’s out of sync or broken.

That’s it. The payoff is that the homelab is describable and checkable; the cost is keeping the repo up to date when I change things by hand (or changing by hand less and deploying from the repo more).

← Security | Back to index | Next: Getting started →