Skip to content

NWarila/deploy-application-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

deploy-application-template

Validate manifests License: MIT Use this template

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.


What you get

  • Kustomize base + overlay skeleton with a minimal, PSS-restricted example workload that renders and validates out of the box.
  • A merge-gating validate.yaml that enforces four hard rules: it renders, it passes kubeconform -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 no imagePullSecrets.
  • Deny-all .gitignore with 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.

Quickstart

  1. Click Use this template → create deploy-<your-app> (lowercase, ^deploy-[a-z0-9-]+$). The repo name becomes the cluster tenant namespace.

  2. Replace the example container in kubernetes/base/deployment.yaml with your application, and set the image in kubernetes/base/kustomization.yaml to your published, signed image — pinned by @sha256: digest.

  3. Set EXPECTED_IMAGE in .github/workflows/validate.yaml to your image (e.g. ghcr.io/<org>/<app>), and rename the deploy-example namespace in base/kustomization.yaml to match your repo.

  4. Add any app-specific egress to kubernetes/base/networkpolicy.yaml (the cluster grants only default-deny + DNS).

  5. 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-DIGEST so 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.

Architecture — the three-repo split

 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.

How it gets onto a cluster

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.

Security model

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

Documentation

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/

License

MIT.

About

Canonical template for deploy-* GitOps repositories: a digest-pinned, PSS-restricted Kustomize base+overlay skeleton with a merge-gating validate workflow (render, schema, digest-pin, image-contract, secret-scan), deny-all .gitignore, repo ADRs, and a documented cluster admission contract.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors