Skip to content

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:

sudo nsd-control zonestatus example.com

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:

server:
    xfrd-reload-timeout: 0

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:

pattern:
    name: "catalog-member"
    store-ixfr: yes

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.