Security-first · spec-driven · Kubernetes-native Website-as-a-Service
kaddy is an internal developer platform for monitored, TLS-terminated websites. One
self-service claim provisions a site behind Caddy with observability, alerting, and
progressive delivery. The gridscale Platform Engineer exercise
is satisfied as one tenant of the platform — clubhouse — not as a one-off VM script.
Pitch deck: Download from Releases (
kaddy-deck.pdfon the latest release).
- Live demo
- Getting Started
- Reviewer paths
- Status
- Stack
- Named components
- Repository layout
- Ways to run
- Testing
- Cloud & cost
- Documentation
- Contributing
Public GSK cloud-edge with Let's Encrypt prod certs (DNS-01). On-demand / time-boxed cost governance — URLs are live only while the edge is up (runbook).
| Surface | URL | Probe (2026-07-20) |
|---|---|---|
| ✅ Argo CD | https://argocd.lab.platformrelay.dev | HTTPS 200 (UI) |
| ✅ Grafana | https://grafana.lab.platformrelay.dev | HTTPS 200 |
| ✅ Demo site | https://demo.lab.platformrelay.dev | HTTPS 200 |
| ✅ Caddy tenant | https://caddy.lab.platformrelay.dev | HTTPS 200 (HTTPRoute caddy-lab) |
| ✅ Portal | https://portal.lab.platformrelay.dev | HTTPS 200 (Backstage) |
Still captures shipped under slides/public/surfaces/ (used by the
deck; paths work on GitHub):
| Surface | Capture |
|---|---|
| Argo CD app-of-apps | ![]() |
| Backstage portal | ![]() |
| Grafana (node pods) | ![]() |
| Upbound Marketplace | ![]() |
Edge overlays: deploy/gateway-controller/traefik/ ·
deploy/gateway/cloud-only/.
Caveats (honest)
- Argo sync ≠ UI up. The Argo CD UI can return 200 while individual apps (e.g.
backstage) are OutOfSync / sync-failed under GSK MemoryPressure — do not claim cluster-wide Synced. - Bring-up / teardown:
task e8b:up→ demo →task e8b:down(see the live-demo runbook).
Local path (kind + Cilium): follow docs/getting-started.md —
task cluster:up → bootstrap → demos (task demo:fire / task demo / task demo:chaos).
| Doc | Why |
|---|---|
| docs/getting-started.md | Bring-up, service catalogue, demos |
| docs/ARCHITECTURE.md | Components & security boundaries |
| docs/ROADMAP.md | Phases 0–2, epics E1–E14 |
| docs/requirements/exercise-traceability.md | Brief → epic mapping |
Local-first: phase 1 runs on kind + Cilium (e1e-kind-local-cluster, landed). Phase 2 promotes to GSK + LBaaS + Upjet — ROADMAP.
- Pitch deck — Download from Releases (deck Pages URL unavailable / not yet published as a static site).
- Scorecard — platformrelay.github.io/Kaddy (HTTP 200; scorecard-pages).
- Local demos — docs/getting-started.md.
- Architecture — docs/ARCHITECTURE.md · exercise traceability · ROADMAP.
ADRs → ARCHITECTURE →
openspec/changes/ (Verify: + Test: per requirement).
Brief answered end-to-end on kind + standing GSK lab edge: serve → scrape → fire, progressive delivery, enforcing security baseline, GitOps. Releases: v0.1.0 … v0.9.1 (working GitHub sign-in gate — same-id override fix, /login redirect; operator-confirmed login).
| Area | State | Notes |
|---|---|---|
| ✅ Phase 1 GitOps | Landed | App-of-apps Synced/Healthy on kind; clubhouse via Cilium Gateway (E4) |
| ✅ Observability | Landed | Prometheus / Alertmanager / Grafana + Loki / Alloy (E3); task demo:fire (E5) |
| ✅ Progressive delivery | Landed | Argo Rollouts + Gateway canary weights / auto-rollback (E7) |
| ✅ Security baseline | Landed | Kyverno Enforce, default-deny NetPol, restricted AppProjects (E1c) |
| ✅ Self-service | Landed | Crossplane Website XRD (E6); Dex + GitHub OAuth (E1d) |
| ✅ Caddy operator | Landed | Optional operator on main (after v0.1.1) |
| ✅ Showcase deck | Recording-ready | E12 / E12d — download from Releases |
| ✅ GSK day-0 IaC | Offline + live-proven | Terramate stacks; E1g cluster proven then torn down / standing carve-out |
| ✅ Cloud edge | Live (time-boxed) | Traefik Gateway + LE on *.lab.platformrelay.dev |
| ✅ Portal (E10) | Live route | portal.lab HTTPS 200; NetPol selectors on main |
| ✅ Caddy lab route | Live | caddy.lab HTTPS 200 via HTTPRoute caddy-lab (no Argo name collision) |
| ✅ Grafana public | Live | grafana.lab HTTPS 200 |
| Partial | UI up; some apps may be OutOfSync under MemoryPressure | |
| Cost-gated | Provider install + Marketplace deploy follow-ups | |
| 🔒 Security review | Filed | docs/security/security-review-2026-07-16.md |
Full plan: ROADMAP.
| Layer | Phase 1 (kind — local) | Phase 2 (gridscale lab) |
|---|---|---|
| Substrate | kind + Cilium (E1e) | GSK managed k8s |
| Day-0 IaC | hack/cluster/ |
Terramate + stacks/gridscale/ |
| Edge | Cilium Gateway + LB-IPAM/L2 | Traefik + LBaaS + LE (deploy/gateway/cloud-only/) |
| GitOps | Argo CD deploy/apps/ |
Same manifests on GSK |
| Identity | Dex + GitHub OAuth | Same |
| Secrets | SOPS + age (ADR-0110) | Same |
| Observability | kube-prometheus-stack + Loki + Alloy | Same |
| Self-service | Crossplane Website XRD |
+ Upjet provider-gridscale (E6g) |
| Progressive delivery | Argo Rollouts + Gateway API | Same |
| Policy | Kyverno, NetworkPolicies | Same |
| Component | Role |
|---|---|
| clubhouse | Sample website tenant (satisfies the brief) |
| marshal | Alerting pipeline — PrometheusRules + Alertmanager |
| mulligan | Blue/green + canary with automated rollback |
| scorecard | Evidence harness — k6 + metrics/logs → HTML report |
| driving-range | Deferred optional 3-node Talos spike (sibling repo; D-025) |
Kaddy/
├── deploy/ # GitOps manifests (Argo app-of-apps)
│ ├── apps/ # Application CRs + AppProjects
│ ├── gateway/ # kind Gateway + cloud-only Traefik routes
│ ├── gateway-controller/ # Traefik (cloud) / Cilium edge controllers
│ ├── portal/ # Backstage IDP wiring (E10)
│ ├── workloads/ # clubhouse / caddy-mvp / demos
│ ├── crossplane/ # Website XRD + compositions
│ ├── monitoring/ # marshal rules, ServiceMonitors
│ └── policies/ # Kyverno + NetworkPolicies
├── stacks/ # OpenTofu / Terramate (phase 2)
│ ├── gridscale/ # network · k8s (GSK) · lbaas · object-storage
│ └── gridscale-marketplace/ # caddy · nix Marketplace templates (E13/E14)
├── nix/ # Flake + modules for Nix golden images (E14)
│ ├── flake.nix
│ └── caddy/ · srv/ · modules/
├── hack/
│ ├── cluster/ # kind bring-up (kind-up.sh, Cilium, Gateway API)
│ └── gsk/ # edge-up.sh, cert-manager, image rolls
├── packer/ # Ubuntu Marketplace golden images
├── operator/ # Optional Caddy operator (Go)
├── slides/ # Slidev interview deck sources
├── openspec/changes/ # Spec-driven change proposals
├── tests/ # smoke · chainsaw · deck · meta gates
├── docs/ # Architecture, ROADMAP, ADRs, getting-started
└── evidence/ # Scorecard + live proof notes
| Path | Entry points |
|---|---|
| kind (local) | hack/cluster/kind/ · hack/cluster/kind-up.sh · task cluster:up · getting-started |
| GSK edge | hack/gsk/edge-up.sh · deploy/gateway/cloud-only/ · live-demo runbook |
| OpenTofu / Terramate | stacks/gridscale/ · stacks/gridscale-marketplace/ · config.tm.hcl / terramate.tm.hcl |
| Nix golden image | nix/flake.nix · nix/caddy/ · .github/workflows/e14-nix-image.yaml |
| Packer (Ubuntu) | packer/caddy.pkr.hcl · packer/nginx.pkr.hcl |
| Argo GitOps | deploy/apps/root.yaml · deploy/apps/ |
| Portal | deploy/portal/ · companion kaddy-portal |
Every requirement carries a Test: artifact and a Verify: command — see
docs/development/testing.md and
ADR-0701.
task verify # lint + scrub + openspec + spec-coverage + meta smokes
task test:spec # every REQ has Test + Verify
task test # L0 tofu test · L1 conftest + promtool · L2 Chainsaw| Level | Tool | Proves |
|---|---|---|
| L0 | tofu test |
Label module outputs |
| L1 | conftest · promtool | Plan labels · alert rules fire |
| L2 | Chainsaw | Policies, routes, rollouts, monitors on a live cluster |
| L3 / L4 | k6 · scorecard | Load / alerting · evidence bundle |
Phase 1 develops on kind ($0). Phase 2 promotes to gridscale-native PaaS (GSK, LBaaS, Object Storage, Upjet) for the employer-facing demo.
Lab-sized footprint — estimates from public gridscale pricing (control plane free; billed per minute). Re-check before quoting. Phase 1 is €0 / month.
| Resource | Size (typical lab) | Est. EUR / month |
|---|---|---|
| GSK node pool | 4× 2C-4G workers (~€46/node; D-048 default 3, 4th operator-approved 2026-07-20) | ~184 |
| LBaaS | 1 load balancer | ~22.50 |
| Object Storage | evidence / marketplace .gz (per GB) |
~0.06 / GB |
| Total (indicative, excl. storage GB) | ~207 EUR / month |
| Document | |
|---|---|
| 🎯 | Getting Started · ROADMAP · exercise traceability |
| 🏗️ | ARCHITECTURE · ADRs |
| 📋 | DEVELOPMENT · testing · skills |
| 🔒 | Audits · security review |
| 🎬 | Slides · Releases (deck) |
| 📊 | Evidence / scorecard |
Reference material (gitignored locally)
references/PocketIDP/ is a local, un-vendored copy of
PocketIDP (Gitea + Backstage patterns
for E10). Not part of the committed tree.
- Gates:
task verify(see DEVELOPMENT). - Commits:
:gitmoji: <type>(scope): summary— ASCII shortcode, no Unicode emoji in the subject. - Spec-driven lanes reference an OpenSpec change under
openspec/changes/. - Deck sources live in
slides/; prefer consuming the published deck from Releases rather than rebuilding locally.




