Canonical template for deploy-* GitOps repositories — the manifests-only
half of a hardened deployment pipeline. A deploy-* repo contains nothing but
Kustomize manifests for one application and the CI that proves they are safe to
reconcile onto a cluster. It owns what runs and how it is configured; it does
not build the image and it does not configure the cluster.
Why this exists. It is the missing piece between the image-build templates (
chiseled-application-template,ubi9-application-template— which produce a signed, digest-pinned OCI image) and the cluster platform (which provides the namespace, RBAC, network envelope, and admission policy). This template encodes the contract that lets those two halves meet safely.
- Kustomize base + overlay skeleton with a minimal, PSS-restricted example workload that renders and validates out of the box.
- A merge-gating
validate.yamlthat enforces four hard rules: it renders, it passeskubeconform -strict, every image is@sha256:-digest-pinned, and no plaintext secret material is committed. - A parameterized image contract (
EXPECTED_IMAGE) so CI asserts you ship exactly the public image you mean to, with noimagePullSecrets. - Deny-all
.gitignorewith credential re-ignores — a secret cannot be committed by accident. - Diataxis docs + repo ADRs covering the lifecycle decisions every deploy repo faces: Kustomize-vs-Helm, digest pinning, temporary bootstrap states, internal-before-external exposure, and deliberate retirement.
-
Click Use this template → create
deploy-<your-app>(lowercase,^deploy-[a-z0-9-]+$). The repo name becomes the cluster tenant namespace. -
Replace the example container in
kubernetes/base/deployment.yamlwith your application, and set the image inkubernetes/base/kustomization.yamlto your published, signed image — pinned by@sha256:digest. -
Set
EXPECTED_IMAGEin.github/workflows/validate.yamlto your image (e.g.ghcr.io/<org>/<app>), and rename thedeploy-examplenamespace inbase/kustomization.yamlto match your repo. -
Add any app-specific egress to
kubernetes/base/networkpolicy.yaml(the cluster grants only default-deny + DNS). -
Render locally and push a PR:
kustomize build kubernetes/overlays/talos-cluster
Not published yet? Use the blocking-placeholder convention: reference
your-image:REPLACE-WITH-SIGNED-DIGESTso the digest-pin gate keeps the PR red until the real signed digest is substituted. CI red == "not ready", visibly and undeniably — better than a silent tag.
image-builder repo this repo (deploy-*) cluster repo
────────────────── ──────────────────── ────────────
chiseled-/ubi9- kubernetes/ manifests talos-cluster
application-template ──▶ + digest pin ──▶ Flux wiring,
builds + signs the + validate.yaml gate tenant namespace,
OCI image (SBOM, (no image build, RBAC, NetworkPolicy
provenance, cosign) no cluster config) envelope, Kyverno
Each repo owns one concern and one trust boundary. The deploy repo proves its manifests are safe before admission; the cluster proves the image is signed at admission. See docs/explanation/architecture.md.
A deploy-* repo is admitted by automated tenant onboarding when it satisfies a
small, explicit contract — chiefly: it exposes
kubernetes/overlays/talos-cluster/kustomization.yaml, every image is
digest-pinned, and all resources are namespace-scoped and PSS-restricted. The
cluster generates the namespace, a namespace-scoped reconciler ServiceAccount,
a default-deny network envelope, and the Flux wiring. The full, current contract
is documented in docs/reference/admission-contract.md.
- Manifests only. No unseal keys, recovery keys, tokens, TLS private keys, or registry credentials are ever committed. Secrets are delivered out-of-band (SOPS, cluster-side) — see SECURITY.md.
- Digest-pinned + signature-verified. This repo pins images by digest; the cluster verifies the signature at admission (Kyverno). Two enforcement points, two owners — see ADR-0002.
- Least privilege. The reconciler ServiceAccount is namespace-scoped; this repo contains no cluster-scoped resources (no ClusterRole/CRD/admission).
| Genre | Start here |
|---|---|
| Explanation | architecture.md — the model and trust boundaries |
| How-to | onboard-to-a-cluster.md |
| Reference | admission-contract.md · validate-gates.md |
| Tutorial | derive-a-deploy-repo.md |
| Decisions | decision-records/ |
MIT.