Operator answers folded into the specs: - OQ-3 VPN: ExpressVPN, cluster-controlled SINGLE shared in-cluster tunnel (OpenVPN UDP / non-TCP), rules enforced outside the service. New ADR-0012 supersedes ADR-0008 (Gluetun-sidecar default dropped). Central kill-switch. - OQ-1 WAN/edge: one commercial WAN, no multi-ISP plans; dumb SOHO edge (no VLAN/VPN/services). Multi-WAN out of scope; segmentation + VPN in-cluster; edge = NAT + manual port-forward. Gateway VIP resolved to Cilium L2 announcement. T-3.3 marked won't-do. - OQ-2 storage: bulk media lives outside the cluster (backing TBD, non-blocking) via a 'bulk' external-mount indirection; Plex metadata DB stays on Longhorn. Split out a separate OQ-BKP for the off-cluster DR backup target (Phase 4). - OQ-4 refined: wildcard record covers reachability but NOT ACME DNS-01 (needs TXT-write access) and does not match *.home.* depth. Still OPEN: Cloudflare API token (Option A) vs acme-dns delegation (Option B). T-2.4/T-2.5 blocked. Updated: docs 00,01,03,04,08,09; ADR-0008/0012 + index; task board. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
5.1 KiB
5.1 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. That is provided by either a one-time*.home.keithjackson.dev→ public-IP record, or by ExternalDNS via the DNS API — both hinge on OQ-4 (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.
Open questions
- OQ-4 — DNS challenge/record access: Cloudflare API token (automated ExternalDNS + DNS-01)
vs acme-dns delegation (one-time CNAME, no standing credential). Determines whether public
*.home.keithjackson.devrecords and ACME challenges are automated or partly manual. See 08.