fix(deploy): align fleet-overlay blueprint with the live kotkan deploy
ci/woodpecker/push/container Pipeline was successful

The deploy/fleet-overlay templates had drifted from what actually runs in
anton-helm-workloads (verified live + against the emdash-kotkanagrilli
reference). Canonical design co-locates everything in the `kotkan` namespace:

- source.yaml: GitRepository flux-system -> kotkan, so the HelmRelease
  chart sourceRef resolves same-namespace (no cross-namespace ref).
- secrets.yaml: deploy-key Secret -> kotkan, defined once in the staging
  overlay; dropped the duplicate definition from the production overlay
  (production references the shared key by name).
- image-automation.yaml: IUA write-back sourceRef
  anton-workloads-image-automation/flux-system -> anton-helm-workloads/kotkan
  (the existing read source already has push access).
- README.md / DEPLOYMENT.md: namespace + ownership docs corrected.
This commit is contained in:
Oleks
2026-06-02 03:24:52 +03:00
parent bfc6a65638
commit bdc43bb1d6
8 changed files with 58 additions and 56 deletions
+1 -1
View File
@@ -127,7 +127,7 @@ Each env has two distinct Secrets:
| Secret | Namespace | Purpose | | Secret | Namespace | Purpose |
|---|---|---| |---|---|---|
| `cms-plugins-deploy-key` | `flux-system` | SSH deploy key for Flux to clone `cms-plugins` (one pair shared between staging + production — same key reads both branches). | | `cms-plugins-deploy-key` | `kotkan` | SSH deploy key for Flux to clone `cms-plugins` (one pair shared between staging + production — same key reads both branches). Defined once in the staging overlay; co-located with the GitRepositories in `kotkan` so the `secretRef` is same-namespace. |
| `cms-plugins-<env>-secrets` | `kotkan` | Env vars the pod consumes via `existingSecret`. Required key: `EMDASH_ENCRYPTION_KEY`. | | `cms-plugins-<env>-secrets` | `kotkan` | Env vars the pod consumes via `existingSecret`. Required key: `EMDASH_ENCRYPTION_KEY`. |
To rotate a credential: To rotate a credential:
+7 -5
View File
@@ -30,11 +30,13 @@ layout in `~/projects/servers/fleet/apps/base/`:
tag in the Gitea OCI registry, resolves the current digest, and rewrites tag in the Gitea OCI registry, resolves the current digest, and rewrites
the digest setter in `helmrelease.yaml` (which is what actually makes the digest setter in `helmrelease.yaml` (which is what actually makes
`helm upgrade` see a change when CI retags the image). `helm upgrade` see a change when CI retags the image).
- `secrets.yaml` — two Secrets per env: the SSH deploy key Flux uses to - `secrets.yaml` — the pod's env-var secret
clone this repo (`cms-plugins-deploy-key`, in `flux-system`), and the (`cms-plugins-{staging,production}-secrets`, in `kotkan`). The staging
pod's env-var secret (`cms-plugins-{staging,production}-secrets`, in overlay's `secrets.yaml` additionally defines the shared SSH deploy key
`kotkan`). **Templates here are NOT encrypted** — sops-encrypt them (`cms-plugins-deploy-key`, also in `kotkan` so the GitRepository
before pushing to anton-helm-workloads. `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. - `kustomization.yaml` — bundles the above.
## Why this lives in two repos ## Why this lives in two repos
@@ -41,11 +41,14 @@ spec:
# tag is reassigned (without digest, tag stays `production` literal and # tag is reassigned (without digest, tag stays `production` literal and
# helm upgrade is a no-op). # helm upgrade is a no-op).
# #
# NOTE: `sourceRef` must reference a GitRepository that points at # NOTE: `sourceRef` is the WRITE-back target — a GitRepository (with a
# THIS workloads repo (anton-helm-workloads) with write access. If it # write-capable deploy key) pointing at the workloads repo this manifest
# doesn't exist yet, create one alongside this manifest. The # lives in. We reuse the same `anton-helm-workloads` GitRepository in
# emdash-kotkanagrilli equivalent uses `oleks-fleet-image-automation` # `kotkan` that Flux already uses to READ these workloads; its deploy key
# because its HelmReleases live in the fleet repo. # has push access, so IUA commits the pinned digest straight back to
# `main`. (The emdash-kotkanagrilli reference instead uses a dedicated
# `oleks-fleet-image-automation` source because its workloads live in the
# fleet repo — same idea, different repo.)
apiVersion: image.toolkit.fluxcd.io/v1 apiVersion: image.toolkit.fluxcd.io/v1
kind: ImageUpdateAutomation kind: ImageUpdateAutomation
metadata: metadata:
@@ -55,8 +58,8 @@ spec:
interval: 1m interval: 1m
sourceRef: sourceRef:
kind: GitRepository kind: GitRepository
name: anton-workloads-image-automation name: anton-helm-workloads
namespace: flux-system namespace: kotkan
git: git:
checkout: checkout:
ref: ref:
@@ -1,43 +1,25 @@
# Two secrets per environment: # Secret for the production environment:
# 1. cms-plugins-deploy-key — Flux's SSH key for cloning the production branch # cms-plugins-production-secrets — env vars consumed by the pod via the
# of cms-plugins (only `read` on this Gitea repo).
# One pair is shared between production + production;
# commit it under whichever env directory is
# applied first.
# 2. cms-plugins-production-secrets — env vars consumed by the pod via the
# chart's `existingSecret`. EMDASH_ENCRYPTION_KEY # chart's `existingSecret`. EMDASH_ENCRYPTION_KEY
# is required; everything else is optional. # is required; everything else is optional.
# #
# These are TEMPLATES — encrypt them with sops before committing to the # NOTE: the Flux SSH deploy key (cms-plugins-deploy-key) is NOT defined here.
# It is a single shared key defined once in the staging overlay's secrets.yaml
# (namespace `kotkan`); this env's source.yaml references it by name. Defining
# it again here would create a duplicate Secret (same name + namespace) with
# last-write-wins ambiguity. Mirrors the emdash-kotkanagrilli reference.
#
# This is a TEMPLATE — encrypt it with sops before committing to the
# anton-helm-workloads repo: # anton-helm-workloads repo:
# #
# sops --encrypt --age <recipient-key> secrets.yaml > secrets.enc.yaml # sops --encrypt --age <recipient-key> secrets.yaml > secrets.enc.yaml
# mv secrets.enc.yaml secrets.yaml # mv secrets.enc.yaml secrets.yaml
# #
# Generation: # Generation:
# ssh-keygen -t ed25519 -f /tmp/cms-plugins-deploy -N ""
# → upload /tmp/cms-plugins-deploy.pub to Gitea: Repo Settings → Deploy
# Keys → "cms-plugins Flux deploy", read-only.
# openssl rand -hex 32 → EMDASH_ENCRYPTION_KEY (one per env, do not reuse). # openssl rand -hex 32 → EMDASH_ENCRYPTION_KEY (one per env, do not reuse).
--- ---
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret
metadata:
name: cms-plugins-deploy-key
namespace: flux-system
type: Opaque
stringData:
identity: |
-----BEGIN OPENSSH PRIVATE KEY-----
REPLACE_WITH_PRIVATE_KEY
-----END OPENSSH PRIVATE KEY-----
identity.pub: |
ssh-ed25519 REPLACE_WITH_PUBLIC_KEY flux@cms-plugins
known_hosts: |
git.oleks.space REPLACE_WITH_HOST_KEY
---
apiVersion: v1
kind: Secret
metadata: metadata:
name: cms-plugins-production-secrets name: cms-plugins-production-secrets
namespace: kotkan namespace: kotkan
@@ -6,7 +6,11 @@ apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository kind: GitRepository
metadata: metadata:
name: cms-plugins-production name: cms-plugins-production
namespace: flux-system # Co-located with the HelmRelease in `kotkan` so the chart sourceRef is a
# same-namespace reference (Flux commonly disables cross-namespace source
# refs). Matches the emdash-kotkanagrilli reference overlay and the live
# deploy in anton-helm-workloads.
namespace: kotkan
spec: spec:
interval: 1m0s interval: 1m0s
url: ssh://git@git.oleks.space/oleks/cms-plugins.git url: ssh://git@git.oleks.space/oleks/cms-plugins.git
@@ -41,11 +41,14 @@ spec:
# tag is reassigned (without digest, tag stays `staging` literal and # tag is reassigned (without digest, tag stays `staging` literal and
# helm upgrade is a no-op). # helm upgrade is a no-op).
# #
# NOTE: `sourceRef` must reference a GitRepository that points at # NOTE: `sourceRef` is the WRITE-back target — a GitRepository (with a
# THIS workloads repo (anton-helm-workloads) with write access. If it # write-capable deploy key) pointing at the workloads repo this manifest
# doesn't exist yet, create one alongside this manifest. The # lives in. We reuse the same `anton-helm-workloads` GitRepository in
# emdash-kotkanagrilli equivalent uses `oleks-fleet-image-automation` # `kotkan` that Flux already uses to READ these workloads; its deploy key
# because its HelmReleases live in the fleet repo. # has push access, so IUA commits the pinned digest straight back to
# `main`. (The emdash-kotkanagrilli reference instead uses a dedicated
# `oleks-fleet-image-automation` source because its workloads live in the
# fleet repo — same idea, different repo.)
apiVersion: image.toolkit.fluxcd.io/v1 apiVersion: image.toolkit.fluxcd.io/v1
kind: ImageUpdateAutomation kind: ImageUpdateAutomation
metadata: metadata:
@@ -55,8 +58,8 @@ spec:
interval: 1m interval: 1m
sourceRef: sourceRef:
kind: GitRepository kind: GitRepository
name: anton-workloads-image-automation name: anton-helm-workloads
namespace: flux-system namespace: kotkan
git: git:
checkout: checkout:
ref: ref:
@@ -1,9 +1,13 @@
# Two secrets per environment: # Secrets for the staging environment:
# 1. cms-plugins-deploy-key — Flux's SSH key for cloning the staging branch # 1. cms-plugins-deploy-key — Flux's SSH key for cloning cms-plugins (only
# of cms-plugins (only `read` on this Gitea repo). # `read` on this Gitea repo). ONE pair is shared
# One pair is shared between staging + production; # between staging + production and is defined HERE
# commit it under whichever env directory is # (staging) only — the production source.yaml
# applied first. # references it by name. Both GitRepositories and
# this Secret live in `kotkan`, so the secretRef
# resolves same-namespace. (Mirrors the
# emdash-kotkanagrilli reference, where the shared
# deploy key is defined once in the staging overlay.)
# 2. cms-plugins-staging-secrets — env vars consumed by the pod via the # 2. cms-plugins-staging-secrets — env vars consumed by the pod via the
# chart's `existingSecret`. EMDASH_ENCRYPTION_KEY # chart's `existingSecret`. EMDASH_ENCRYPTION_KEY
# is required; everything else is optional. # is required; everything else is optional.
@@ -24,7 +28,7 @@ apiVersion: v1
kind: Secret kind: Secret
metadata: metadata:
name: cms-plugins-deploy-key name: cms-plugins-deploy-key
namespace: flux-system namespace: kotkan
type: Opaque type: Opaque
stringData: stringData:
identity: | identity: |
@@ -6,7 +6,11 @@ apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository kind: GitRepository
metadata: metadata:
name: cms-plugins-staging name: cms-plugins-staging
namespace: flux-system # Co-located with the HelmRelease in `kotkan` so the chart sourceRef is a
# same-namespace reference (Flux commonly disables cross-namespace source
# refs). Matches the emdash-kotkanagrilli reference overlay and the live
# deploy in anton-helm-workloads.
namespace: kotkan
spec: spec:
interval: 1m0s interval: 1m0s
url: ssh://git@git.oleks.space/oleks/cms-plugins.git url: ssh://git@git.oleks.space/oleks/cms-plugins.git