BIND as a Hidden Primary
Run BIND as a hidden primary behind your firewall and let an external secondary answer the queries.
What a hidden primary is
A hidden primary holds the master copy of your zone, but it does not appear in the zone's NS records. Resolvers never ask it. Only your secondaries talk to it: they pull the zone with AXFR or IXFR and answer every public query. You edit the zone on the primary, and the secondaries follow within seconds.
This setup gives you three things:
- Your primary is not exposed to query floods or DDoS traffic. You can keep it on an internal network.
- You keep full control of the zone file, your tooling, and your change process.
- The public nameservers can be run by somebody else, on networks built for that load.
1. Declare the zone as primary
In named.conf, declare the zone with type primary. BIND versions before 9.16 use the
older keyword type master, which means the same.
The addresses above are the ones hiddenprimary.ch uses. If you use a different secondary, put its transfer addresses there instead. For hiddenprimary.ch, allow all four addresses: two hosts can connect to your primary, the transfer node and the standby that takes over when the transfer node is unavailable. If you leave the standby out, your zone stops updating during that time.
notify explicit tells BIND to send NOTIFY messages only to the servers in
also-notify. Without it, BIND also notifies every server named in the zone's NS records.
That does no harm, but it is traffic you do not need.
2. Lock transfers down with TSIG (recommended)
An address list works, but a shared TSIG key is stronger: a request without the key is refused, whatever address it comes from. A key-based rule also covers every host of your secondary at once, so you do not have to update it when the secondary adds a node.
Give your secondary the same key name, algorithm, and secret. The TSIG guide shows how to enter the key on hiddenprimary.ch.
3. Open the firewall
Zone transfers need two things through your firewall:
- Inbound TCP port 53 from the transfer addresses. AXFR and IXFR run over TCP.
- Outbound UDP port 53 to the notify addresses, so your NOTIFY messages arrive.
The secondary also asks for your SOA record over UDP to see if the serial changed. Allow inbound UDP port 53 from the same addresses as well.
4. Check the configuration and reload
5. Change the zone the right way
A secondary only pulls a new copy when the SOA serial goes up. Every time you edit the zone file, increase
the serial. A common format is YYYYMMDDNN, for example 2026092201 for the first
change on 22 September 2026. Then reload the zone:
If the zone accepts dynamic updates (for example for ACME DNS-01 challenges), rndc reload does
not read your edited file. BIND keeps the changes in a journal and ignores the file, but still reports
success. Use rndc freeze example.ch, edit the file, then rndc thaw example.ch.
6. Verify the transfer
Compare what your secondary serves with your own file. Check the content, for example one record you just changed. The serial alone can mislead you: if the secondary signs the zone with DNSSEC, it uses its own serial.
Common mistakes
- The serial did not change. The secondary sees the same serial and keeps its old copy.
- The firewall blocks TCP. The SOA check over UDP works, but every transfer fails.
- The zone's NS records still name the old provider. Resolvers prefer the NS records inside your zone over the delegation at the registry. Update both. The migration guide explains the order.
- The primary is listed in the NS records. Then it is not hidden: resolvers send it queries.
Next Steps
- Getting Started — add your zone on hiddenprimary.ch
- TSIG Setup — authenticate zone transfers
- DNSSEC on the secondary — sign without keys on your primary
- Knot DNS and NSD as a hidden primary