# 05 — GitOps & Delivery Serves: **R-GITOPS-01..03**, **R-PLAT-02/04**, **R-ENV-02**. Related: [ADR-0004 (Flux)](../decisions/adr-0004-gitops-flux.md). ## Model Pull-based GitOps with **Flux CD**. The cluster continuously reconciles its state from git. Git is the single source of truth; the cluster conforms to git, not the reverse (R-GITOPS-01). Drift is detected and corrected automatically (R-GITOPS-03). ## Repository layout (the implementation repo, created in a later phase) > This spec repo (`home-network-k3s`) holds intent. The **implementation** repo(s) hold the > reconciled manifests. Proposed structure: ``` platform/ ← cluster-wide platform services (Flux-managed) cilium/ ← CNI, egress gateway, network baseline longhorn/ ← storage cert-manager/ ← TLS issuers + ClusterIssuer externaldns/ ← DNS automation gateway/ ← Gateway API + listeners/TLS monitoring/ ← kube-prometheus-stack, Loki, Alloy, Alertmanager velero/ ← backup/DR kubevirt/ ← KubeVirt + CDI image-automation/ ← Flux image update automation config apps/ ← application workloads, one dir per service plex/ sonarr/ radarr/ jackett/ seerr/ pihole/ nextcloud/ minecraft/ unifi/ semaphore/ kasm/ gitea/ qbittorrent/ catalog/ ← ServiceDefinition entries (the onboarding surface) clusters/ dev/ ← Flux entrypoint + dev overlay/vars prod/ ← Flux entrypoint + prod overlay/vars (design-only) ``` - **Kustomize overlays** (or equivalent) express environment differences (R-ENV-02). Base is shared; `clusters/dev` and `clusters/prod` supply scoped values only. - **HelmReleases** (Flux) wrap upstream charts (Cilium, Longhorn, cert-manager, kube-prometheus- stack, etc.); app workloads use charts where good ones exist, otherwise plain manifests. ## The onboarding surface: ServiceDefinition (R-GITOPS-02) Onboarding a service = adding one **ServiceDefinition** under `catalog/`. It is the operator-facing abstraction that the platform compiles into the concrete resources (Deployment/VM, PVCs, NetworkPolicies, HTTPRoute, Certificate, DNS record, ServiceMonitor, update policy). See [`13-service-catalog.md`](13-service-catalog.md) for the schema. Intent lives in one place; the platform renders the rest. ## Reconciliation flow 1. Operator opens a PR against the implementation repo (new/updated ServiceDefinition or platform change). 2. CI validates (lint, policy checks, schema validation, dry-run/build). 3. Merge to the tracked branch. 4. Flux reconciles: applies manifests, reports status, corrects drift on an interval. 5. Health/rollout status surfaces in the C2 UI ([12](12-command-center-ui.md)) and alerts on failure ([10](10-observability-and-alerting.md)). ## Secrets in GitOps Secrets are committed **encrypted** with **SOPS + age**; Flux decrypts them in-cluster at reconciliation. No plaintext secret ever lands in git. See [`07-security-and-secrets.md`](07-security-and-secrets.md) and [ADR-0007](../decisions/adr-0007-secrets-sops-age.md). ## Automated updates interplay (R-UPD-*) GitOps and hands-off updates coexist: - **Container image tags** advance automatically via **Flux image-update-automation** driven by per-service **image policies** (semver range / stable channel) — the controller resolves and reconciles the new version with **no human-authored change** (R-UPD-02). - **Helm chart / manifest version bumps** are proposed by **Renovate** with auto-merge for allowed update classes. Full detail and the "is an automated commit a GitOps change?" nuance is in [`11-automated-updates.md`](11-automated-updates.md) and [ADR-0009](../decisions/adr-0009-automated-image-updates.md). ## Bootstrap & recovery - Flux is bootstrapped onto a fresh cluster by the Ansible handoff ([02](02-environments-and-provisioning.md)). - Because desired state is in git and data is on Longhorn/backups, a rebuilt cluster reconverges by re-bootstrapping Flux and restoring volumes ([04](04-storage-and-state.md)). ## Guardrails - No `kubectl apply` of app state by hand — everything flows through git/Flux (R-GITOPS-01, click- ops-never per [AGENTS.md](../AGENTS.md)). - Reconciliation errors and drift are **alerting conditions** (R-OBS-04). - Base config is never forked per environment (R-ENV-02). ## Acceptance gates - Adding a ServiceDefinition PR results in a fully wired service (compute, storage, policy, TLS, DNS, monitoring) with no manual steps beyond the merge. - Manually mutating a live resource is auto-reverted by Flux (drift correction proven). - The same base config renders correctly for both dev and prod overlays.