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]>
90 lines
5.1 KiB
Markdown
90 lines
5.1 KiB
Markdown
# 09 — DNS & Ingress
|
|
|
|
Serves: **R-DNS-01/02/03**, **R-C2-01**, works with **R-TLS-***. Related:
|
|
[ADR-0002 (Cilium/Gateway API)](../decisions/adr-0002-cni-cilium.md).
|
|
|
|
## Naming model
|
|
|
|
- All services live at `<service>.home.keithjackson.dev` (e.g. `plex.home.keithjackson.dev`).
|
|
- The **root** `home.keithjackson.dev` serves the **Command & Control UI** ([12](12-command-center-ui.md)).
|
|
- Public apex `*.keithjackson.dev` resolves to the network's public IP; `*.home.keithjackson.dev`
|
|
is 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.dev` are created/updated/removed as services come and go.
|
|
|
|
## Split-horizon resolution (R-DNS-03)
|
|
|
|
Internal and external answers differ:
|
|
- **External** (`*.home.keithjackson.dev` from the internet): resolves to the public IP; reaches
|
|
the edge router, which forwards `public`-class services to the in-cluster Gateway.
|
|
- **Internal** (LAN clients): resolves `<service>.home.keithjackson.dev` to 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](08-tls-and-certificates.md)).
|
|
|
|
> 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`](../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](../decisions/adr-0002-cni-cilium.md)).
|
|
- A shared **Gateway** defines HTTPS listeners on `*.home.keithjackson.dev` terminating TLS with the
|
|
cert-manager cert ([08](08-tls-and-certificates.md)).
|
|
- 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 `public` services. 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](03-networking-isolation-and-egress.md)).
|
|
- `internal` services 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:
|
|
- **`internal` services need no public record** — PiHole resolves `<svc>.home.keithjackson.dev` to
|
|
the internal Gateway VIP (split-horizon). This is the majority of services.
|
|
- **`public` services** 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](08-tls-and-certificates.md)).
|
|
|
|
## Interaction with default-deny
|
|
|
|
Ingress opens **north-south** paths to the specific service; it does **not** relax **east-west**
|
|
default-deny ([03](03-networking-isolation-and-egress.md)). 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.dev` record appears automatically and routes to it.
|
|
- `internal` services are unreachable from the public internet; `public` services are reachable and
|
|
TLS-valid.
|
|
- Internal clients resolve to the internal Gateway (no public hairpin) and get a trusted cert.
|
|
- The root `home.keithjackson.dev` serves 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.dev` records and ACME challenges are automated or partly manual. See
|
|
[08](08-tls-and-certificates.md).
|