| name | linux-dns-server |
| description | Use when operating BIND or Unbound as an authoritative or recursive DNS server, including zone authoring, validation, reloads, reverse zones, transfers, and SELinux contexts. Use linux-network-admin for client-side resolution or interface configuration. |
| license | MIT |
| metadata | {"portable":true,"compatible_with":["claude-code","codex"],"author":"Peter Bamuhigire","author_url":"techguypeter.com","author_contact":"+256784464178"} |
Linux DNS Server
Distro support
BIND and unbound run on both families; dig, rndc, named-checkconf, and
named-checkzone are identical. The differences are package names, config
file locations, and SELinux. Body uses Debian/Ubuntu; the RHEL family
(Fedora, RHEL, CentOS Stream, Rocky, Alma, Oracle) equivalents are in the matrix.
| Concept | Debian/Ubuntu | RHEL family |
|---|
| BIND package | bind9 | bind |
| DNS utilities | dnsutils | bind-utils |
| systemd unit | named (alias bind9) | named |
| Main config | /etc/bind/named.conf* | /etc/named.conf |
| Zone files | /etc/bind/, /var/lib/bind/ | /var/named/ |
| Service user | bind | named |
| Validation tools | named-checkconf, named-checkzone, dig | identical |
RHEL-family gotcha: SELinux governs BIND. Zone files must carry the
named_zone_t context (restorecon -Rv /var/named) and writes to
/var/named need the right labels; serving from a non-standard path requires
semanage fcontext. There is no SELinux step on Debian/Ubuntu. (Deep SELinux
coverage lands in linux-server-hardening / Phase 2.)
In sk-* scripts use the common.sh primitives (pkg_install, svc_name)
instead of hardcoding the family. See linux-bash-scripting
and docs/multi-distro/plan.md.
Use when
- Managing authoritative DNS zones, records, serials, or server reloads.
- Validating zone files or setting up reverse DNS on Ubuntu/Debian.
- Debugging BIND9 or unbound behavior on a server that owns DNS service.
Do not use when
- The task is client-side DNS resolution from an application host; use
linux-network-admin.
- The task is mail authentication policy only; use
linux-mail-server.
Required inputs
| Artefact | Source | Required? | If absent |
|---|
| Zone name, current zone/config, server role, and software | Authoritative host or version control | required | Stay read-only and return discovery commands. |
| Requested records, TTL/serial policy, and delegation/transfer constraints | DNS owner/change request | required for change | Stop before editing or reloading. |
| Maintenance and rollback path | Service owner | required for mutation | Produce a proposed diff and validation plan only. |
Workflow
- Identify the zone and the authoritative server role before editing.
- Make the smallest correct record or config change and validate syntax first.
- Reload the service only after passing the relevant checks.
- Query the authoritative server directly to verify the expected answer.
- Stop if zone ownership, serial policy, validator output, transfer/recursion scope, or rollback is unresolved.
- Recover a failed reload by restoring the saved zone/config, validating it, reloading the prior version, and querying each authority again.
Quality standards
- Validate zone syntax before reload every time.
- Keep serial management explicit and predictable.
- Verify from the authoritative source, not only from cached resolvers.
Anti-patterns
- Editing a zone without advancing its serial. Fix: apply the site's serial policy exactly once per published change.
- Reloading
named before named-checkconf and named-checkzone. Fix: block reload on either validator failure.
- Querying only a caching resolver. Fix: query each authoritative server directly and then check public delegation.
- Allowing unrestricted recursion or zone transfer. Fix: restrict by role, network, TSIG, and explicit ACL.
- Bypassing an SELinux denial with permissive mode. Fix: restore correct zone paths/contexts and keep enforcement.
Outputs
| Artefact | Consumer | Acceptance condition |
|---|
| Zone/config change or diagnosis | DNS operator | Correct owner/name/type/value/TTL/serial and family-specific path/context are explicit. |
| Validation/reload evidence | Reviewer | Config and every changed zone validate before a successful reload. |
| Authoritative query record | Service owner | Expected answers and SOA serial are returned directly by every authoritative server. |
References
Evidence Produced
| Artefact | Acceptance condition |
|---|
| DNS change evidence | Includes reviewed diff, validators, reload result, direct answers from each authority, SOA serial, transfer result where relevant, and rollback. |
Capability contract
Read-only inspection is the default for diagnosis. Editing zones/configuration, reloading DNS, changing delegation, opening firewall access, or enabling transfer/recursion requires explicit authority. Do not expose TSIG private material.
Degraded mode
Without access to the authoritative host, validate supplied text where possible and mark live reload, delegation, propagation, and SELinux checks not assessed. Do not treat a local syntax pass as published DNS success.
Decision rules
| Choice | Action | Failure or risk avoided |
|---|
| Authoritative record change | Edit owner zone, advance serial, validate, reload, query authority | Stale or unpublished answers. |
| Client cannot resolve | Route to linux-network-admin first | Editing healthy authoritative zones. |
| Recursive resolver service | Restrict recursion to approved clients | Open-resolver abuse. |
Worked example
To add api.example.org A 192.0.2.40, confirm the authoritative zone and serial policy, edit the managed source, validate configuration and zone, reload, query each authoritative server with recursion disabled, and record the returned address, TTL, and new SOA serial.
This skill is self-contained. Every command below is a standard BIND
tool (named, rndc, named-checkconf, named-checkzone, dig) present on
both Debian/Ubuntu and the RHEL family; only package names and paths differ
(see Distro support). The sk-* scripts in the Optional fast path
section are convenience wrappers — never required.
This skill owns authoritative DNS serving — running BIND9 or unbound
as a server that answers queries for zones you control.
It does not own:
- Client-side DNS lookups from a server —
linux-network-admin.
- MX records and email auth —
linux-mail-server.
- DNS records at a registrar — those belong to whoever manages the
domain at its registrar; this skill handles self-hosted authoritative
DNS.
Informed by Linux Network Administrator's Guide (BIND chapters) and
the Canonical Ubuntu Server Guide (BIND9 packaging).
When to use
- Hosting authoritative zones for your own domains.
- Setting up a recursive resolver for an internal network.
- Validating zone files before reload.
- Debugging zone transfer failures or serial mismatches.
- Adding, removing, or editing DNS records in a managed zone.
- Setting up reverse DNS (in-addr.arpa / ip6.arpa).
When NOT to use
- Debugging outbound DNS from a server —
linux-network-admin's
diagnostics.
- Cloudflare / Route53 / Google Cloud DNS — those are managed DNS APIs.
Standing rules
- Always
named-checkconf before reloading. A bad config takes
down every zone.
- Always
named-checkzone for every modified zone. A bad zone
file takes down that zone.
- Bump the serial on every change. Format:
YYYYMMDDNN. Slaves
won't pull the change if the serial hasn't moved.
- Reverse zones must match forward zones. Every A record you own
should have a PTR in the in-addr.arpa zone you control (or upstream).
- Zone files live in
/etc/bind/zones/ by convention. Permissions:
bind:bind, mode 0644.
rndc reload <zone> is safer than systemctl reload bind9. It
reloads one zone at a time.
- Restrict recursion. Only answer recursive queries from trusted
networks. Open recursive resolvers are used in amplification attacks.
Quick reference — manual commands
Install and baseline
sudo apt install bind9 bind9-utils dnsutils
sudo systemctl status bind9 --no-pager
sudo journalctl -u bind9 -n 50 --no-pager
Validate and reload
sudo named-checkconf
sudo named-checkzone example.com /etc/bind/zones/example.com.zone
sudo rndc reload
sudo rndc reload example.com
sudo rndc dumpdb -cache
sudo less /var/cache/bind/named_dump.db
sudo rndc flush
Query your own server
dig @127.0.0.1 example.com SOA
dig @127.0.0.1 example.com NS
dig @127.0.0.1 example.com MX
dig @127.0.0.1 example.com A +all
dig @<public-ip> example.com SOA
dig @<master> example.com AXFR
Adding a record
sudo nano /etc/bind/zones/example.com.zone
sudo named-checkzone example.com /etc/bind/zones/example.com.zone
sudo rndc reload example.com
dig @127.0.0.1 new-record.example.com A +short
Full BIND9 reference (named.conf structure, options, logging, views,
TSIG, rndc control channel, systemd integration, common errors) — see
references/bind9-reference.md.
Full zone file syntax reference (SOA, NS, A, AAAA, CNAME, MX, TXT, SRV,
PTR, CAA, reverse zones, slave config, 4–6 complete examples) — see
references/zone-file-syntax.md.
Typical workflows
Workflow: Adding a record to a managed zone
sudo nano /etc/bind/zones/example.com.zone
sudo named-checkzone example.com /etc/bind/zones/example.com.zone
sudo rndc reload example.com
dig @127.0.0.1 new.example.com A +short
Workflow: Serial mismatch between master and slave
dig @master.example.com example.com SOA +short | awk '{print $3}'
dig @slave.example.com example.com SOA +short | awk '{print $3}'
sudo journalctl -u bind9 -n 100 --no-pager | grep -i -E "transfer|notify"
sudo rndc retransfer example.com
sudo ls /var/lib/bind/
Workflow: Validating a zone before import
named-checkzone example.com /tmp/imported-zone.zone
named-compilezone -o - example.com /tmp/imported-zone.zone | less
Workflow: Setting up a reverse zone for your subnet
sudo nano /etc/bind/named.conf.local
sudo named-checkconf
sudo named-checkzone 2.0.192.in-addr.arpa /etc/bind/zones/db.192.0.2
sudo rndc reload
dig @127.0.0.1 -x 192.0.2.10 +short
Troubleshooting / gotchas
- Zone loaded but queries return SERVFAIL. Check
named-checkconf
for missing includes. Check that the zone stanza in
named.conf.local points at a file BIND can read (bind:bind, mode
0644).
- Serial didn't increment, slaves aren't pulling. BIND compares
serial numbers literally — a new file with the same serial is treated
as identical. Always bump.
rndc reload works but queries show old data. BIND caches
recursive answers. sudo rndc flush clears the recursive cache; zone
data is authoritative and updates immediately.
- AXFR failing with "REFUSED". Master's
allow-transfer doesn't
list the slave's IP, or TSIG key mismatch.
- Running both
systemd-resolved and bind9. Port 53 conflict.
Disable resolved's stub listener: DNSStubListener=no in
/etc/systemd/resolved.conf, then systemctl restart systemd-resolved.
- Logs going to syslog with nothing in
/var/log/named.log. BIND
defaults to syslog (journalctl -u bind9). File logging requires
explicit logging { ... } stanzas — see the reference.
References
references/bind9-reference.md —
full BIND9 reference: named.conf structure, options, logging, views,
TSIG, rndc, systemd.
references/zone-file-syntax.md —
zone file syntax with all record types, reverse zones, slave config,
complete worked examples.
- Book: Linux Network Administrator's Guide — BIND chapters.
- Book: Ubuntu Server Guide — BIND9 package layout.
- Man pages:
named(8), named.conf(5), named-checkconf(8),
named-checkzone(8), rndc(8).
Optional fast path (when sk-* scripts are installed)
Running sudo install-skills-bin linux-dns-server installs:
| Task | Fast-path script |
|---|
| Validate a zone file + snapshot records for diff | sudo sk-dns-zone-check --file <path> |
| Checked-reload (config + each zone + verify serial bumped) | sudo sk-bind-reload [--zone <name>] |
These are optional wrappers around named-checkconf, named-checkzone,
and rndc.
Scripts
This skill installs the following scripts to /usr/local/bin/. To install:
sudo install-skills-bin linux-dns-server
| Script | Source | Core? | Purpose |
|---|
| sk-dns-zone-check | scripts/sk-dns-zone-check.sh | no | Validate a BIND zone file with named-checkzone, dump SOA/NS/A/MX, diff against previous snapshot. |
| sk-bind-reload | scripts/sk-bind-reload.sh | no | Run named-checkconf, named-checkzone for each modified zone, rndc reload, verify serial bumped. |