secondary: scaffold public CoreDNS secondary on ns.supported.systems

Adds a second non-HE public secondary that pulls AXFR from dell01 (the
hidden primary at 154.27.180.210) and answers public queries on
ns.supported.systems (64.177.113.227, 2001:19f0:5c00:4daa:5400:6ff:fe2d:38fa).

  secondary/
    Corefile                            generated, 84 zones + REFUSED catch-all
    docker-compose.yml                  CoreDNS in host-net mode
    Makefile                            up/down/logs/regen/test/axfr-test
    .env / .env.example                 image pin + bind IPs
    scripts/generate-secondary-corefile.sh  reads ../zones/*.zone

  scripts/notify-he.py → notify-secondaries.py
                                        adds 64.177.113.227 as a second
                                        NOTIFY target alongside HE's
                                        216.218.130.2

Uses CoreDNS's `bind` plugin to avoid colliding with systemd-resolved
on loopback :53. Authoritative-only — non-listed zones get REFUSED, no
recursion. AXFR pull requires opening TCP/53 on dell01's FortiWiFi for
the secondary's IP (manual step, separate from this commit).
This commit is contained in:
Ryan Malloy 2026-05-20 18:40:11 -06:00
parent 94f2bdc68a
commit 618e9504e7
9 changed files with 276 additions and 22 deletions

View file

@ -10,7 +10,7 @@ what the public actually sees. Git/this repo is the source of truth.
```
edit zones/*.zone → make prep → CoreDNS auto-reloads (30s)
scripts/notify-he.py
scripts/notify-secondaries.py
NOTIFY → ns1.he.net (216.218.130.2)
@ -53,7 +53,7 @@ git add -A && git commit -m "homestar.ink: add foo A 1.2.3.4"
```
Wait ≤5 minutes for HE to AXFR. If serial doesn't flip on HE,
re-run NOTIFY: `ssh -A dell01... 'cd ~/coredns && ./scripts/notify-he.py'`
re-run NOTIFY: `ssh -A dell01... 'cd ~/coredns && ./scripts/notify-secondaries.py'`
## Publishing to dell01
@ -97,7 +97,7 @@ The Docker stack: `coredns` (server) + `coredns-caddy` (LE cert for
## NOTIFY: external script, not CoreDNS-native
We use `scripts/notify-he.py` to send NOTIFY messages to
We use `scripts/notify-secondaries.py` to send NOTIFY messages to
`216.218.130.2` (ns1.he.net) on every `make prep`. Pure stdlib Python,
no deps.
@ -112,11 +112,11 @@ Only `transfer { to * }` works.
So:
- `Corefile`: `transfer { to * }` — open AXFR (firewall does the
source-IP filtering on TCP/53 NAT anyway)
- `notify-he.py`: sends NOTIFY explicitly to the right IP
- `notify-secondaries.py`: sends NOTIFY explicitly to each secondary's IP
NOTIFY happens automatically on `make prep`. To NOTIFY manually:
```bash
ssh -A dell01... 'cd ~/coredns && ./scripts/notify-he.py'
ssh -A dell01... 'cd ~/coredns && ./scripts/notify-secondaries.py'
```
The script's output doubles as a **"what's on HE" inventory** — `✓`
@ -125,7 +125,7 @@ for zones HE hosts, `✗ rcode=5` for zones HE doesn't yet host.
**HE's NOTIFY behavior**: HE acks NOTIFY at the protocol level (rcode=0),
and *usually* triggers an immediate AXFR. Sometimes the batch NOTIFY
fired from `make prep` doesn't seem to wake them; re-running
`notify-he.py` manually almost always does. Per-zone NOTIFY is more
`notify-secondaries.py` manually almost always does. Per-zone NOTIFY is more
reliable than batch.
## HE asymmetric IPs
@ -196,7 +196,7 @@ Intermediate empty non-terminals **do** block synthesis below them.
## Zone-by-zone HE status
`./scripts/notify-he.py` prints `✓` / `✗` per zone — `✓` means HE
`./scripts/notify-secondaries.py` prints `✓` / `✗` per zone — `✓` means HE
hosts that zone as a secondary, `✗` (rcode=5) means HE doesn't yet
host it. As of the last NOTIFY run, ~11 of 91 zones are slaved on HE.
The other 80 are still served from Vultr at the registrar level.
@ -228,7 +228,8 @@ Renewal happens automatically; Caddy uses ACME ARI to schedule it.
| `zones-prepared/*.zone` | Generated, served by CoreDNS (gitignored) |
| `Corefile` | CoreDNS config |
| `scripts/prepare-zones.sh` | Zone prep + auto-bump serial |
| `scripts/notify-he.py` | Send NOTIFY to ns1.he.net |
| `scripts/notify-secondaries.py` | Send NOTIFY to ns1.he.net + ns.supported.systems |
| `secondary/` | Public secondary (CoreDNS in Docker) deployed to ns.supported.systems |
| `scripts/check-he.sh` | Parallel HE anycast verification |
| `caddy/Caddyfile` + `caddy/Dockerfile` | Caddy sidecar config |
| `docker-compose.yml` | CoreDNS + Caddy stack |