Skip to content

v2.0.1 — DNS zone round-trip fixes

Latest

Choose a tag to compare

@danhorntx danhorntx released this 30 Aug 01:26
· 7 commits to main since this release

Patch release. Every zone mutation in DPanel rewrites the whole zone file, so any record the parser could not represent faithfully was silently altered or dropped on the next unrelated edit. Three such cases are fixed, along with an .env load-order bug that could re-delegate a zone to the wrong nameservers.

No configuration change is required. Defaults are unchanged, so existing installs behave exactly as before.

Fixed

SRV records lost their trailing dot. parseZone stripped it from every non-TXT value, but renderZone restored it only for CNAME and MX. An SRV target sip.example.com. came back as sip.example.com, which BIND then resolves against $ORIGIN as sip.example.com.<zone>. The record survived its own creation and broke on the next edit to that zone — a delayed failure that does not point back at the edit that caused it.

Subdomain NS delegations were deleted. parseZone skipped all NS records as infrastructure, so an operator-added delegation (sub IN NS ns1.other.net.) vanished on the next zone write. Only apex NS records are skipped now.

The SOA serial could go backwards. YYYYMMDDNN has room for 99 revisions per day. The 100th produced an 11-digit serial that overflows the uint32 SOA field and failed the 10-digit reader, so the following write read it back as 0 and regressed — which stops zone transfers to secondaries. Every path is now guarded to return a strictly larger, in-range, 10-digit serial.

.env was not loaded by modules that read it at require time. lib/dns.js read DPANEL_NS1/DPANEL_NS2 into constants at import but relied on the requiring process having loaded dotenv. server.js does; a maintenance script or node -e one-liner does not, and would silently fall back to the built-in defaults — then re-stamp the zone's apex NS and SOA MNAME to the wrong nameservers on its first write. lib/imap.js and lib/analytics-mailer.js had the same shape with milder consequences.

Added

  • DPANEL_NS1 / DPANEL_NS2 — the vanity nameserver pair is no longer hard-coded, so a second host can advertise its own. Defaults unchanged.
  • NS re-stamp audit trail. The apex NS RRset and SOA MNAME are re-stamped on every zone write, so an unrelated record edit can silently re-delegate a zone once that pair changes. That behaviour is intentional, but now logs as dns:ns-restamp with before/after values.
  • BIND reload failures are reported. reloadBind() swallowed every error, leaving BIND serving stale data with no signal. It now logs dns:reload-failed and returns a status. It still does not throw — the zone on disk is already validated, and rolling back a good write over a transient rndc hiccup is the worse failure.

Removed

  • panel.<domain> A record is no longer written into new zones. The panel is served only at each host's own hostname, so this stamped a record pointing at an unserved name into every zone.

Upgrading

The fixes are not retroactive — they preserve what is already on disk, so anything the old parser mangled stays mangled. After deploying, audit for pre-existing damage:

# SRV targets missing a trailing dot — being resolved against $ORIGIN
grep -H "IN[[:space:]]*SRV" /var/lib/bind/*.db | grep -v '\.$'

# Should be exactly 2 NS per zone unless a delegation legitimately exists
grep -c "IN[[:space:]]*NS" /var/lib/bind/*.db

Subdomain delegations already deleted by the old parser cannot be recovered from the zone files and must be re-added. See PROD_MIGRATIONS.md for the full checklist.