cheat-sheets

BIND 9

BIND 9 (named) is the reference authoritative and recursive DNS server. In a homelab it usually serves your own zone (home.example.com) with a primary and optional secondary, while a resolver such as Unbound or Pi-hole handles recursion for clients.

Documentation: BIND 9 Administrator Reference Manual · rndc Project: BIND 9 at ISC

Verification: rndc, named-checkconf and named-checkzone options were checked against the man pages in Ubuntu 24.04 (bind9, bind9-utils), and the example config and zone were validated with those two checkers. File locations are Debian and Ubuntu (/etc/bind/); other distributions differ. The configuration was not served to real clients.

Install and Service #

COMMANDDESCRIPTION
sudo apt install bind9 bind9-utils bind9-dnsutilsServer, checkers and dig
sudo systemctl enable --now namedStart now and at boot (the unit is also available as bind9)
sudo systemctl status namedService state
sudo journalctl -u named -fFollow logs

Check Before Reloading #

COMMANDDESCRIPTION
named-checkconfCheck named.conf and included files (no output means OK)
named-checkconf -zAlso test-load every primary zone
named-checkconf -pPrint the configuration in canonical form
named-checkconf -pxSame, hiding shared secrets
named-checkzone example.com /etc/bind/zones/db.example.comCheck one zone file
named-checkzone -i full example.com /etc/bind/zones/db.example.comStricter integrity checks

rndc #

rndc controls the running server over a local control channel; the Debian package sets up its key.

COMMANDDESCRIPTION
sudo rndc statusServer version, zone count, query log state
sudo rndc reloadReload configuration and changed zones
sudo rndc reload example.comReload one zone
sudo rndc reconfigPick up new or removed zones only
sudo rndc flushFlush the resolver cache
sudo rndc flushname <NAME>Remove one name from the cache
sudo rndc zonestatus example.comSerial, type and refresh times
sudo rndc retransfer example.comSecondary: force a fresh transfer
sudo rndc notify example.comPrimary: tell secondaries the zone changed
sudo rndc querylog on / offLog every query (noisy)
sudo rndc freeze example.com / thaw example.comPause dynamic updates to edit a zone file by hand, then resume

Primary Zone #

/etc/bind/named.conf.local:

text
zone "example.com" {
    type primary;
    file "/etc/bind/zones/db.example.com";
    allow-transfer { 192.0.2.54; };
    notify yes;
};

zone "2.0.192.in-addr.arpa" {
    type primary;
    file "/etc/bind/zones/db.192.0.2";
};

/etc/bind/zones/db.example.com:

text
$TTL 1h
@   IN SOA ns1.example.com. hostmaster.example.com. (
        2026110701 ; serial (YYYYMMDDnn)
        1h         ; refresh
        15m        ; retry
        1w         ; expire
        1h )       ; negative cache TTL
    IN NS  ns1.example.com.
    IN NS  ns2.example.com.
ns1 IN A   192.0.2.53
ns2 IN A   192.0.2.54
nas IN A   192.0.2.20
www IN CNAME nas

/etc/bind/zones/db.192.0.2:

text
$TTL 1h
@   IN SOA ns1.example.com. hostmaster.example.com. (
        2026110701 ; serial
        1h 15m 1w 1h )
    IN NS  ns1.example.com.
53  IN PTR ns1.example.com.
20  IN PTR nas.example.com.

Increase the serial on every change, otherwise secondaries do not transfer. Names ending in a dot are absolute.

Options #

/etc/bind/named.conf.options:

text
options {
    directory "/var/cache/bind";
    listen-on { 192.0.2.53; 127.0.0.1; };
    allow-query { 192.0.2.0/24; localhost; };
    recursion no;
    dnssec-validation auto;
};
OPTIONPURPOSE
recursion noAuthoritative only; never open to the internet as a recursive resolver
allow-queryWho may ask
allow-transferWho may fetch the whole zone (restrict to secondaries)
listen-onAddresses to bind
forwarders { ... };Send recursive queries to an upstream (only if recursion is on)
dnssec-validation autoValidate with the built-in trust anchor

Test #

bash
dig @192.0.2.53 www.example.com +short
dig @192.0.2.53 -x 192.0.2.20 +short
dig @192.0.2.53 example.com SOA +short
dig @192.0.2.53 example.com AXFR

See dig for more options.

Troubleshooting #

SYMPTOMFIX
Zone not loadedsudo journalctl -u named, then named-checkzone
Changes not visibleSerial not increased, or you forgot rndc reload
REFUSEDallow-query or recursion no blocks the client
Secondary out of daterndc zonestatus on both; rndc retransfer on the secondary; check allow-transfer and the firewall (TCP 53)
Permission denied reading a zone fileAppArmor on Ubuntu confines named to /etc/bind and /var/cache/bind; put zone files there
Dynamic update failsThe directory must be writable by named (/var/cache/bind or /var/lib/bind)

See Also #

Search all sheets

Tip: / or Ctrl/Cmd+K to open, Esc to close.