Operator directive: don't diverge architecture to avoid asking for credentials; provision them upfront via SOPS and keep the existing (unified) graph. Roadmap reconciliation: Phase 2 = Network/Storage/TLS/DNS/Ingress, so cert-manager/externaldns/gateway (the credential-gated pieces) ARE Phase 2; monitoring is Phase 4. Earlier A2/rollout scope was inverted by credential-avoidance. Reverts (credential-driven): remove clusters/dev/rollout/ + the $patch:delete's; restore unified base graph (dev = ../base + cluster-vars + SOPS decryption, R-ENV-02 intact); restore monitoring files (Phase 4). Kept non-credential improvements: tofu for_each/rejoin, Kyverno parametrization + webhook excludes. platform/kustomization.yaml now phased (single shared list): Phase-2 set = kyverno, cilium, longhorn, cert-manager, externaldns, gateway; later components commented with phase markers. SOPS activated: .sops.yaml at repo root; bootstrap/sops/secret-templates/*.yaml.example for all secrets (cloudflare x2, grafana, alertmanager-smtp, keycloak, oauth2-proxy, pia); bootstrap/sops/CREDENTIALS.md checklist; pre-wired commented cloudflare-api-token lines in cert-manager + externaldns; filled non-secret ACME email. Agents never touch real secret values (operator encrypts). Validated: kubectl kustomize dev(unified)/prod/platform(Phase-2 only), templates inert, make -C ci gate PASS. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
platform/externaldns
ExternalDNS — automatic public DNS records for public services (Cloudflare).
- Spec: docs/09 — DNS & Ingress (ExternalDNS is named in docs/01; no dedicated ADR)
- Serves: R-DNS-01/02/03
- Owner: WS-NET (token from WS-SEC)
What this stub is
Flux HelmRelease watching Gateway/HTTPRoute + Service resources, publishing
<service>.home.keithjackson.dev records in Cloudflare from declared intent (no manual record
editing, R-DNS-02).
Split-horizon note (docs/09)
A wildcard *.keithjackson.dev matches only one label deep, so <svc>.home.keithjackson.dev needs
its own record. internal services need NO public record — PiHole resolves them to the internal
Gateway VIP (split-horizon). ExternalDNS manages public services' records only.
Secrets
Cloudflare API token referenced by name (cloudflare-api-token, shared with cert-manager),
SOPS-encrypted (WS-SEC, OQ-4).
TODO (later phases)
- Phase 2 (WS-NET): confirm
gateway-httproutesource; prove an auto record for a test route (R-DNS-02, Phase-2 exit gate). - Phase 6 (WS-APPS): PiHole provides the internal split-horizon answers as it onboards.