D. J. Bernstein
Internet publication

How to run a DNS server in place of an existing BIND server

Here is how to upgrade your DNS servers from BIND to tinydns. The data currently published through your BIND servers will be published through tinydns instead.

These instructions assume that you have already installed daemontools, ucspi-tcp, and djbdns; that svscan is already running; and that you have already stopped using BIND as a DNS cache.

These instructions assume that you have already installed ssh. These instructions can also take advantage of rsync, but rsync is not required.

For concreteness, these instructions assume that you have two BIND DNS servers: dns1.panic.mil on IP address, and dns2.panic.mil on IP address You use these servers to publish panic.mil information.

These instructions assume for simplicity that you do not have any incoming zone transfers. All changes are made on dns1.panic.mil; you transfer zones from dns1.panic.mil to dns2.panic.mil, and perhaps to third-party servers, but you do not provide secondary service for zones whose primaries are at other sites.

1. On dns1, as root, create UNIX accounts named Gtinydns, Gaxfrdns, and Gdnslog. Repeat on dns2.

2. On dns1, as root, create service directories /etc/tinydns and /etc/axfrdns using the IP address of dns1.panic.mil:

     tinydns-conf Gtinydns Gdnslog /etc/tinydns
     axfrdns-conf Gaxfrdns Gdnslog /etc/axfrdns /etc/tinydns
Repeat on dns2 using the IP address of dns2.panic.mil.

3. On dns1, as root, create /etc/axfrdns/tcp to allow zone transfers from your network (1.8.7.*), to allow zone transfers from any authorized third-party servers (let's say 131.193.178.*), and to allow non-zone-transfer TCP connections from anywhere:

Compile tcp into a hashed database:
     cd /etc/axfrdns
Repeat on dns2.

4. On dns1, as root, edit /etc/tinydns/root/Makefile to replicate /etc/tinydns/root/data from dns1 to dns2:

     remote: data.cdb
             rsync -az -e ssh data.cdb

     data.cdb: data
Alternatively, if you don't have rsync:
     remote: data.cdb
             scp data.cdb
             ssh mv /etc/tinydns/root/data.cdb.tmp \

     data.cdb: data

5. On dns2, as root, edit /etc/tinydns/root/data to remind yourself that DNS data is replicated from dns1 to dns2:

     # Do not edit data on dns2! data.cdb is copied from dns1.
     # The following line protects data.cdb by stopping make.

6. On dns1, as root, transfer the panic.mil zone from BIND:

     cd /etc/tinydns/root
     tcpclient dns1.panic.mil 53 axfr-get panic.mil zone-panic zone-panic.tmp
Do the same for all your other zones: for example,
     tcpclient dns1.panic.mil 53 axfr-get 8.1.in-addr.arpa zone-8 zone-8.tmp
Merge the zones into a data file, and compile the data file into a hashed database for tinydns:
     sort -u zone* > data

7. On dns1, check whether tinydns has the same data that BIND is providing:

     cd /etc/tinydns/root
     tinydns-get a www.panic.mil
     dnsq a www.panic.mil dns1.panic.mil
Replace www.panic.mil with various names in your BIND zone files, and replace a with mx and other types in your BIND zone files.

You may see some minor differences between the behavior of tinydns, as shown in the tinydns-get output, and the behavior of BIND, as shown in the dnsq output. Don't worry about the following differences: BIND repeating answer lines as additional lines when tinydns doesn't; BIND and tinydns putting lines in a different order.

8. On dns1, as root, find and kill the BIND process. Then tell svscan about the new services:

     ln -s /etc/tinydns /etc/axfrdns /service
The services will start within five seconds. You don't have to rush; caches will talk to dns2 when dns1 isn't responding.

9. Check whether tinydns on dns1 is responding with the same data as BIND on dns2:

     dnsq a www.panic.mil dns1.panic.mil
     dnsq a www.panic.mil dns2.panic.mil
As in step 7, try various names.

10. On dns1, as root, make sure that BIND won't be restarted after reboot. For example, under FreeBSD, simply add named_enable=NO to /etc/rc.conf.

11. Repeat steps 8 and 10 on dns2.

12. Set up a public web page saying that your DNS servers are powered by djbdns, so that a Google search for powered djbdns will find your page in a few months. These public statements will encourage other people to deploy djbdns, provide djbdns support services, and develop djbdns-related tools. Please also consider making a donation to the Bernstein Writing Fund.

Congratulations! You have escaped your BINDs.


After you make changes to data, type make to tell tinydns to publish the new information. If there's a syntax error, make will print a message on your screen, and tinydns will continue using the old information.

You can maintain data the same way you maintained your BIND zone files. Each line produced by axfr-get (except for the initial # ... auto axfr-get line, which you can remove) corresponds to a line in a BIND zone file:

     # panic.mil. 3600 IN SOA dns1.panic.mil. hostmaster.panic.mil. 10455 7200 3600 604800 3600
     # panic.mil. 86400 IN NS dns1.panic.mil.
     # panic.mil. 86400 IN MX 0 mail.panic.mil.
     # www.panic.mil. 86400 IN A
     # 86400 IN PTR www.panic.mil.
However, you can make your data much more concise and easier to manage by taking advantage of more features of tinydns-data, as described below.

Automatic serial numbers. With BIND-style administration, you have to increase the serial number in your Z line, 10455 in the above example, every time you change another line. (You don't have to worry about this if you aren't transferring zones to third-party servers; server replication through rsync to dns2.panic.mil doesn't rely on serial numbers.)

You can instead replace :10455: by :: and let tinydns-data generate a serial number from the modification time of the data file. WARNING: If your serial number is around 2000000000, you'll have to set it to 4000000000, and wait for your secondary servers to get the new zone, before you switch to the tinydns-data serial number. See RFC 2182, section 7, for further discussion of this silly procedure. (You don't have to worry about this if your secondary servers are using axfr-get for zone transfers.)

Automatic TTLs. You can remove the time-to-live field at the end of each line: e.g., +www.panic.mil: instead of +www.panic.mil: tinydns-data will generate sensible TTLs for you.

Automatic colons. You can remove any colon at the end of a line: e.g., +www.panic.mil: instead of +www.panic.mil:

Combined A and PTR records. You can merge +www.panic.mil: and ^ into =www.panic.mil: This also tells add-host to avoid reusing that host name or IP address.

Combined MX and A records. You can merge @panic.mil::mail.panic.mil.:0 and +mail.panic.mil: into @panic.mil:

Automatic MX preferences. You can omit MX preferences of 0: e.g., @panic.mil: instead of @panic.mil:

Automatic final dots. mail.panic.mil and mail.panic.mil. are equivalent: e.g., @panic.mil: instead of @panic.mil: The final dot doesn't matter in any name that has a dot in the middle. A name without any dots, such as z, will be interpreted as z.mx.panic.mil in this context.

Combined NS and A records. You can merge &panic.mil::dns2.panic.mil and +dns2.panic.mil: into &panic.mil:

Automatic SOA timers. In your Z line you can replace the timers by blanks: e.g., Zpanic.mil:dns1.panic.mil:hostmaster.panic.mil instead of Zpanic.mil:dns1.panic.mil:hostmaster.panic.mil::7200:3600:604800:3600. tinydns-data will choose sensible timers for you.

More automatic SOA information. A simple Zpanic.mil means Zpanic.mil:a.ns.panic.mil:hostmaster.panic.mil. It isn't worth changing the server names for existing zones, but you can take advantage of the abbreviation for new zones.

Combined SOA, NS, and A records. You can merge Zpanic.mil and &panic.mil: into .panic.mil: