Serve the Pangolin-fronted zones from local DNS - #428
Merged
Conversation
*.lab / *.arr / *.iot are grey-cloud A records at Cloudflare pointing to the home WAN IP, so inside the house they resolved to the WAN too and every admin UI was reached by NAT hairpin back through the pangolin-https port-forward. That made the forward load-bearing for LAN access rather than only for remote access, so ADR-0007's "reversible exit" of closing :443 would have taken the whole admin surface down at home as well. Three controller-local records decouple the two. Wildcards, not the ~16 individual records #419 estimated: the controller supports them and matches arbitrary labels, which was verified against the live gateway (the Azure Lab's *.topaz.local.dev already answers any label under it). A new Pangolin resource now needs no DNS work at all. The mechanism is a new `staticDns` list on the UnifiNetwork shape, reconciled by converge-unifi against the v2 site API. Add-only and drift-correcting, like the rest: a record that exists but answers differently is corrected, and the 17 records belonging to other things are listed and left alone. Matching is by name AND type, because an A and a CNAME for one name are distinct rows — matching on name alone would make converge try to turn one into the other. TTL is only claimed when the shape states one, or every run would rewrite the controller's default forever. An update carries the live record's untouched fields forward: v2 rejects partial updates, so a full replacement rebuilt from defaults would silently reset fields the shape says nothing about. Deliberately NOT overridden: pangolin.chrison.dev, which is orange-clouded and rides the core CF tunnel that serves the SSO redirect every resource bounces through; and vpn.chrison.dev, which has to resolve to the WAN address from inside the house too or the client dials its own LAN. Verified live. All three zones resolve to 10.10.0.13 including a brand-new label; the UIs answer 302 to the SSO gate; that gate still resolves via Cloudflare; the Let's Encrypt cert is served directly by Traefik on the LAN path; and a second run reports no changes. Closes #419. Refs #314 — this codifies the UniFi half; pairing a record with a Pangolin resource declaration is the remaining part. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #419. Refs #314.
The problem
*.lab/*.arr/*.iotare grey-cloud A records at Cloudflare pointing at the home WAN IP, so inside the house they resolved to the WAN too:Every admin UI on the LAN was therefore reached by NAT hairpin back through the
pangolin-httpsport-forward. That made the forward load-bearing for LAN access, not just remote access — so ADR-0007's "reversible exit" of closing:443would have taken the whole admin surface down at home as well.Three records, not sixteen
#419 estimated ~16 records and asked whether the controller supports wildcards. It does, and they match arbitrary labels — verified against the live gateway, where the Azure Lab's
*.topaz.local.devalready answers any label under it. So a new Pangolin resource now needs no DNS work at all:The mechanism
A
staticDnslist on theUnifiNetworkshape, reconciled byconverge-unifiagainst the v2 site API (a different surface from the legacy one — UnifiSharp#18 added the client). Add-only and drift-correcting, like the rest: the 17 records belonging to other things are listed and left alone.Three decisions worth reviewing:
Deliberately not overridden
pangolin.chrison.dev— orange-clouded, rides the core CF tunnel. Every resource bounces through it for the SSO gate; pointing it at Traefik locally would take that redirect off the tunnel serving it.vpn.chrison.dev— also a WAN A record, but a VPN endpoint must resolve to the WAN address from inside the house too, or the client dials its own LAN.Verified live
Applied, then checked:
Against #419's acceptance criteria:
302to the SSO gate, over the direct pathpangolin.chrison.devis untouched and still Cloudflare)pulse.lab.chrison.devis served directly by Traefik on the LAN path:443is not being closed here — that stays open per the 2026-08-16 decision. This removes the reason it was load-bearing for LAN access, so closing it becomes a decision about remote access alone.A second run reports
Everything declared is present and matching — nothing to do.308 tests pass (14 new).🤖 Generated with Claude Code