0001 GitOps apply model

accepted date 2024 (backfilled 2026-07-08) deciders jawn #adr
  • 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 apply comment to apply, automerge on success. Local terraform apply against remote state is forbidden.

      • Kubernetes state applies only through Flux (and ArgoCD for external-repo apps) on merge to main. kubectl apply is never used to author state.

      • NixOS hosts auto-rebuild from GitHub main; nixos-rebuild remains 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

ADR/0001 GitOps apply model — operators apply desired state; humans only merge

Architecture/Kubernetes

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).

Architecture/Terraform

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).

Runbooks/Kubernetes GitOps Change

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.

Runbooks/Terraform Change

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.

Architecture/GitOps

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.

Architecture

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.