feat(dns): PiHole answers an explicit LAN name list, not a zone wildcard #157

Open
gitea-admin wants to merge 1 commits from feat/pihole-explicit-lan-names into main
pull from: feat/pihole-explicit-lan-names
Owner

Public names are proxied CNAMEs to the Cloudflare Tunnel since #156 and work from the LAN, so Pi-hole's zone wildcard goes away. It now answers an explicit list; everything else is forwarded and resolves to Cloudflare from the LAN as from anywhere.

Name (.${BASE_DOMAIN}) Answer Why
jackett, pihole, plex, qbittorrent, radarr, semaphore, sonarr, headlamp ${GATEWAY_VIP} LAN-only, derived from every controller: none HTTPRoute; no public record and the tunnel 404s them
gitea, nextcloud ${GATEWAY_VIP} Off Cloudflare's 100 MB / 100 s limits
keycloak, auth ${GATEWAY_VIP} OIDC stays on one path for the LAN-path apps
unifi / crafty-mc / pihole-dns / plex-vip their own VIPs L4 / the resolver itself / Plex's certificate domain

Not listed, so Cloudflare from the LAN: the apex, grafana, crafty, seerr.

Rollout / LAN DNS blip. The env change rolls the StatefulSet (RollingUpdate, one pod at a time, pihole-1 then pihole-0; 2 replicas). No total outage expected: one replica answers throughout. Each replacement can lose a few UDP queries for ~1-2 s (clients retry), and for ~30-60 s the two pods answer differently for the unlisted names (both answers work). Estimate from the last measured rollout; not observed for this change.

Consequences to accept

  • The apex, grafana, crafty and seerr now depend on the internet and the tunnel from the LAN too. Add grafana to the list if it must survive an internet outage.
  • Rolling the tunnel back to wan. now also requires restoring the wildcard (recorded in runbooks/cloudflare-tunnel.md).

Flagged, not changed: the pihole container has no readiness probe; only the oauth2-proxy sidecar does, so Ready says nothing about DNS.

New L0 check pihole-lan-names (whole-repo scope): no zone-wide entry; every disowned route, every tunnel-404 host and gitea/nextcloud covered, L4 names on their own VIPs. 10 mutants against the real files each failed the check.

Also corrects docs that still described public names as CNAME to wan., and the cloudflared entrypoint comment (the pinned image's Entrypoint is cloudflared, Cmd version).

Gate: local toolbox rc 3. Stages that did not run: gitea-settings (needs the CI token); L2/L3 conformance scaffold-skipped (no cluster). spec-immutability, decisions-log, lint, l0, render-golden, l1 passed; approval-policy reports N/A offline.

Needs /approve-override from the operator: conformance/tests/l0-static/pihole-lan-names/{check.sh,chainsaw-test.yaml} are sensitive paths, so approval-policy will be red in CI until then.

Not verified: behaviour against a live Pi-hole with the new list. After reconcile, dig @192.168.2.23 one name per row and confirm grafana returns Cloudflare. Details: decisions/2026-11-09-pihole-explicit-lan-names.md.

🤖 Generated with Claude Code

Public names are proxied CNAMEs to the Cloudflare Tunnel since #156 and work from the LAN, so Pi-hole's zone wildcard goes away. It now answers an explicit list; everything else is forwarded and resolves to Cloudflare from the LAN as from anywhere. | Name (`.${BASE_DOMAIN}`) | Answer | Why | |---|---|---| | jackett, pihole, plex, qbittorrent, radarr, semaphore, sonarr, headlamp | `${GATEWAY_VIP}` | LAN-only, derived from every `controller: none` HTTPRoute; no public record and the tunnel 404s them | | gitea, nextcloud | `${GATEWAY_VIP}` | Off Cloudflare's 100 MB / 100 s limits | | keycloak, auth | `${GATEWAY_VIP}` | OIDC stays on one path for the LAN-path apps | | unifi / crafty-mc / pihole-dns / plex-vip | their own VIPs | L4 / the resolver itself / Plex's certificate domain | Not listed, so Cloudflare from the LAN: the apex, grafana, crafty, seerr. **Rollout / LAN DNS blip.** The env change rolls the StatefulSet (RollingUpdate, one pod at a time, pihole-1 then pihole-0; 2 replicas). No total outage expected: one replica answers throughout. Each replacement can lose a few UDP queries for ~1-2 s (clients retry), and for ~30-60 s the two pods answer differently for the unlisted names (both answers work). Estimate from the last measured rollout; not observed for this change. **Consequences to accept** - The apex, grafana, crafty and seerr now depend on the internet and the tunnel from the LAN too. Add grafana to the list if it must survive an internet outage. - Rolling the tunnel back to `wan.` now also requires restoring the wildcard (recorded in `runbooks/cloudflare-tunnel.md`). **Flagged, not changed:** the `pihole` container has no readiness probe; only the `oauth2-proxy` sidecar does, so Ready says nothing about DNS. **New L0 check** `pihole-lan-names` (whole-repo scope): no zone-wide entry; every disowned route, every tunnel-404 host and gitea/nextcloud covered, L4 names on their own VIPs. 10 mutants against the real files each failed the check. Also corrects docs that still described public names as CNAME to `wan.`, and the cloudflared entrypoint comment (the pinned image's Entrypoint is `cloudflared`, Cmd `version`). **Gate:** local toolbox rc 3. Stages that did not run: `gitea-settings` (needs the CI token); L2/L3 `conformance` scaffold-skipped (no cluster). spec-immutability, decisions-log, lint, l0, render-golden, l1 passed; approval-policy reports N/A offline. **Needs `/approve-override` from the operator:** `conformance/tests/l0-static/pihole-lan-names/{check.sh,chainsaw-test.yaml}` are sensitive paths, so `approval-policy` will be red in CI until then. **Not verified:** behaviour against a live Pi-hole with the new list. After reconcile, `dig @192.168.2.23` one name per row and confirm grafana returns Cloudflare. Details: `decisions/2026-11-09-pihole-explicit-lan-names.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
gitea-admin added 1 commit 2026-11-09 01:58:01 +00:00
feat(dns): PiHole answers an explicit LAN name list, not a zone wildcard
gate / gate (pull_request) Failing after 43s
gate / conformance (pull_request) Skipped
8fe8d5df8a
Public names are proxied CNAMEs to the Cloudflare Tunnel since PR #156 and
work from the LAN, so they should resolve publicly there too. Replace the
address=/${BASE_DOMAIN}/ wildcard with explicit entries: the LAN-only names
(derived from every controller:none HTTPRoute), gitea/nextcloud (off
Cloudflare's 100 MB / 100 s limits), keycloak/auth, and the L4 VIPs.

Add L0 check pihole-lan-names, mutation-tested. Correct docs that still
described public names as CNAME to wan. and the cloudflared entrypoint comment.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Some required checks failed
gate / gate (pull_request) Failing after 43s
Required
Details
gate / conformance (pull_request) Skipped
Some required checks were not successful.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/pihole-explicit-lan-names:feat/pihole-explicit-lan-names
git checkout feat/pihole-explicit-lan-names
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#157