Operator chose Option A. cert-manager solves ACME DNS-01 and ExternalDNS manages *.home.keithjackson.dev records via a scoped Cloudflare token (Zone.DNS.Edit, keithjackson.dev), stored SOPS-encrypted. Operator provides the token once (new prereq T-2.4p); T-2.4/T-2.5 unblocked. Only OQ-BKP (off-cluster DR backup target, Phase 4) remains open. Updated: docs 00,08,09; task board. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
4.9 KiB
4.9 KiB
09 — DNS & Ingress
Serves: R-DNS-01/02/03, R-C2-01, works with R-TLS-*. Related: ADR-0002 (Cilium/Gateway API).
Naming model
- All services live at
<service>.home.keithjackson.dev(e.g.plex.home.keithjackson.dev). - The root
home.keithjackson.devserves the Command & Control UI (12). - Public apex
*.keithjackson.devresolves to the network's public IP;*.home.keithjackson.devis the platform's zone.
DNS automation (R-DNS-02)
- ExternalDNS watches Gateway/HTTPRoute (and Service) resources and manages records in the authoritative DNS provider (Cloudflare, per OQ-4) automatically — a new service's DNS appears from its declared intent, no manual record editing.
- Records for
*.home.keithjackson.devare created/updated/removed as services come and go.
Split-horizon resolution (R-DNS-03)
Internal and external answers differ:
- External (
*.home.keithjackson.devfrom the internet): resolves to the public IP; reaches the edge router, which forwardspublic-class services to the in-cluster Gateway. - Internal (LAN clients): resolves
<service>.home.keithjackson.devto the internal Gateway address directly, avoiding hairpinning through the public IP. - PiHole (itself an onboarded service) provides internal LAN DNS and the split-horizon answers
for
.home.keithjackson.dev; the trusted Let's Encrypt cert is served either way (08).
DNS is thus both a platform capability and a hosted service. Bootstrapping order matters: the platform needs working DNS before PiHole is fully managed — handled by the bring-up sequence in
roadmap/phases.md.
Ingress (north-south) via Gateway API
- Gateway API implemented by Cilium is the ingress layer (no separate ingress controller; reuses the CNI, ADR-0002).
- A shared Gateway defines HTTPS listeners on
*.home.keithjackson.devterminating TLS with the cert-manager cert (08). - Each service contributes an HTTPRoute mapping its hostname to its Service — rendered from the ServiceDefinition, not hand-authored.
- Exposure class is declared per service:
internal— reachable only on the LAN (no edge port-forward; internal DNS only).public— additionally reachable from the internet via the edge router forwarding 80/443 to the Gateway.
Edge integration (single SOHO router — OQ-1 resolved)
- The environment has one SOHO edge router: no VLANs, no VPN, no services, no API/IaC. Its only
ingress job is manual port-forwarding of 80/443 (and specific service ports, e.g. Plex 32400,
Minecraft 25565) to the Gateway VIP for
publicservices. This is a documented manual edge step (the SOHO device has no automation) — the analogue of the old pfSense manual-config exception. Confirm the router can port-forward (basic NAT; almost all can). - No multi-WAN inbound rules — single WAN (03).
internalservices are never port-forwarded; they rely on internal DNS + Gateway on the LAN.- Ingress VIP mechanism — resolved: Cilium L2 announcement (ARP/NDP) on the flat LAN. BGP is not available on a SOHO router, and a single flat subnet makes L2 announcement the natural choice.
DNS record depth (note for *.home.keithjackson.dev)
A wildcard *.keithjackson.dev matches only one label deep — it covers home.keithjackson.dev
but not plex.home.keithjackson.dev. Consequences:
internalservices need no public record — PiHole resolves<svc>.home.keithjackson.devto the internal Gateway VIP (split-horizon). This is the majority of services.publicservices need a public record for<svc>.home.keithjackson.dev. Per OQ-4 (resolved), ExternalDNS manages these automatically via the scoped Cloudflare API token — no manual record editing (see 08).
Interaction with default-deny
Ingress opens north-south paths to the specific service; it does not relax east-west default-deny (03). A service being publicly reachable does not let other in-cluster services reach it unless an explicit allow rule exists.
Acceptance gates
- A new service's
<service>.home.keithjackson.devrecord appears automatically and routes to it. internalservices are unreachable from the public internet;publicservices are reachable and TLS-valid.- Internal clients resolve to the internal Gateway (no public hairpin) and get a trusted cert.
- The root
home.keithjackson.devserves the C2 UI.
Resolved
- OQ-1 — single SOHO edge (manual port-forward only); ingress VIP via Cilium L2 announcement.
- OQ-4 — scoped Cloudflare API token drives ExternalDNS (records) and cert-manager DNS-01 (certs) automatically; see 08.