named.conf, zone files, and rndc are the three operational surfaces you touch every day.ops.hexworth.com. — the trailing dot is the root. Read: host, then domain, then TLD, then root. Zone files require the trailing dot on all absolute names. Omit it and BIND appends the zone origin, silently misdelegating.
.com to Verisign. Verisign delegates hexworth.com to your name servers. You own everything below that cut. NS records are the delegation mechanism at every level.
A
ops 300 IN A 10.0.1.50
AAAA
ops 300 IN AAAA 2001:db8::50
CNAME
www IN CNAME ops.hexworth.com.
MX
@ IN MX 10 mail1.hexworth.com.
NS
@ IN NS ns1.hexworth.com.
PTR
50 IN PTR ops.hexworth.com.
SOA
@ IN SOA ns1... (2026040901 3600...)
@). 2. MX records must point to hostnames, never IP addresses, never CNAMEs.
allow-recursion { 127.0.0.1; 10.0.0.0/8; }; in named.conf.options.
dig +short A hostname against 8.8.8.8 directly. If that returns the correct answer but your host does not, the problem is your resolver cache or /etc/resolv.conf, not the authoritative server.dig @ns1.matrix.internal A ops.matrix.internal. Look for the aa flag in the response. No aa flag means you did not hit the authoritative server.named-checkzone matrix.internal /etc/bind/db.matrix.internal and named-checkconf. BIND silently refuses to load a zone with syntax errors. Always run both tools before reloading named./etc/bind/ or /var/cache/bind/. Files placed in /tmp or /home silently fail to load — named logs a permission denied, and the zone never starts.
type master — this server is authoritative, owns the writable zone file.type slave — pulls zone data from the master via AXFR zone transfer. Stored in /var/cache/bind/.
allow-transfer { none; }; in options. Override per-zone to permit only your secondary server IP. An open allow-transfer leaks your entire zone to any requester.
YYYYMMDDnn. The secondary compares its serial to the primary's. Equal or lower = no transfer. Wrong serial = stale secondary = split-brain DNS.
ops.matrix.internal (no dot) becomes ops.matrix.internal.matrix.internal. — silently wrong.
-e, a script that fails halfway keeps running. Commands after a failed cp or mkdir still execute, often with destructive results.-u treats unset variables as errors. Without it, rm -rf "$DIIR/" (typo: two I's) expands to rm -rf / and deletes the filesystem.trap 'rm -f "$TMPFILE"' EXIT runs whether the script exits normally, hits an error, or receives a signal. Temp files never leak.[[ ]] not [ ], quote every variable, use "$@" not $*."$VAR" not $VAR. An unquoted variable containing a space splits into two words. An unquoted * glob-expands against the filesystem. Both are silent, destructive bugs.
"$@" expands each argument as a separate quoted word. "$*" concatenates all arguments into one word. Always use "$@" in loops.
$?. 0 = success, non-zero = failure. Chain with && (run if previous succeeded) and || (run if previous failed).
local. Without it, the variable leaks to global scope and overwrites caller variables of the same name. Silent, intermittent, extremely hard to debug.
${NODES[@]} — all elements as separate words (correct in loops).${NODES[*]} — all elements joined (usually wrong).${#NODES[@]} — count.${!ASSOC[@]} — all keys of an associative array.
echo and command substitution: result=$(my_function).
/usr/bin:/bin. Commands in /usr/local/bin, /usr/sbin, or user-specific locations are not found. Always use absolute paths or set PATH explicitly at the crontab top.~/.bashrc or /etc/profile. Environment variables, aliases, and functions defined there are invisible. Scripts must be self-contained or explicitly source what they need.>> /var/log/myjob.log 2>&1Persistent=true catches missed runs (cron's biggest gap). After=named.service expresses dependencies. systemctl list-timers shows next scheduled run.
daily — once per day at midnight.weekly — Monday at midnight.*:0/15 — every 15 minutes.Mon..Fri 08:00 — weekdays at 8am.systemd-analyze calendar 'Mon..Fri 08:00'
named-checkzone validates BIND syntax; knowing DNS tells you whether the data itself is correct.dig-based health check catches DNS outages before users do. Persistent=true means a maintenance window does not silently skip the health check that was scheduled during it.set -euo pipefail and logging via tee turn a fragile script into one whose failures are visible in the job log rather than silently discarded.ufw allow 53 must be added for clients to reach it. The W2 default-deny policy means named will be silently unreachable without this rule.systemctl status named, journalctl -u named -p err, and the After=named.service dependency chain from Week 1 are the operational surface for all of BIND9's runtime behavior.www IN CNAME ops.matrix.internal (no trailing dot) makes BIND append the zone origin, creating the nonsense FQDN ops.matrix.internal.matrix.internal. Resolution silently fails.named-checkzone — it catches absolute name references missing the dot.YYYYMMDDnn. Force a secondary transfer immediately: rndc retransfer partner.examplerndc or named-checkconf. Both live in /usr/sbin. Cron's PATH is /usr/bin:/bin. Command not found. No output because output is not redirected. Job "runs" with no effect.PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin at the top of the crontab and redirect output: >> /var/log/job.log 2>&1set -e, a script that fails to create a directory will attempt to write files into a non-existent path. Without set -u, a typo in a variable name expands to empty string, silently processing nothing.set -euo pipefail. No exceptions for scripts that run unattended or modify system state.dig +short A ops.matrix.internal
dig -x 10.0.1.50 +short
sudo named-checkconf && echo OK
sudo rndc status
bash -n script.sh
sudo grep CRON /var/log/syslog | tail -10
systemctl list-timers --all