NSD¶
Catalog zones need NSD 4.9 or newer; Bindizr's interoperability run covers 4.14. An older NSD takes each zone by hand; see NSD before 4.9.
1. Register the secondary in Bindizr¶
Register the secondary's address so it receives NOTIFY and can transfer zones. This example uses a server on the same host, listening on port 53:
# A NSD on this host; elsewhere, its address or hostname
sudo bindizr secondary create nsd --address 127.0.0.1
For a remote server, use its address or hostname and Bindizr's reachable DNS address in the configuration below. Registration is also needed when using signed transfers, so NOTIFY reaches the server.
2. Configure the catalog zone¶
catalog: consumer marks the zone, and catalog-member-pattern names the
pattern every member zone is created with — so the pattern, not the catalog
zone, carries the primary those zones transfer from. Add this to
/etc/nsd/nsd.conf:
pattern:
name: "catalog-member"
zonefile: "members/%s.zone"
allow-notify: 127.0.0.1 NOKEY
request-xfr: 127.0.0.1@5300 NOKEY
zone:
name: "catalog.bindizr"
zonefile: "catalog.bindizr.zone"
catalog: consumer
catalog-member-pattern: "catalog-member"
allow-notify: 127.0.0.1 NOKEY
request-xfr: 127.0.0.1@5300 NOKEY
NSD writes each member's zone file itself, but not the directory holding them.
zonefile: is relative to zonesdir, which differs by distribution, so ask
NSD where it is:
sudo install -d -o nsd -g nsd "$(nsd-checkconf -o zonesdir /etc/nsd/nsd.conf)/members"
sudo nsd-checkconf /etc/nsd/nsd.conf
sudo systemctl restart nsd
3. Check a zone it learned¶
zonestatus reports the catalog member id the zone was provisioned under:
Example output:
zone: example.com
pattern: catalog-member
catalog-member-id: 33220188aa7541b8d3b935bd11880c49.zones.catalog.bindizr.
state: ok
served-serial: "12 since 2026-01-01T00:00:00"
Two defaults worth knowing¶
NSD holds a received transfer for up to xfrd-reload-timeout seconds — one by
default — before the serving process picks it up, so a change takes about a
second to become visible even though the transfer finished in milliseconds.
Reloading as each transfer lands costs CPU in proportion to how often zones
change, so it is a trade rather than a fix:
NSD also discards the deltas it receives unless told to keep them, and answers an inbound IXFR with a full transfer. This matters only where something pulls zones from NSD, such as a downstream secondary:
Bindizr's benchmark suite measures both: 1050ms versus 6.7ms p50 visibility, and 700 bytes versus 55KB for a single-record change on a 1000-record zone.
NSD before 4.9¶
An NSD without catalog zone support, such as the 4.6 Debian 12 ships, takes
each zone as its own zone: entry; the interoperability run covers 4.6,
signed and unsigned, with changes arriving as IXFR deltas:
zone:
name: "example.com"
zonefile: "example.com.zone"
allow-notify: 127.0.0.1 NOKEY
request-xfr: 127.0.0.1@5300 NOKEY
A zone created in Bindizr later needs its own entry, and a deleted one its
entry removed. Signing works as below, on each zone's request-xfr.
Sign the transfers¶
Declare the key, then name it in place of NOKEY on request-xfr — in the
pattern as well as the catalog zone, so member transfers are signed too:
key:
name: "xfr-key"
algorithm: hmac-sha256
secret: "<base64 secret from bindizr tsig-key create>"
pattern:
name: "catalog-member"
zonefile: "members/%s.zone"
allow-notify: 10.0.0.5 NOKEY
request-xfr: 10.0.0.5@5300 xfr-key
zone:
name: "catalog.bindizr"
zonefile: "catalog.bindizr.zone"
catalog: consumer
catalog-member-pattern: "catalog-member"
allow-notify: 10.0.0.5 NOKEY
request-xfr: 10.0.0.5@5300 xfr-key
Keep allow-notify on NOKEY unless the secondary is registered with
--notify-key; then use that key there too. See
Signed NOTIFY.
See Access Control
for creating the key in a role that holds zone:transfer in all zones.