Week 3 Lecture Companion | Advanced Linux Administration

Lecture Companion  |  Week 3 of 4  |  CTS4321C · Course Objectives 5 & 6
Sector Authority —
DNS + BIND + Bash + Automation
The hardened box from Week 2 now needs a name, a voice, and a brain. DNS gives it identity. BIND makes it authoritative. Bash and cron make it self-operating.
26 Slides 4 Topic Blocks Infrastructure-Focused Bring a terminal
This deck is the instructor companion. The 4 topic decks (DNS Fundamentals, BIND9 Deployment, Bash Scripting, Linux Automation) hold the drilldown. This deck holds the throughline.
Slide 2 of 26  |  The Week Ahead
Four Stops, One Authority
Last week you locked the door. This week you hang a sign, give the place a name, and teach it to run itself.
1 DNS Fundamentals the naming layer hierarchy · records · resolution A, MX, CNAME, PTR, SOA ~12 MIN 2 BIND9 Deployment the authority named.conf · zone files · rndc forward + reverse zones ~12 MIN 3 Bash Scripting the language variables · conditionals · loops functions · set -euo pipefail ~12 MIN 4 Automation the scheduler cron · systemd timers · at idempotent · observable ~12 MIN ~50 minutes · 4 infrastructure layers · everything builds on Week 2's hardened foundation
Slide 3 of 26  |  The Big Picture
How These Four Fit Together
DNS names the infrastructure. BIND makes those names authoritative on your network. Bash writes the operations logic. Automation runs it without humans.
W2 HARDENED UFW + PAM + AV + apt DNS hierarchy + records BIND9 authoritative server BASH operations logic AUTOMATION cron + systemd timers Each layer depends on the previous. BIND serves names only if DNS concepts are right. Automation only works if scripts are sound.
DNS is the mental model
Before you type a single BIND directive you need to know what the hierarchy is, what each record type does, and why the SOA serial matters. Every misconfiguration traces back to a conceptual gap.
BIND is the implementation
BIND9 translates the DNS mental model into a running service. named.conf, zone files, and rndc are the three operational surfaces you touch every day.
Bash + cron close the loop
Scripts automate the work that ties the layers together: health checks on named, zone serial increment scripts, log rotation, backup jobs. Without automation, you are the cron daemon.
Slide 4 of 26  |  Topic 1: DNS Fundamentals
DNS: The Hierarchy in 60 Seconds
A distributed, delegated, globally consistent database. Authority flows downward from 13 root server clusters.
. (root) .com .org .net .io hexworth.com example.com ops. www. mail. delegation flows downward via NS
FQDN reads right to left
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.
Delegation is the core concept
The root delegates .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.
# Walk the hierarchy manually with dig $ dig NS . ; ANSWER: a.root-servers.net. ... m.root-servers.net. $ dig NS com. ; ANSWER: a.gtld-servers.net. ... m.gtld-servers.net. $ dig NS hexworth.com ; ANSWER: ns1.hexworth.com. ns2.hexworth.com. # +trace does the full walk in one command $ dig +trace A ops.hexworth.com ; root -> .com TLD -> hexworth.com auth -> answer
Slide 5 of 26
The Record Types You Must Know
DNS is not just an address book. Seven record types carry different data for different purposes. The quiz tests all seven.
A
name → IPv4 address
ops 300 IN A 10.0.1.50
AAAA
name → IPv6 address
ops 300 IN AAAA 2001:db8::50
CNAME
alias name → canonical name (not IP)
www IN CNAME ops.hexworth.com.
MX
mail routing, priority number (lower = preferred)
@ IN MX 10 mail1.hexworth.com.
NS
delegates zone to these name servers
@ IN NS ns1.hexworth.com.
PTR
IP → hostname (reverse lookup, lives in in-addr.arpa)
50 IN PTR ops.hexworth.com.
SOA
Start of Authority — zone metadata, serial, timing
@ IN SOA ns1... (2026040901 3600...)
Two rules that show up on every quiz
1. CNAME cannot coexist with other records at the same name — and cannot live at the zone apex (@). 2. MX records must point to hostnames, never IP addresses, never CNAMEs.
Slide 6 of 26
Resolution: Recursive vs. Authoritative
Two server roles that beginners constantly conflate. The distinction determines security posture, caching behavior, and zone ownership.
CLIENT getaddrinfo() RECURSIVE walks root → TLD → auth caches results for TTL duration 8.8.8.8 / 1.1.1.1 / unbound root . .com TLD auth server vs AUTHORITATIVE holds zone data, answers with aa (Authoritative Answer) does NOT recurse for external names BIND9 / NSD / PowerDNS Zone files it owns: hexworth.com. (forward) 1.0.10.in-addr.arpa. (reverse) queries for other zones: REFUSED
Security rule
An open recursive resolver — one that recurses for any internet client — enables DNS amplification DDoS attacks. Restrict recursion: allow-recursion { 127.0.0.1; 10.0.0.0/8; }; in named.conf.options.
Slide 7 of 26  |  DNS Synthesis
DNS Mental Model: Three Diagnostic Questions
When DNS is broken, students freeze. These three questions narrow any DNS failure to a single failure domain in under two minutes.
1
Is it a local cache problem?
Run 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.
2
Does the authoritative server have the record?
Query the authoritative server directly: 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.
3
Is the zone file syntactically correct?
Run 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.
Slide 8 of 26  |  Topic 2: BIND9 Deployment
BIND9: Install to Running in Five Steps
Berkeley Internet Name Domain 9. Install it, disable the systemd-resolved conflict, configure, validate, reload. Repeat the validate-reload cycle every time.
# Step 1: Install $ sudo apt update && sudo apt install -y bind9 bind9utils bind9-doc # Step 2: Disable systemd-resolved stub (conflicts on :53) $ sudo sed -i 's/#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf $ sudo systemctl restart systemd-resolved # Step 3: Verify named owns port 53 $ sudo ss -tulnp | grep ':53' udp UNCONN 0 0 0.0.0.0:53 *:* users:(("named",pid=3241,fd=20)) tcp LISTEN 0 10 0.0.0.0:53 *:* users:(("named",pid=3241,fd=21)) # Step 4 — after editing conf or zone files: ALWAYS validate first $ sudo named-checkconf $ sudo named-checkzone matrix.internal /etc/bind/db.matrix.internal zone matrix.internal/IN: loaded serial 2026040901 OK # Step 5: Reload (live reload — no service restart needed) $ sudo rndc reload server reload successful
AppArmor restricts named
Ubuntu ships AppArmor profiles for named. Zone files MUST live in /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.
Slide 9 of 26
named.conf: Three Files, One Config
Ubuntu splits BIND9 configuration across three included files. Know which one to edit for each type of change.
// named.conf.options -- global security posture acl "trusted" { 127.0.0.1; 10.0.0.0/8; 192.168.0.0/16; }; options { directory "/var/cache/bind"; recursion yes; allow-recursion { trusted; }; allow-query { trusted; }; allow-transfer { none; }; forwarders { 8.8.8.8; 1.1.1.1; }; forward only; dnssec-validation auto; listen-on { any; }; }; // named.conf.local -- your zones zone "matrix.internal" { type master; file "/etc/bind/db.matrix.internal"; allow-transfer { 10.0.1.11; }; notify yes; }; zone "1.0.10.in-addr.arpa" { type master; file "/etc/bind/db.10.0.1"; allow-transfer { 10.0.1.11; }; };
File responsibilities
named.conf — only includes the others. Never edit it.
named.conf.options — global options, ACLs, forwarders, recursion policy.
named.conf.local — your zone declarations.
named.conf.default-zones — root hints, localhost. Never edit it.
Zone types
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
Default is 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.
Slide 10 of 26
Zone File: SOA Serial Is the Clock
Every zone file starts with a SOA. The serial is the only field secondaries check before deciding whether to transfer. Forget to increment it and your secondaries never update.
; /etc/bind/db.matrix.internal (semicolons = comments in zone files) $TTL 3600 ; default TTL for records without an explicit TTL @ IN SOA ns1.matrix.internal. admin.matrix.internal. ( 2026040901 ; serial: YYYYMMDDnn -- MUST increment on every edit 3600 ; refresh: secondary re-checks primary every 1 hour 900 ; retry: on refresh failure, retry after 15 min 604800 ; expire: secondary stops answering after 7 days 300 ; minimum TTL (negative cache / NXDOMAIN TTL) ) ; NS records -- required, both must have glue A records @ IN NS ns1.matrix.internal. @ IN NS ns2.matrix.internal. ns1 IN A 10.0.1.10 ; glue record ns2 IN A 10.0.1.11 ; glue record ops IN A 10.0.1.50 db1 IN A 10.0.1.60 www IN CNAME ops.matrix.internal. ; trailing dot required @ IN MX 10 mail.matrix.internal. mail IN A 10.0.1.70 @ IN TXT "v=spf1 mx -all"
Serial increment rule
Increment the serial on EVERY zone file edit, no exceptions. Convention: YYYYMMDDnn. The secondary compares its serial to the primary's. Equal or lower = no transfer. Wrong serial = stale secondary = split-brain DNS.
The trailing dot rule
Any FQDN in a zone file requires a trailing dot. Without it, BIND appends the zone origin. ops.matrix.internal (no dot) becomes ops.matrix.internal.matrix.internal. — silently wrong.
Slide 11 of 26  |  Topic 3: Bash Scripting
Every Script Starts Here
The production script skeleton. Six lines at the top prevent an entire class of bugs. Non-negotiable for anything that runs unattended.
#!/usr/bin/env bash # script-name.sh — one-line description of what this script does # Usage: ./script-name.sh [OPTIONS] <argument> set -euo pipefail # exit on error, unset vars, pipe failures IFS=$'\n\t' # safe word splitting: newlines + tabs only # Constants (UPPER_CASE) readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly LOG_FILE="/var/log/sector/$(basename "$0" .sh).log" # Functions declared before main logic log() { echo "[$(date +%T)] $*" | tee -a "$LOG_FILE"; } die() { echo "[ERROR] $*" >&2; exit 1; } # Argument guard [[ $# -lt 1 ]] && die "Usage: $0 <node-name>" NODE="$1" # Temp file with automatic cleanup TMPFILE="/tmp/scan-$$-${NODE}.txt" trap 'rm -f "$TMPFILE"' EXIT log "Script started. Target: $NODE"
set -e exits on error
Without -e, a script that fails halfway keeps running. Commands after a failed cp or mkdir still execute, often with destructive results.
set -u catches typos
-u treats unset variables as errors. Without it, rm -rf "$DIIR/" (typo: two I's) expands to rm -rf / and deletes the filesystem.
trap EXIT = guaranteed cleanup
trap 'rm -f "$TMPFILE"' EXIT runs whether the script exits normally, hits an error, or receives a signal. Temp files never leak.
Slide 12 of 26
Conditionals + Loops: The Operational Core
Most real scripts are conditionals and loops. The key decisions: use [[ ]] not [ ], quote every variable, use "$@" not $*.
# [[ ]] is the bash conditional -- safer than [ ] if [[ -z "$TARGET" ]]; then die "TARGET is empty" elif [[ "$TARGET" == *".internal" ]]; then log "Internal host" else log "External host" fi # Regex test with =~ if [[ "$IP" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then log "Valid IPv4: $IP" fi # File tests [[ -f "$FILE" ]] && log "File exists" [[ -d "$DIR" ]] || die "Directory missing" [[ -x "$BIN" ]] || die "Not executable" # for loop over all arguments safely for node in "$@"; do ping -c1 -W1 "$node" >/dev/null 2>&1 \ && log "$node UP" || log "$node DOWN" done # while read loop -- safe for files with spaces while IFS= read -r line; do log "Processing: $line" done < /etc/hosts
Quoting rule: always double-quote
"$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.
$@ vs $*
"$@" expands each argument as a separate quoted word. "$*" concatenates all arguments into one word. Always use "$@" in loops.
Exit codes are your return values
Every command exits with $?. 0 = success, non-zero = failure. Chain with && (run if previous succeeded) and || (run if previous failed).
Slide 13 of 26
Functions + Arrays: Reusable Operations Logic
Functions give scripts structure and testability. Arrays hold ordered lists without the word-splitting hazards of flat strings.
# Functions: declare before calling check_service() { local svc="$1" # local = function scope only if systemctl is-active --quiet "$svc"; then log "[OK] $svc running" return 0 else log "[FAIL] $svc stopped" return 1 fi } check_service named || die "named is not running" # Arrays: indexed NODES=("ops" "db1" "mail" "ns1") echo "First node: ${NODES[0]}" echo "All nodes: ${NODES[@]}" echo "Count: ${#NODES[@]}" for node in "${NODES[@]}"; do check_service "$node" || true # || true: don't exit on failure done # Associative arrays (declare -A) declare -A SERVICES SERVICES["dns"]="named" SERVICES["web"]="nginx" SERVICES["db"]="postgresql" for role in "${!SERVICES[@]}"; do check_service "${SERVICES[$role]}" done
local scope is mandatory
Always declare loop counters and working variables inside functions with local. Without it, the variable leaks to global scope and overwrites caller variables of the same name. Silent, intermittent, extremely hard to debug.
Array expansion syntax
${NODES[@]} — all elements as separate words (correct in loops).
${NODES[*]} — all elements joined (usually wrong).
${#NODES[@]} — count.
${!ASSOC[@]} — all keys of an associative array.
Return values from functions
Bash functions return exit codes (0-255), not data. To return a string, use echo and command substitution: result=$(my_function).
Slide 14 of 26  |  Topic 4: Automation
Cron: The Five-Field Schedule
Five fields. The most common admin mistake is getting the order wrong. Burn this into memory: minute, hour, day-of-month, month, day-of-week.
MINUTE 0–59 HOUR 0–23 DAY OF MONTH 1–31 MONTH 1–12 DAY OF WEEK 0–7 (0=Sun) COMMAND /usr/local/bin/script.sh * * * * * command — every field * means "every valid value"
# Common patterns every admin must recognize 30 2 * * * /usr/local/bin/backup.sh # daily at 02:30 0 4 * * 1 /usr/local/bin/weekly-audit.sh # every Monday at 04:00 */15 * * * * /usr/local/bin/check-dns.sh # every 15 minutes 0 0 1 * * /usr/local/bin/monthly.sh # 1st of month at midnight 0 8 * * 1-5 /usr/local/bin/workday.sh # weekdays at 08:00 0 6,12,18 * * * /usr/local/bin/sync.sh # three times a day # /etc/cron.d drop-in format adds a username field 30 2 * * * root /usr/local/bin/sector-backup.sh >> /var/log/backup.log 2>&1
Slide 15 of 26
Why Cron Jobs Fail: The Environment Problem
Cron runs with a minimal environment. Jobs that work perfectly interactively fail silently in cron for one consistent reason: PATH.
Minimal PATH
Cron's default PATH is /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.
No profile loaded
Cron does not source ~/.bashrc or /etc/profile. Environment variables, aliases, and functions defined there are invisible. Scripts must be self-contained or explicitly source what they need.
Redirect output or lose it
Cron mails output to the local user account. On most production systems that mail queue is never read. Redirect both stdout and stderr: >> /var/log/myjob.log 2>&1
# Pattern: set PATH at the top of every crontab PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin MAILTO="" # suppress mail output SHELL=/bin/bash # Pattern: capture all output with a timestamp 30 2 * * * root /usr/local/bin/backup.sh \ >> /var/log/backup.log 2>&1 # Debug a failing cron job $ sudo grep CRON /var/log/syslog | tail -20 Jun 15 02:30:01 ns1 CRON[4421]: (root) CMD (/usr/local/bin/backup.sh) # Test the script in a cron-like environment $ env -i HOME=/root SHELL=/bin/bash PATH=/usr/bin:/bin \ /usr/local/bin/backup.sh bash: named-checkconf: command not found # Conclusion: add /usr/sbin to the script's PATH
Slide 16 of 26
systemd Timers: The Modern Replacement
systemd timers solve cron's two biggest problems: no logging integration and missed runs vanish silently. Use timers for new work on Ubuntu 22.04.
# Two files per timer: .service + .timer # /etc/systemd/system/dns-check.service [Unit] Description=DNS Health Check After=network.target named.service [Service] Type=oneshot ExecStart=/usr/local/bin/check-dns.sh StandardOutput=journal StandardError=journal SyslogIdentifier=dns-check # /etc/systemd/system/dns-check.timer [Unit] Description=DNS Health Check Timer [Timer] OnCalendar=*:0/15 # every 15 minutes Persistent=true # catch missed runs on next boot Unit=dns-check.service [Install] WantedBy=timers.target # Enable and start $ sudo systemctl enable --now dns-check.timer $ sudo systemctl list-timers --all $ journalctl -u dns-check.service -n 20
Why timers beat cron
Output goes to journalctl, no mail configuration needed. Persistent=true catches missed runs (cron's biggest gap). After=named.service expresses dependencies. systemctl list-timers shows next scheduled run.
OnCalendar syntax
daily — once per day at midnight.
weekly — Monday at midnight.
*:0/15 — every 15 minutes.
Mon..Fri 08:00 — weekdays at 8am.
Validate with systemd-analyze calendar 'Mon..Fri 08:00'
When to keep cron
Simple per-user jobs where a .service unit is overkill. Legacy scripts already deployed. Cross-platform scripts that need to run on non-systemd systems. For everything else on Ubuntu 22.04, use timers.
Slide 17 of 26  |  Synthesis
W3 in One Scenario: "The DNS Authority Node"
Build a self-operating, authoritative DNS server for the matrix.internal domain. Four Week 3 layers applied in order.
1 DNS DESIGN — choose record types before touching BIND A records for each host · PTR for reverse · MX for mail · CNAME for www alias · SOA serial YYYYMMDDnn 2 BIND9 DEPLOYMENT — validate every edit before reloading named-checkconf && named-checkzone matrix.internal /etc/bind/db.matrix.internal && rndc reload 3 BASH HEALTH SCRIPT — write check-dns.sh with set -euo pipefail dig @127.0.0.1 +short A ops.matrix.internal | grep -q "10.0.1.50" || die "DNS broken" 4 AUTOMATION — systemd timer runs check-dns.sh every 15 minutes OnCalendar=*:0/15 · Persistent=true · journalctl -u dns-check -f + RESULT — a self-monitoring authoritative DNS node names resolve correctly · secondaries stay in sync · anomalies auto-detected · logs in journalctl
Slide 18 of 26
The Cross-Connections
Week 3 topics are not isolated modules. Each touches the others in operational practice. These are the joints that make the system coherent.
DNS + BIND validation
You cannot correctly configure BIND zone files without understanding DNS record semantics first. named-checkzone validates BIND syntax; knowing DNS tells you whether the data itself is correct.
Bash + BIND operations
Zone serial increment, zone file templating, AXFR verification, and named reload are all repeatable operations — exactly what bash scripts are for. Scripting BIND operations turns a 10-step manual procedure into one idempotent command.
Automation + DNS health
A systemd timer running a 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.
Bash + automation
A cron job is only as reliable as the script it calls. 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.
W2 firewall + BIND
BIND listens on port 53 UDP and TCP. The UFW rule 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.
systemd + everything
named itself runs as a systemd service. 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.
Slide 19 of 26
Common Mistakes: What Goes Wrong
These are the four errors instructors see most often across labs. Each has an exact root cause and a two-command fix.
1
Missing trailing dot in zone file
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.
Fix
Every FQDN in a zone file ends with a dot. Run named-checkzone — it catches absolute name references missing the dot.
2
SOA serial not incremented after zone edit
Secondary name servers compare their serial to the primary. If the serial did not change, they do not transfer. Your edit is live on ns1 but ns2 serves stale data. Split-brain DNS follows.
Fix
Increment the serial before every zone reload. Convention: YYYYMMDDnn. Force a secondary transfer immediately: rndc retransfer partner.example
3
Cron job works interactively, fails silently
Script uses rndc 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.
Fix
Add 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>&1
4
Bash script continues after a failed command
Without set -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.
Fix
Line two of every script: set -euo pipefail. No exceptions for scripts that run unattended or modify system state.
Slide 20 of 26
The W3 Sector Authority Checklist
One page. Four categories. Every item is verifiable with a single command.
DNS Fundamentals
Can explain recursive vs. authoritative distinction
Knows all 7 required record types (A, AAAA, CNAME, MX, NS, PTR, SOA)
Understands TTL and its effect on caching
Can use dig to query any record type from any server
Knows why CNAME cannot live at zone apex
BIND9 Deployment
BIND9 installed and named owns port 53
named.conf.options restricts recursion to trusted ACL
Forward zone file passes named-checkzone
Reverse zone file created (PTR records match A records)
SOA serial uses YYYYMMDDnn format
Bash Scripting
All scripts start with #!/usr/bin/env bash + set -euo pipefail
All variable expansions double-quoted
Functions use local variables
Exit codes checked and logged
Temp files cleaned up via trap EXIT
Automation
At least one job scheduled (cron or systemd timer)
Cron jobs use absolute paths or explicit PATH= at top
All output redirected to a log file
systemd timer uses Persistent=true
systemctl list-timers shows next scheduled run
Slide 21 of 26
Verification: How to Confirm It Works
A configuration that cannot be verified is a guess. Each W3 layer has a specific command that proves operational state.
DNS
dig +short A ops.matrix.internal
Should return 10.0.1.50. Empty = record missing or named not running.
DNS
dig -x 10.0.1.50 +short
Reverse lookup. Should return ops.matrix.internal. Verifies PTR zone.
BIND9
sudo named-checkconf && echo OK
Zero output + exit 0 = named.conf is syntactically valid. Must run before every reload.
BIND9
sudo rndc status
Shows named version, uptime, and number of zones loaded. Confirms control channel works.
BASH
bash -n script.sh
Syntax-check without executing. Zero output = no syntax errors. Run before first deployment.
CRON
sudo grep CRON /var/log/syslog | tail -10
Confirms cron invoked the job. Check for CMD entry with correct command path.
TIMER
systemctl list-timers --all
Shows NEXT run time and LAST trigger. Confirms timer is active and scheduled correctly.
Slide 22 of 26
W3 Toolchain: One Reference View
Every command a student needs to operate this week's stack, grouped by layer. Print this. Tape it up.
DNS Diagnostics
dig A hostname — forward lookup
dig -x 10.0.1.50 — reverse lookup
dig MX domain — mail exchanger
dig +trace A hostname — walk hierarchy
dig @8.8.8.8 +short A host — bypass local resolver
nslookup hostname ns1.domain — quick test
BIND9 Operations
named-checkconf — validate config
named-checkzone zone /path/db — validate zone
rndc reload — live reload all zones
rndc reload matrix.internal — reload one zone
rndc status — daemon status
journalctl -u named -p err — errors only
Bash Validation
bash -n script.sh — syntax check only
bash -x script.sh — trace execution
shellcheck script.sh — static analysis
echo $? — last exit code
set -euo pipefail — safety harness
trap 'cleanup' EXIT — guaranteed cleanup
Automation Management
crontab -e — edit user crontab
crontab -l — list user crontab
grep CRON /var/log/syslog — cron log
systemctl list-timers --all — all timers
journalctl -u timer-name — timer output
systemd-analyze calendar 'daily' — validate schedule
Slide 23 of 26
Week 3 Complete — What Comes Next
Week 4 closes the loop: integrity verification, audit logging, and performance analysis on the infrastructure you now have running.
WEEK 1 — DONE Grid Connection CLI · systemd · ip · ss COs 1 & 2 covered WEEK 2 — DONE Perimeter Defense UFW · PAM · ClamAV · apt COs 3 & 4 covered WEEK 3 — DONE Sector Authority DNS · BIND · bash · cron COs 5 & 6 covered 4 WEEK 4 — NEXT Integrity Verification AIDE · audit · perf · logs knowing when something changed CTS4321C · DNS + automation running. Week 4 proves nothing changed without authorization.
Drilldown decks (this week)
ALA-W3-DNS · ALA-W3-BIND · ALA-05 Bash · ALA-06 Automation — ~138 slides
Before next class
W3 labs: BIND zone deployment, bash health script, systemd timer · Week 3 quiz (70% to pass)
W4: Integrity Verification
AIDE file integrity, auditd, performance analysis, log management. The system tells you what happened.
Slide 24 of 26
Discussion & Lab Bridges
Three open questions to drive discussion. No right answer in 30 seconds. Bring your reasoning.
DNS Question
You lower the TTL on an A record from 3600 to 60 seconds before a planned IP migration. What does that actually change about resolver behavior, and when should you lower it?
Thread pull: caching, stale records, migration windows, the 24-hour-ahead rule, vs. always keeping TTL low.
Bash Question
A bash script runs successfully in your terminal but fails every night in cron. What is your five-minute debugging procedure?
Thread pull: PATH, env -i test, output redirection, syslog grep, absolute paths vs. relative, set -x tracing.
Architecture Question
You have a cron job that has been running for 18 months. No one knows what it does or if it's still needed. What do you do before deleting it?
Thread pull: log analysis, process observation, disable vs. delete, change management, the we-do-not-destroy principle.
Slide 25 of 26  |  Sector Authority — Full Walkthrough
Sector Authority — The Full Walkthrough
Watch the week's four layers — DNS, BIND9, Bash, and automation — come together end to end on one box.
Slide 26 of 26
End of Week 3
DNS hierarchy, authoritative BIND9 deployment, bash scripting discipline, and cron + systemd automation. The sector now has a name, an authority, and a brain.
DNS hierarchy · records · dig COs 5 & 6 BIND9 named · zones · rndc COs 5 & 6 BASH set -euo · functions · trap COs 5 & 6 AUTOMATION cron · systemd timers COs 5 & 6 CTS4321C · sector authority established. Week 4 verifies nothing changed without authorization.