An authoritative DNS server is where the lookup for your domain ends: a resolver asks for www.example.com, the delegation leads to your server, and it answers from its own copy of the zone. Running your own is cheap and easy to get subtly wrong: two servers in one rack, an exposed primary, a DS record pointing at no key. Each takes down a whole domain. This setup avoids them: a hidden primary, three secondaries in different cities, Knot DNS and dig tests.
Authoritative is not recursive
A recursive resolver works for clients, walking from the root to whoever holds the answer and caching it. An authoritative server answers only for its own zones, from what RFC 2182 calls local knowledge.
An authoritative server that also recurses for anyone is an open resolver, which attackers use to aim replies at spoofed victims. Keep the jobs in separate programs: NSD describes itself as an authoritative name server, and Knot DNS's guide says to move any resolver on the same host off port 53.
Two servers is the rule, three is the advice
RFC 2182 starts from the registration rule of at least two servers per zone, then explains why two is thin: while one is down, the zone runs on the other alone. It recommends three for most organisation-level zones, "with at least one which must be well removed from the others."
It wants secondaries dispersed geographically and topologically. Separate cities survive a power cut at one site; separate networks survive a routing failure inside one provider. VPSes in Frankfurt, Amsterdam and Bucharest give you the first, but in one autonomous system, ours or anyone's, they miss the second. Put one secondary with another provider.
Hidden primary, public secondaries
The hidden primary holds the master copy and signs it, but is not in the NS records, so no resolver queries it; RFC 2182 calls this a stealth server. Its firewall admits only the secondaries, which are the listed servers.
On a change, the primary raises the SOA serial and sends a NOTIFY; each secondary pulls an IXFR (the differences) or AXFR (the whole zone), and the SOA refresh timer catches a lost NOTIFY. TSIG signs every NOTIFY and transfer with a shared secret, so only your primary can push changes and only your secondaries get the zone.
Serials only go up: RFC 2182 warns that secondaries ignore a decreased serial, and every later increment, until the old value is exceeded.
Knot DNS or NSD
|
Knot DNS |
NSD |
| TSIG transfers |
Yes |
Yes |
| DNSSEC signing |
Built in, automatic keys |
Not in its docs |
| Catalog zones |
Yes |
Yes |
| Docs highlight |
Signing, QUIC and TLS, query modules |
Raw performance, XDP |
NSD, BSD-licensed, aims to be a reference implementation for emerging IETF standards; for DNSSEC, sign the zone elsewhere. Knot signs and rolls keys itself, so the examples follow the Knot DNS 3.6.1 configuration guide. BIND and PowerDNS are the other mature choices; BIND can also resolve, so confirm recursion is off.
A minimal Knot DNS configuration
Generate a shared secret with keymgr -t xfr_notify_key and use it on all four machines. The hidden primary's /etc/knot/knot.conf:
server:
listen: 192.0.2.10@53
listen: 2001:db8:10::10@53
automatic-acl: on
log:
- target: syslog
any: info
key:
- id: xfr_notify_key
algorithm: hmac-sha256
secret: <the secret printed by keymgr -t>
remote:
- id: ns1
address: [198.51.100.11, 2001:db8:11::11]
key: xfr_notify_key
- id: ns2
address: [198.51.100.22, 2001:db8:22::22]
key: xfr_notify_key
- id: ns3
address: [198.51.100.33, 2001:db8:33::33]
key: xfr_notify_key
policy:
- id: ecdsa
algorithm: ECDSAP256SHA256
zsk-lifetime: 60d
zone:
- domain: example.com
storage: /var/lib/knot/zones/
file: example.com.zone
semantic-checks: on
notify: [ns1, ns2, ns3]
dnssec-signing: on
dnssec-policy: ecdsa
With automatic-acl on, remotes in notify may transfer the zone if they sign with the key; an explicit acl with address, key and action: transfer is the alternative. Each secondary, differing only in listen:
server:
listen: 198.51.100.11@53
listen: 2001:db8:11::11@53
automatic-acl: on
key:
- id: xfr_notify_key
algorithm: hmac-sha256
secret: <the same secret>
remote:
- id: primary
address: [192.0.2.10, 2001:db8:10::10]
key: xfr_notify_key
zone:
- domain: example.com
storage: /var/lib/knot/zones/
master: primary
Secondaries receive the zone signed. The policy creates keys on first load and rolls the ZSK; the default ksk-lifetime is infinite, so the KSK and your DS stay put. Keys live in the KASP database, so keep its permissions tight. Apply changes with knotc reload.
Glue and the registrar
At the registrar, list the three secondaries as NS, never the primary, matching your zone's NS set. If the servers are named inside the domain they serve, nobody can find ns1.example.com without asking ns1 first, so the parent publishes the address beside the delegation. That is glue, usually registered as a host or child name server.
$ORIGIN example.com.
$TTL 3600
@ SOA ns1.example.com. hostmaster.example.com. (
2026102501 3600 900 1209600 3600 ) ; serial refresh retry expire negative
NS ns1.example.com.
NS ns2.example.com.
NS ns3.example.com.
ns1 A 198.51.100.11
ns1 AAAA 2001:db8:11::11
Confirm each secondary answers authoritatively, then register the glue, then switch the NS list.
DNSSEC without breaking your own domain
The parent publishes a DS record fingerprinting your key-signing key. An unsigned zone simply resolves; a zone whose DS matches no published key gets SERVFAIL from validating resolvers for every name.
- Enable signing and let the signed zone reach every secondary.
- Check each secondary serves RRSIG records.
- Knot's docs say a new KSK starts in the ready state, when the server publishes CDS and CDNSKEY records. Query them and enter the values in the registrar's DS form.
- Confirm validation from outside.
To turn DNSSEC off, or move to servers with different keys, change the DS first and wait out its TTL. Signatures also expire: if the primary stays down past their validity, the zone fails while every secondary looks healthy.
Rate limiting against reflection
Refusing recursion is not enough: small queries with a forged source draw larger answers, signed ones especially, onto the victim. Response rate limiting caps how fast answers repeat to one destination. In Knot it is the mod-rrl query module, enabled per zone with module or everywhere with global-module; the docs load mod-cookies before it.
TTLs for planned changes
- Records: lower a TTL one old TTL ahead. At 86400 seconds, publish the short value 86,400 ÷ 3,600 = 24 hours before the change.
- SOA expire: how long a secondary serves without reaching the primary. Make it weeks (1209600 is 14 × 86,400 seconds), so a dead primary is an inconvenience, not an outage.
- Changing NS: keep the old servers answering until the parent's TTL on your delegation has passed.
Testing with dig
dig +norec @198.51.100.11 example.com SOA # authoritative: "aa" in the flags
for ns in 192.0.2.10 198.51.100.11 198.51.100.22 198.51.100.33; do # same serial everywhere
printf '%s ' "$ns"; dig +norec +short @"$ns" example.com SOA | awk '{print $3}'
done # run from a host the primary's firewall admits
dig +nssearch example.com # SOA from every listed server
dig +trace example.com NS # the delegation from the root down
dig +norec +dnssec @198.51.100.11 example.com SOA # expect RRSIG records
dig +norec @198.51.100.11 example.com CDS # what the registrar's DS form needs
dig +short example.com DS # what the parent publishes
delv example.com SOA # validates from built-in root trust anchors
dig @198.51.100.11 example.org A # not an open resolver: REFUSED, no "ra" flag
Monitoring serial drift and expiry
A secondary that stops transferring keeps serving its old copy until the zone expires. Signing re-signs the SOA on every run, so compare secondaries with the primary, not a fixed serial:
#!/bin/sh
zone=example.com
want=$(dig +norec +short @192.0.2.10 "$zone" SOA | awk '{print $3}')
for ns in 198.51.100.11 198.51.100.22 198.51.100.33; do
got=$(dig +norec +short +time=3 +tries=2 @"$ns" "$zone" SOA | awk '{print $3}')
[ "$got" = "$want" ] || echo "WARN $ns serves ${got:-nothing}, primary has $want"
done
dig +norec +dnssec @198.51.100.11 "$zone" SOA | awk '$4=="RRSIG" {print $9}' # RRSIG expiry, YYYYMMDDHHMMSS
Alert on drift longer than the refresh interval and on signatures near expiry; dedicated server monitoring covers the alerting. If a secondary is unreachable from one region, an mtr report shows where the path breaks.
Sizing: a small VPS is plenty
The work is answering small UDP queries. At an assumed 500 bytes per response, a 1 Gbps guarantee covers 1,000,000,000 ÷ (500 × 8) = 250,000 responses per second. Signing, the CPU work, happens on the primary.
Our entry unmetered VPS, one dedicated 3.2 GHz vCPU, 4 GB DDR4, 50 GB NVMe and 1 Gbps guaranteed, is €29 a month (checked October 2026) in Frankfurt, Amsterdam, Paris, Madrid, Milan, Vienna, Dublin and Bucharest. Three secondaries cost 3 × €29 = €87; a hidden primary makes €116. All share AS 25198, so the well-removed server belongs elsewhere; how to choose a VPS covers what to check there.
When managed DNS or anycast wins
- You do not want to be on call for the service everything depends on.
- You need GeoDNS or health-checked answers, covered in build your own CDN.
- Your domain attracts floods that three unicast servers cannot absorb.
- You want anycast, which needs your own prefix and BGP; see announcing your own IP space.
A middle path keeps the primary and keys yours, with secondaries at a provider that accepts NOTIFY and TSIG transfers.
Frequently asked questions
What is an authoritative DNS server?
An authoritative DNS server holds the records for a zone and answers queries about it from its own copy, without asking any other server. Every lookup for your domain ends there. A recursive resolver does the opposite job, querying other servers for a client and caching what it finds.
How many authoritative DNS servers does a domain need?
Registries require at least two. RFC 2182 recommends three for most organisations, with at least one well removed from the others, because a zone with two servers runs on one whenever either is down. Spread them across cities and onto more than one provider's network.
Can an authoritative server also be a recursive resolver?
It should not be. Combining both on one public address makes an open resolver, which strangers use for lookups and attackers use to reflect traffic at victims. Run any resolver as a separate program for your own machines, and check that the authoritative server refuses domains it does not host.
What happens if the DS record is wrong?
Validating resolvers treat the zone as broken, not unsigned, and return SERVFAIL for every name in it. Add the DS only after every secondary serves signed answers. When switching DNSSEC off or changing keys, update the DS first and wait out its TTL before retiring old keys.