feat(dns): publish Gateway names to the WAN via in-cluster DDNS #40

Merged
jakman85 merged 1 commits from feat/public-dns-wan-target into main 2026-10-03 22:25:13 +00:00
Owner

Points public DNS for the shared Gateway's names at the home WAN instead of the RFC1918 Gateway VIP. The WAN 80/443 forward to 192.168.2.20 is already in place.

Change

  • platform/gateway/gateway.yaml: adds external-dns.alpha.kubernetes.io/target: wan.${BASE_DOMAIN} to the shared Gateway. Every Gateway-published name becomes CNAME wan.home.keithjackson.dev.
  • platform/externaldns/ddns.yaml (new): a favonia/cloudflare-ddns:1.17.1 Deployment that keeps wan.home.keithjackson.dev an A record at the current WAN IP (IPv4, unproxied, checked every 5m). It reuses the existing cloudflare-api-token. external-dns has no registry TXT for this record, so it never owns or deletes it.
  • The comment block in the external-dns HelmRelease, the README and decisions/2026-10-03-public-dns-wan-target.md now record the operator decision that every Gateway-published name goes public. That includes the admin UIs, not only the five exposure: public apps.

Unchanged: internal routes (controller: none) still publish nothing. The service-source L4 names (crafty-mc, unifi) still publish their LB VIPs.

Gate (pinned toolbox, DEV_KUBECONFIG=/dev/null)

rc=3: spec-immutability, decisions-log, lint, l0, render-golden, l1 and approval-policy all pass. gitea-settings was skipped because there is no SETTINGS_API_TOKEN on the workstation. conformance (L2/L3) did not run. No sensitive paths are touched.

Known risk: kubectl OIDC SSO

The nodes resolve through public DNS, so the apiserver's issuer keycloak.home.keithjackson.dev will resolve to the WAN IP. A LAN probe of 136.51.115.252:443 returned a self-signed placeholder cert, not the Gateway's LE wildcard, which suggests the router does not hairpin. kubectl SSO may break until there is a node /etc/hosts pin or NAT reflection. The cert-based admin kubeconfig is unaffected.

After merge, verify

  • kubectl -n external-dns logs deploy/cloudflare-ddns
  • dig +short @1.1.1.1 plex.home.keithjackson.dev should return wan.home.keithjackson.dev. and then the WAN IP
  • Load the site from outside the LAN (e.g. a phone on cellular)

🤖 Generated with Claude Code

Points public DNS for the shared Gateway's names at the home WAN instead of the RFC1918 Gateway VIP. The WAN 80/443 forward to `192.168.2.20` is already in place. ## Change - **`platform/gateway/gateway.yaml`**: adds `external-dns.alpha.kubernetes.io/target: wan.${BASE_DOMAIN}` to the shared Gateway. Every Gateway-published name becomes `CNAME wan.home.keithjackson.dev`. - **`platform/externaldns/ddns.yaml`** (new): a `favonia/cloudflare-ddns:1.17.1` Deployment that keeps `wan.home.keithjackson.dev` an A record at the current WAN IP (IPv4, unproxied, checked every 5m). It reuses the existing `cloudflare-api-token`. external-dns has no registry TXT for this record, so it never owns or deletes it. - The comment block in the external-dns HelmRelease, the README and `decisions/2026-10-03-public-dns-wan-target.md` now record the operator decision that every Gateway-published name goes public. That includes the admin UIs, not only the five `exposure: public` apps. Unchanged: `internal` routes (`controller: none`) still publish nothing. The service-source L4 names (crafty-mc, unifi) still publish their LB VIPs. ## Gate (pinned toolbox, `DEV_KUBECONFIG=/dev/null`) `rc=3`: spec-immutability, decisions-log, lint, **l0**, render-golden, l1 and approval-policy all **pass**. `gitea-settings` was skipped because there is no `SETTINGS_API_TOKEN` on the workstation. `conformance` (L2/L3) did not run. No sensitive paths are touched. ## Known risk: kubectl OIDC SSO The nodes resolve through public DNS, so the apiserver's issuer `keycloak.home.keithjackson.dev` will resolve to the WAN IP. A LAN probe of `136.51.115.252:443` returned a self-signed placeholder cert, not the Gateway's LE wildcard, which suggests the router does not hairpin. kubectl SSO may break until there is a node `/etc/hosts` pin or NAT reflection. The cert-based admin kubeconfig is unaffected. ## After merge, verify - `kubectl -n external-dns logs deploy/cloudflare-ddns` - `dig +short @1.1.1.1 plex.home.keithjackson.dev` should return `wan.home.keithjackson.dev.` and then the WAN IP - Load the site from outside the LAN (e.g. a phone on cellular) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
gitea-admin added 1 commit 2026-10-03 22:03:42 +00:00
feat(dns): publish Gateway names to the WAN via in-cluster DDNS
gate / gate (pull_request) Successful in 1m46s
gate / conformance (pull_request) Has been skipped
a1e808e697
Gateway-published records now CNAME to wan.${BASE_DOMAIN}, which a
favonia/cloudflare-ddns Deployment keeps at the home WAN's current public
IP. Operator decision: every Gateway-published name goes public; internal
services (controller: none) remain unpublished.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
jakman85 merged commit 576e1abb19 into main 2026-10-03 22:25:13 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Home-Network/home-network-k3s-impl#40