Retire prepare-zones.sh pipeline; zones/ is now the served form
Big migration: the source/prepared split is gone. Each zones/*.zone is now an RFC-compliant zone file that CoreDNS reads directly. Editing a record is just edit + bump SOA + commit. CoreDNS auto-reloads within 30s; HE pulls on its own 300s SOA-refresh cycle. Why: groundwork for the coredns-rfc2136 plugin to edit zones in place without juggling a source/prepared transformation step. Also reduces the mental model from "edit source, run prep, push" to just "edit". Changes: - zones/*.zone: 84 files migrated from Vultr-export form to RFC-compliant form (SOA injected, Vultr NS replaced with HE NS, CNAME/MX/NS rdata dot-terminated, apex lines get explicit @ prefix). Diff is mechanical and byte-count is unchanged (~340K) -- pure formatting promotion. - docker-compose.yml: bind ./zones:/zones:ro (was ./zones-prepared) - Makefile: dropped 'prep' target. 'reload' is now a no-op explainer. 'tls-up' no longer depends on prep. 'clean' no longer wipes prepared. - scripts/prepare-zones.sh moved to scripts/archive/ (kept for reference). - .gitignore: updated comment for zones-prepared/ (now legacy). NOT in this commit (follow-ups): - CLAUDE.md updates documenting the new workflow. - scripts/bump-serials.sh helper for manual-edit SOA bumping. - coredns-rfc2136 plugin refactor (Phase 2b in the plan).
This commit is contained in:
parent
a9256f8ba4
commit
6d72d65642
88 changed files with 2125 additions and 795 deletions
129
scripts/archive/prepare-zones.sh
Executable file
129
scripts/archive/prepare-zones.sh
Executable file
|
|
@ -0,0 +1,129 @@
|
|||
#!/usr/bin/env bash
|
||||
# Injects an SOA record + canonical NS records into each raw Vultr zone
|
||||
# file, then writes the result to zones-prepared/. Source files in zones/
|
||||
# are never modified.
|
||||
#
|
||||
# Corrections applied to each zone:
|
||||
# 1. Synthesize SOA — Vultr's export omits it. SOA mname is ns1.he.net
|
||||
# because Hurricane Electric secondaries serve the public face of
|
||||
# these zones (hidden-primary architecture).
|
||||
# 2. Strip the source's ns1.vultr.com / ns2.vultr.com NS records and
|
||||
# replace with the five HE nameservers, so AXFR-pulled zones at HE
|
||||
# advertise the correct delegation.
|
||||
# 3. Apex disambiguation: lines starting with leading-TAB-then-TTL get
|
||||
# "@" prepended (Vultr's apex convention vs. RFC 1035 inheritance).
|
||||
# 4. Dot-terminate NS/MX/CNAME rdata (Vultr exports unqualified names).
|
||||
set -euo pipefail
|
||||
|
||||
SRC_DIR="${SRC_DIR:-zones}"
|
||||
DST_DIR="${DST_DIR:-zones-prepared}"
|
||||
ADMIN_EMAIL="${ADMIN_EMAIL:-admin}" # becomes admin.<zone>.
|
||||
|
||||
# Serial number generation — YYYYMMDDNN format (RFC 1912 §2.2).
|
||||
#
|
||||
# Strategy: every `make prep` run produces a strictly-increasing serial
|
||||
# so that HE slaves notice the change on their next poll. If today's
|
||||
# previous serials exist in zones-prepared/, increment the 2-digit
|
||||
# counter. Otherwise start at NN=01.
|
||||
#
|
||||
# Honors an explicit override: `SERIAL=2026051699 make prep` skips the
|
||||
# auto-detection.
|
||||
TODAY=$(date +%Y%m%d)
|
||||
if [[ -z "${SERIAL:-}" ]]; then
|
||||
# Pull the highest YYYYMMDDNN serial from currently-prepared zones
|
||||
# that starts with today's date. If none, default to NN=01.
|
||||
# `|| true` so a zero-match grep doesn't trip `set -e`. Empty $highest
|
||||
# then triggers the "first run of the day" branch below.
|
||||
highest=$(grep -hE '^[[:space:]]+'"${TODAY}"'[0-9]{2}[[:space:]]+;' "$DST_DIR"/*.zone 2>/dev/null \
|
||||
| awk '{print $1}' | sort -un | tail -1 || true)
|
||||
if [[ -n "$highest" ]]; then
|
||||
nn=$((10#${highest:8:2}))
|
||||
next_nn=$((nn + 1))
|
||||
if (( next_nn > 99 )); then
|
||||
echo "ERROR: serial counter exhausted for ${TODAY} (NN=99 reached)." >&2
|
||||
echo "Set SERIAL manually or wait until tomorrow." >&2
|
||||
exit 1
|
||||
fi
|
||||
SERIAL=$(printf "%s%02d" "$TODAY" "$next_nn")
|
||||
else
|
||||
SERIAL="${TODAY}01"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Public-facing nameservers (Hurricane Electric free secondary service).
|
||||
# These appear in NS records inside every zone so that recursive
|
||||
# resolvers fetching the zone learn the correct delegation.
|
||||
HE_NAMESERVERS=(
|
||||
"ns1.he.net."
|
||||
"ns2.he.net."
|
||||
"ns3.he.net."
|
||||
"ns4.he.net."
|
||||
"ns5.he.net."
|
||||
)
|
||||
|
||||
mkdir -p "$DST_DIR"
|
||||
|
||||
count=0
|
||||
for src in "$SRC_DIR"/*.zone; do
|
||||
fname=$(basename "$src")
|
||||
zone="${fname%.zone}"
|
||||
dst="$DST_DIR/$fname"
|
||||
|
||||
{
|
||||
echo "; Auto-prepared by scripts/prepare-zones.sh on $(date -Iseconds)"
|
||||
echo "; Source: $src"
|
||||
echo "\$ORIGIN ${zone}."
|
||||
echo "\$TTL 3600"
|
||||
echo "@ 3600 IN SOA ns1.he.net. ${ADMIN_EMAIL}.${zone}. ("
|
||||
echo " ${SERIAL} ; serial — bump per change (SERIAL=YYYYMMDDNN make prep)"
|
||||
echo " 300 ; refresh (5 min) — slaves poll us this often;"
|
||||
echo " ; tightened from 3600 to nudge HE's internal"
|
||||
echo " ; puller→anycast replication"
|
||||
echo " 120 ; retry (2 min) — kept < refresh per RFC 1912"
|
||||
echo " 604800 ; expire (1 week)"
|
||||
echo " 60 ; minimum (1 min) — negative-cache TTL on public"
|
||||
echo " ; resolvers; shrinks the window when an old"
|
||||
echo " ; NXDOMAIN keeps showing after we add a name"
|
||||
echo " )"
|
||||
echo ""
|
||||
# Inject HE nameservers as the authoritative NS set.
|
||||
for ns in "${HE_NAMESERVERS[@]}"; do
|
||||
echo "@ 3600 IN NS ${ns}"
|
||||
done
|
||||
echo ""
|
||||
|
||||
# Strip source's own $ORIGIN / $TTL / comments AND drop ns?.vultr.com
|
||||
# NS records (we just emitted HE's NS set above). Then run the awk
|
||||
# transformations for apex disambiguation and rdata dot-termination.
|
||||
grep -vE '^\$(ORIGIN|TTL)|^;' "$src" \
|
||||
| grep -vE '[[:space:]]NS[[:space:]]+ns[12]\.vultr\.com\.?[[:space:]]*$' \
|
||||
| awk '
|
||||
NF == 0 { print; next }
|
||||
{
|
||||
# (a) Detect Vultr-style apex line: leading whitespace, then TTL,
|
||||
# then "IN". Prepend "@" so the owner is explicit.
|
||||
if ($0 ~ /^[[:space:]]+[0-9]+[[:space:]]+IN[[:space:]]/) {
|
||||
sub(/^[[:space:]]+/, "@\t", $0)
|
||||
}
|
||||
|
||||
# (b) Dot-terminate trailing hostname for NS/CNAME/MX rdata.
|
||||
type = ""
|
||||
for (i = 1; i <= NF; i++) {
|
||||
if ($i == "NS" || $i == "CNAME" || $i == "MX") { type = $i; break }
|
||||
}
|
||||
if (type != "") {
|
||||
target = $NF
|
||||
if (index(target, ".") > 0 && substr(target, length(target), 1) != ".") {
|
||||
sub(/[[:space:]]+$/, "", $0)
|
||||
print $0 "."
|
||||
next
|
||||
}
|
||||
}
|
||||
print
|
||||
}
|
||||
'
|
||||
} > "$dst"
|
||||
count=$((count + 1))
|
||||
done
|
||||
|
||||
echo "Prepared ${count} zone files in ${DST_DIR}/ (serial=${SERIAL})"
|
||||
Loading…
Add table
Add a link
Reference in a new issue