# Fleet overlay templates The YAMLs under `cms-plugins-staging/` and `cms-plugins-production/` are the FluxCD manifests that drive each environment. They are **not** consumed from this repo — they live here as a versioned blueprint, intended to be copied into the workloads repo that Flux watches: ``` git.oleks.space/anton/helm-workloads ├─ cms-plugins-staging/ ← copy from deploy/fleet-overlay/cms-plugins-staging/ ├─ cms-plugins-production/ ← copy from deploy/fleet-overlay/cms-plugins-production/ └─ kustomization.yaml ← add both directories to `resources:` ``` See `../../DEPLOYMENT.md` for the full pipeline and the first-time setup checklist (deploy keys, sops secrets, Woodpecker secrets, DNS). ## Shape Each env directory contains five files, mirroring the emdash-kotkanagrilli layout in `~/projects/servers/fleet/apps/base/`: - `source.yaml` — `GitRepository` pointing at this repo on the matching branch (`staging` / `production`), restricted to `/deploy/helm` via the `ignore` rule so Flux only pulls the chart. - `helmrelease.yaml` — `HelmRelease` consuming the chart from `./deploy/helm` in that `GitRepository`. Pinned by digest (see image-automation.yaml). - `image-automation.yaml` — `ImageRepository` + `ImagePolicy` + `ImageUpdateAutomation`. Watches the floating `staging` / `production` tag in the Gitea OCI registry, resolves the current digest, and rewrites the digest setter in `helmrelease.yaml` (which is what actually makes `helm upgrade` see a change when CI retags the image). - `secrets.yaml` — the pod's env-var secret (`cms-plugins-{staging,production}-secrets`, in `kotkan`). The staging overlay's `secrets.yaml` additionally defines the shared SSH deploy key (`cms-plugins-deploy-key`, also in `kotkan` so the GitRepository `secretRef` resolves same-namespace); production references that same key by name and does NOT redefine it. **Templates here are NOT encrypted** — sops-encrypt them before pushing to anton-helm-workloads. - `kustomization.yaml` — bundles the above. ## Why this lives in two repos The chart (`deploy/helm/`) ships with the app — that way a chart change is reviewed and tagged alongside the code that depends on it. The HelmRelease references the chart as a path inside a `GitRepository`, not as an OCI artifact, so there's no "publish chart" step in CI. The HelmRelease itself lives in the workloads repo because that repo is the source of truth for what runs on the kotkanagrilli.fi subdomain pool. Same convention as the existing `kotkanagrilli/` (legacy WP) and `hello-kotkan/` entries there. ## Why two image automations share one branch Both `cms-plugins-staging` and `cms-plugins-production` define an `ImageUpdateAutomation` that checks out, commits to, and pushes the **same** `main` branch of `anton-helm-workloads` on the same `interval: 1m`. This is intentional and safe: - Each automation is scoped to a disjoint `update.path` (`./cms-plugins-staging` vs `./cms-plugins-production`), so they only ever rewrite the digest setter inside their *own* `helmrelease.yaml`. They never touch the same file. - `strategy: Setters` rewrites only the explicitly marked digest setter, not arbitrary YAML — there is no whole-file regeneration that could clobber a sibling's change. - The image-automation-controller serializes its git pushes and retries on a non-fast-forward rejection, so two automations landing commits on `main` in the same reconcile window resolve cleanly rather than racing. This mirrors the per-env automations under `~/projects/servers/fleet/apps/base/` for `emdash-kotkanagrilli-*`. The only deviation (justified in `image-automation.yaml`) is that these reuse the read-side `anton-helm-workloads` `GitRepository` as the write-back `sourceRef` instead of a dedicated image-automation source, because these workloads live in that same repo. Note for go-live: nothing here reconciles while the HelmReleases are `suspend: true` (Phase 0). These automations only begin writing back once the releases are deliberately resumed.