SKYHOUSE.dev Journal

Maintaining the Cloud Fortress

DNS self-healing: ANAME retired for a literal A + a drift watchdog

Why: The WAN IP changed at 14:20 and the site went ~half-unreachable for over an hour — the "auto-redirection" we'd built reacted (Telegram alert fired) but nothing fixed anything, and when I dug in, the supposed manual fix turned out to be impossible too.

This entry reverses the headline decision of 2026-06-03 (apex ANAME → glddns). That design was based on a wrong premise; today's IP change exposed it. I converted the apexes back to a literal A record that the API can actually manage, wired up real remediation (not just alerting), and added a second, independent watchdog so two different triggers can each kick off a repair.

1. What actually broke

At 14:20 the public IP went 97.113.239.113 → 174.21.187.113. The router's own DDNS name cw526dc.glddns.com tracked it correctly within seconds. But skyhouse.dev stayed broken for ~half the internet for over an hour. The smoking gun:

2. Root cause: the ANAME's "staticness" was the bug, not the feature

The 2026-06-03 entry praised the ANAME because "the Dynadot record never changes, so there's nothing for ns1 to get wrong." That's exactly backwards. An ANAME isn't static at the IP level — Dynadot resolves glddns.com server-side and hands clients a plain A, caching that result per-backend. When the IP changed, the registrar record didn't change, so ns1 had no reload trigger and kept serving its cached old resolution forever. The 6/3 "verified 8/8 correct" only proved the zone was consistent at switch-time; it never proved ANAME re-resolution stays consistent across an actual IP change. It doesn't.

Proof in the act: the moment I pushed a real record edit (ANAME→A), ns1 got its trigger and converged within minutes. The earlier room101.com "ANAME worked, so ANAME is what saves us" conclusion was the same trap — one domain happening to look fine (its ns1 replica happened to be current) is luck, not evidence. Today botaa.org's ns1 was coincidentally correct at the same moment skyhouse.dev's was an hour stale.

3. The fix: literal A on the API-writable domains

Converted the apex from ANAME → cw526dc.glddns.com to a literal A → <current IP> (plus the unchanged * wildcard CNAME → apex) via set_dns2:

The trade-off we knowingly give up: the router no longer auto-feeds the apex. So the IP must now be pushed on change — which is the whole point, because a push is what gives ns1 a reload trigger.

4. New processes — two independent triggers, real remediation

The old setup was detect-and-alert only. Now there are two independent reactors, either of which initiates a repair, plus hardened IP detection:

5. The honest limit — and why Cloudflare is still the real fix

Even after converting to A, I watched both Dynadot nameserver pools flap between the old and new IP for a while (some backend machines in each pool hadn't reloaded). Re-asserting nudges them and ns2 recovers fast, but we cannot force Dynadot's pools to converge on demand — there's simply no API lever for it. So this setup gives automatic, hands-off recovery bounded by Dynadot's own (minutes-to-tens-of-minutes, occasionally worse) convergence, which is a massive improvement over "stuck until a human logs in." But the only thing that eliminates per-nameserver split-brain entirely is a single anycast authority. The durable fix remains the Cloudflare migration (same flattened-CNAME pattern, a real DDNS API, plus free email forwarding which would also unblock room101). Damien is resistant to adding another company in the path; this A-record self-healing is the agreed interim until he's ready.

Net effect: the apex is a literal A the API can manage; an IP change is now auto-pushed, and a second watchdog independently catches and re-asserts authoritative-DNS drift — so a recurrence repairs itself instead of waiting for a human, within the bounds of Dynadot's flaky nameservers.

← Back to Admin Hub