How to run DNS with a hidden primary and public secondaries
Keep the master copy of your zones off the internet and let secondaries do the answering. Two ways to feed them with PowerDNS, DNSSEC included, and the checks.

The server where you edit your DNS zones does not need to answer the internet, and it should not. A hidden primary holds the authoritative copy and takes changes from your people and your automation. A set of public secondaries, which are the only servers listed in your NS records, answer every query. The primary can be patched, rebooted or attacked by nobody, because nobody outside knows where it is. This article shows how to build that with PowerDNS, the two ways to get data from the primary to the secondaries, and the checks that prove the primary really is hidden.
The shape of the design
- One primary on a private network, no public address, never named in NS or SOA records. It runs the API and the web interface your team uses.
- Two or more public secondaries in different sites, ideally on different networks and different providers or platforms, so no single failure takes them all out.
- A private path from the primary to each secondary, for replication only.
- Secondaries keep answering if the primary disappears. They hold a complete copy, so a dead primary means "no changes for a while", not "domain offline".
There are two ways to feed the secondaries. Both work; they suit different teams.
Option one: zone transfers with NOTIFY and TSIG
This is standard DNS and works with any mix of DNS servers. The primary sends a NOTIFY when a zone changes; the secondary checks the SOA serial and pulls the zone with AXFR or IXFR.
On the primary, in pdns.conf:
primary=yes
allow-axfr-ips=192.0.2.21/32,198.51.100.31/32
also-notify=192.0.2.21,198.51.100.31
only-notify=
Those addresses are the secondaries' private addresses. Leaving only-notify empty and listing targets in also-notify means NOTIFY goes only to your secondaries, never to whatever happens to be in the NS records.
Then sign the transfers. An IP allow list alone trusts the network; a TSIG key proves the request comes from your secondary.
# on the primary
pdnsutil generate-tsig-key xfr hmac-sha256
pdnsutil activate-tsig-key example.com xfr primary
pdnsutil list-tsig-keys # copy the secret
# on each secondary (pdns.conf contains: secondary=yes)
pdnsutil import-tsig-key xfr hmac-sha256 '<secret>'
pdnsutil create-secondary-zone example.com 203.0.113.10
pdnsutil activate-tsig-key example.com xfr secondary
Where 203.0.113.10 is the primary's private address. To avoid creating every zone by hand on every secondary, PowerDNS can create them automatically when the primary sends a NOTIFY for a new zone. Configure the primary as an autoprimary on each secondary:
pdnsutil add-autoprimary 203.0.113.10 ns1.example.net
and set autosecondary=yes on the secondaries.
Option two: native zones and database replication
PowerDNS can also skip DNS transfers entirely. Mark zones as NATIVE, keep them in a MySQL, MariaDB or PostgreSQL backend, and let the database replicate the primary's data to a read-only replica on each secondary.
pdnsutil set-kind example.com native
On each secondary, PowerDNS reads from its local replica database, configured read-only. Replication runs over the private network only.
Why choose this:
- Every change arrives as a row, as soon as the database ships it. There is no serial bump to forget and no NOTIFY to lose.
- AXFR can be switched off everywhere, so there is no transfer interface to protect at all.
- New zones appear on the secondaries automatically, because they are rows too.
- DNSSEC keys replicate along with the records, and each secondary signs answers itself.
Why not: every secondary must run the same backend, and you are now operating database replication, which needs its own monitoring for lag and broken threads. If your secondaries include another vendor's DNS, transfers are the only option.
We build ours with native zones and database replication, because it removes the transfer surface completely and makes the database the single, obvious source of truth.
DNSSEC with a hidden primary
Both options support signing:
- With transfers, sign on the primary. The secondaries receive the signed zone and serve it as presigned data; PowerDNS marks the zone
PRESIGNEDautomatically when it transfers signed records. - With database replication, the keys live in the database, so every secondary signs live with the same keys and answers identically.
Either way, test validation from outside with a validating resolver:
dig +dnssec example.com SOA @1.1.1.1
delv example.com SOA
delv should report "fully validated".
Name the right servers
The point of a hidden primary is lost if its name leaks into the records the world reads.
- NS records list only the public secondaries.
- The SOA MNAME field names a public secondary, not the primary. In PowerDNS,
default-soa-contentsets it for new zones; fix existing ones withpdnsutil edit-zone. - Glue at the registry points to the secondaries' public addresses only.
Some tools put the server's own name into the SOA MNAME by default. Check it on every zone, not just the first.
Lock each role down
- Put a DNS-aware front end such as dnsdist in front of each public secondary, to refuse amplification query types, rate limit, and drop queries for zones you do not serve.
- On the secondaries, refuse NOTIFY from anywhere except the primary, and refuse AXFR requests from the internet.
Check it from the outside
# NS and SOA name only public secondaries
dig +short NS example.com
dig +short SOA example.com
# Every secondary has the same serial
for ns in $(dig +short NS example.com); do
printf '%s ' "$ns"; dig +short SOA example.com @"$ns" | awk '{print $3}'
done
# Transfers are refused from the internet
dig AXFR example.com @ns1.example.net
# The primary does not answer from outside (expect a timeout)
dig example.com SOA @<primary-address> +time=2 +tries=1
Run the serial comparison continuously, not once. A secondary that stopped receiving updates keeps answering confidently with old data; the only symptom is a serial that falls behind. Alert on it, and alert if the primary's name or address ever appears in an NS or SOA record.
In short
The primary is where you edit, the secondaries are where the world asks, and the two meet only on a private network. Pick transfers if you mix DNS vendors, database replication if you want no transfer surface at all. Name only the secondaries, sign the zone, and watch the serials.
We build and run PowerDNS clusters this way for customers who want to own their DNS. If you are planning one, we are glad to help.
Published 22 October 2026.
All field notes