0001 GitOps apply model
Context
The homelab spans four layers with different tooling (Terraform, Kubernetes manifests, NixOS). Applying changes by hand from a laptop invites drift, races between operators, un-reviewed changes, and state/lock corruption. There should be exactly one way a change reaches production, and it should leave an audit trail.
Decision
Git is the source of truth; operators apply, humans merge:
Terraform applies only through Atlantis on the PR: autoplan on open,
atlantis applycomment to apply, automerge on success. Localterraform applyagainst remote state is forbidden.Kubernetes state applies only through Flux (and ArgoCD for external-repo apps) on merge to
main.kubectl applyis never used to author state.NixOS hosts auto-rebuild from GitHub
main;nixos-rebuildremains the manual apply path but anything not merged reverts on the next upgrade cycle.
Consequences
Every production change has a PR, a plan/diff, and a reviewer (even if that reviewer is future-you).
Lock contention and state races disappear — Atlantis is the only writer.
Local workflows become inspection-only (
terraform init -backend=false && validate,flux get,kubectl get), which also means CI and web sessions need no production credentials.Emergency fixes are slower by one PR; that is the accepted cost.
Bootstrap remains a chicken-and-egg exception:
clusters/<site>/bootstrap/Terraform installs Flux itself.
Links
Linked references 7
ADR/0001 GitOps apply model — operators apply desired state; humans only merge
Merge to main → Flux reconciles. Never kubectl apply to author state; kubectl and flux are for inspection or forcing a sync (ADR/0001 GitOps apply model).
Layer 3. All Terraform root modules live under terraform/; each is standalone. Applies run through Atlantis on the PR — never locally (ADR/0001 GitOps apply model).
Use this when changing manifests under clusters/ or inspecting Flux deployment state. Architecture lives in Architecture/Kubernetes and the apply model is ADR/0001 GitOps apply model.
Use this when changing Terraform under terraform/ or cluster bootstrap Terraform under clusters/<site>/bootstrap/. Background lives in Architecture/Terraform and the apply model is ADR/0001 GitOps apply model.
How a change actually ships, by layer. The common thread: author desired state in git, let an operator apply it. Rationale in ADR/0001 GitOps apply model.
Terraform root modules under terraform/: UniFi network fabric, Cloudflare DNS/tunnels, Tailscale, GCP organization and projects, Google Workspace, and Vault. Applies run through Atlantis on the PR — see ADR/0001 GitOps apply model.