How to setup BIND9 Authoritative Name Servers on Ubuntu/Debian

In this tutorial we will be going through how to setup and configure BIND9 for Public DNS.

What is a Authoritative DNS Server?

You may have a domain name that’s been purchased from a Domain Registrar such as Namescheap, Godaddy etc, having your own DNS Servers which will handle name resolution for your domain. With your own DNS Server’s you no longer require to use Domain’s Registrars DNS Servers or a third party.

About BIND9

BIND which stands for (Berkeley Internet Name Domain) is opensource, flexible and full featured DNS software which is widely used on Linux & Unix, due to it’s reliability. It was originally developed by UC Berkeley, it was moved to ISC (Internet Systems Consortium INC.

BIND can be used in different variants from Authoritative, Resolver and Forwarder. However it’s good practice to separate the different rolls.

This Guide will work on Ubuntu 22.04/24.04, Debian 12.

Prerequisites

In order to follow this guide, you will require a Domain Name, if you don’t currently have a Domain Name then you can purchase one from a DNS Registrar such as Namescheap, Godaddy etc. I Recommend NamesCheap as their prices aren’t too bad.

You will need two servers, One Server for Master and the second as a Slave DNS Server in an event of a failure DNS Queries can still flow and resolve. Recommend ns1 in one location, ns2 in another. You can run ns1 on premise and ns2 on a cheap VPS. Due to design of DNS it is not recommend to run both on in the same location neither on the same subnet.

(Please note that if you plan on using this guide and your Public IP isn’t static then this guide won’t work.)

Each of the servers only need about 1 to 2GB of RAM, a good hosting provider that I recommend is Hetzner. VPS from €3.95 a month, I have tried different providers like Linode, DigitalOcean.

Once you have two Servers whether it’s on Premise and on a VPS or with two different providers, we can install BIND9.

Setting up Authoritative DNS Servers on Ubuntu/Debian.

Log into ns1 via SSH and run the following commands to install BIND9 on Ubuntu or Debian.

Recommend Installing all updates before proceeding.

apt update && upgrade -y

Set the Hostname for ns1, Be sure to change the domain to the one you have purchased.

nano /etc/hosts

127.0.0.1 localhost
127.0.1.1 ns1.your-domain.uk

Save and exit. CTRL X. Y to save.

nano /etc/hostname

ns1.your-domain.uk

Save and exit. CTRL X. Y to save. Be sure to reboot after changing hostname.

shutdown -r 

Once all updates are Installed and hostname is changed, we can now install BIND9.

apt install bind9 bind9utils bind9-doc

Check version number.

named -v

BIND 9.18.30-0ubuntu0.22.04.2-Ubuntu (Extended Support Version)
running on Linux x86_64 5.15.0-141-generic #151-Ubuntu SMP Sun May 18 21:35:19 UTC 2025
built by make with  '--build=x86_64-linux-gnu' '--prefix=/usr' '--includedir=${prefix}/include' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' '--sysconfdir=/etc' '--localstatedir=/var' '--disable-option-checking' '--disable-silent-rules' '--libdir=${prefix}/lib/x86_64-linux-gnu' '--runstatedir=/run' '--disable-maintainer-mode' '--disable-dependency-tracking' '--libdir=/usr/lib/x86_64-linux-gnu' '--sysconfdir=/etc/bind' '--with-python=python3' '--localstatedir=/' '--enable-threads' '--enable-largefile' '--with-libtool' '--enable-shared' '--disable-static' '--with-gost=no' '--with-openssl=/usr' '--with-gssapi=yes' '--with-libidn2' '--with-json-c' '--with-lmdb=/usr' '--with-gnu-ld' '--with-maxminddb' '--with-atf=no' '--enable-ipv6' '--enable-rrl' '--enable-filter-aaaa' '--disable-native-pkcs11' 'build_alias=x86_64-linux-gnu' 'CFLAGS=-g -O2 -ffile-prefix-map=/build/bind9-AB1uwX/bind9-9.18.30=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -fno-strict-aliasing -fno-delete-null-pointer-checks -DNO_VERSION_DATE -DDIG_SIGCHASE' 'LDFLAGS=-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'
compiled by GCC 11.4.0
compiled with OpenSSL version: OpenSSL 3.0.2 15 Mar 2022
linked to OpenSSL version: OpenSSL 3.0.2 15 Mar 2022
compiled with libuv version: 1.43.0
linked to libuv version: 1.43.0
compiled with libnghttp2 version: 1.43.0
linked to libnghttp2 version: 1.43.0
compiled with libxml2 version: 2.9.13
linked to libxml2 version: 20913
compiled with json-c version: 0.15
linked to json-c version: 0.15
compiled with zlib version: 1.2.11
linked to zlib version: 1.2.11
linked to maxminddb version: 1.5.2
threads support is enabled

By default, BIND will automatically start after installing, you can check the status with.

systemctl status bind9

named.service - BIND Domain Name Server
     Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled)
     Active: active (running) since Tue 2025-06-10 11:24:21 BST; 22s ago
       Docs: man:named(8)
   Main PID: 759221 (named)
     Status: "running"
      Tasks: 14 (limit: 18911)
     Memory: 8.9M (peak: 9.4M)
        CPU: 26ms
     CGroup: /system.slice/named.service
             └─759221 /usr/sbin/named -f -u bind

If BINDis not running, start it using.

systemctl start bind9

Enable BIND to auto start at boot.

systemctl enable named

BIND server will run as bind user, which is created during the installation and listens on TCP/UDP Port 53.

netstat -lnptu | grep named

cp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      759221/named        
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      759221/named        
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      759221/named        
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      759221/named        
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      759221/named        
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN      759221/named 

BIND has a daemon called named, A daemon is software that runs in the background. Named binary is installed by the BIND9 Package. The other part of uses something called rndc which we will cover further down the tutorial.

rndc status

version: BIND 9.18.30-0ubuntu0.24.04.2-Ubuntu (Extended Support Version) <id:>
running on localhost: Linux x86_64 6.11.0-26-generic #26~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Apr 17 19:20:47 UTC 2
boot time: Tue, 10 Jun 2025 10:24:21 GMT
last configured: Tue, 10 Jun 2025 10:24:21 GMT
configuration file: /etc/bind/named.conf
CPUs found: 6
worker threads: 6
UDP listeners per interface: 6
number of zones: 103 (98 automatic)
debug level: 0
xfers running: 0
xfers deferred: 0
soa queries in progress: 0
query logging is OFF
recursive clients: 0/900/1000
tcp clients: 0/150
TCP high-water: 0
server is up and running

Main BIND Configuration files are location /etc/bind/

  • /etc/bind/named.conf.options
  • /etc/bind/named.conf.local
  • /etc/bind/named.conf.default-zones

BIND9 Server provides recursive server for localhost (127.0.0.1) and local network clients, Since we are setting up authoritative DNS Servers, we need to disable recursion. Edit /etc/bind/named.conf.options.

cd /etc/bind/
nano named.conf.options

Add the following in options {…};

// hide version number from clients for security reasons.
version "not currently available";

// disable recursion on authoritative DNS server.
recursion no;

// enable the query log
querylog yes;

// disallow zone transfer
allow-transfer { none; };

Save and exit. CTRL X. Y to save.

Restart BIND

systemctl restart bind9

Master Configuration

Master DNS Server holds the master Zone, Changes are done on the Master DNS Server. The Zone on Master holds all the DNS Records like A, MX, CNAME, DKIM, SPF etc. DNS Servers can host multiple domains. (In this guide we will only cover one domain).

/etc/bind/named.conf.default-zones defines root zone as well as localhost zone. Add a zone for your domain name, edit /etc/bind/named.conf.local.

nano named.conf.local

zone "your-domain.uk" {
      type master;
      file "/etc/bind/db.domain.uk";
      allow-query { any; };
      allow-transfer { 1.2.3.4; };
};

Be sure to change your-domain.uk to the domain you have purchased, Allow transfer needs to be the IP Address of ns2.

The above configuration we created new zone and we specified this is the Master zone. Zone file is /etc/bind/db.your-domain.uk, where we add DNS Records, Zone transfer will only work for the IP address we specified in allow-transfer.

Instead of creating a zone file from scratch, we can use the zone template file. Copy the content of db.empty to /etc/bind/db.your-domain.uk.

cd /etc/bind/
cp db.empty db.your-domain.uk

Empty zone contains 3 types of enteries.

  • Comments: start with a semicolon (;)
  • Directives: start with a dollar sign ($)
  • Resource Records: DNS records

The forward zones consists of the following types of DNS Records.

  • The SOA (Start of Authority) record: defines the key characteristics of a zone. It’s the first DNS record in the zone file and is mandatory.
  • NS (Name Server) record: specifies which servers are used to store DNS records and answer DNS queries for a domain name. There must be at least two NS record in a zone file.
  • MX (Mail Exchanger) record: specifies which hosts are responsible for email delivery for a domain name.
  • A (Address) record: Converts DNS names into IPv4 addresses.
  • AAAA (Quad A) record: Converts DNS names into IPv6 addresses.
  • CNAME record (Canonical Name): It’s used to create alias for a DNS name.
  • TXT record: SPF, DKIM, DMARC, etc.

Lets create our new Zone. the db.your.domain.uk will contain the following,

; BIND reverse data file for empty rfc1918 zone
;
; DO NOT EDIT THIS FILE - it is used for multiple zones.
; Instead, copy it, edit named.conf, and use that copy.
;
$TTL    86400
@       IN      SOA     localhost. root.localhost. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                          86400 )       ; Negative Cache TTL
;
@       IN      NS      localhost.

We now need to add the correct DNS Records to the Zone as follows. Remember updating Serial is required when editing a Zone.

; zone file for your-domain.uk

$TTL    86400
$ORIGIN your-domain.uk. ; appended to unqualified records

@     IN    SOA     ns1.your-domain.uk. noc.your-domain.uk. (
                    2025061001          ; serial YYYYMMDDnn
                          3600          ; refresh ( 1 hour)
                          1800           ; retry ( 30 mins)
                          1296000       ; expire (15 days)
                          86400 )       ; minium ( 1 days)


; name servers - NS records
@       IN     NS      ns1.your-domain.uk.
@       IN     NS      ns2.your-domain.uk.

; Name records for this domain
ns1     IN      A       1.2.3.4
ns2     IN      A       5.6.7.8

; MX record for mail server
@       IN      MX      10      mx1.your-domain.uk.
@       IN      MX      20      mx2.your-domain.uk.

; A records for mail server
mx1     IN      A       10.11.12.13
mx2     IN      A       14.15.16.17

; A records for web services
@       IN      A       1.2.3.4
www     IN      A       1.2.3.4
mail    IN      A       1.2.3.4

; TXT records (SPF, DKIM, DMARC, CAA etc)
@       IN      TXT        "v=spf1 mx ip4:1.2.3.4 ip4:1.2.3.4 -all"
_dmarc.your-domain.uk. IN TXT "v=DMARC1; p=reject; sp=reject; adkim=r; aspf=r; pct=100; fo=1; rf=afrf; ri=86400; rua=mailto:abuse@your-domain.uk"

Be sure to update all Records you see above to correspond to the correct IP Address.

  • $TTL directive defines Time to Live value for the zone, which is the time a DNS record can be cached on a DNS resolver. This directive is mandatory. The time is specified in seconds.
  • $ORIGIN directive defines the base domain.
  • Domain names must end with a dot (.), which is the root domain. When a domain name ends with a dot, it is a fully qualified domain name (FQDN).
  • The @ symbol references to the base domain.
  • IN is the DNS class. It stands for Internet. Other DNS classes exist but are rarely used.

The first record in a zone file is the SOA (Start of Authority) record. This record contains the following information.

  • The master DNS server.
  • Email address of the zone administrator. RFC 2142 recommends the email address hostmaster@example.com. In the zone file, this email address takes this form: hostmaster.example.com because the @ symbol has special meaning in zone file.
  • Zone serial number. The serial number is a way of tracking changes in zone by the slave DNS server. By convention, the serial number takes a date format: yyyymmddss, where yyyy is the four-digit year number, mm is the month, dd is the day, and ss is the sequence number for the day. You must update the serial number when changes are made to the zone file.
  • Refresh value. When the refresh value is reached, the slave DNS server will try to read of the SOA record from the master DNS server. If the serial number becomes higher, a zone transfer is initiated.
  • Retry value. Defines the retry interval in seconds if the slave DNS server fails to connect to the master DNS server.
  • Expiry: If the slave DNS server has been failing to make contact with master DNS server for this amount of time, the slave will stop responding to DNS queries for this zone.
  • Negative cache TTL: Defines the time to live value of DNS responses for non-existent DNS names (NXDOMAIN).

TXT Records are enclosed with double quotes, if you add a DKIM Record you enclose the value with parentheses.

Save and exit. CTRL X. Y to save.

Run the following command to check if there are any syntax errors in the main forward zone.

named-checkzone your-domain.uk /etc/bind/db.your-domain.uk

Any syntax errors will need to be fixed before the zone will successfully load. Output from the above command you should see the following.

zone example.com/IN: loaded serial 2025061001
OK

We now need to use rndc, most people use systemctl restart bind9 this is okay but it can be very destructive and especially if you have Production DNS Servers with loads of zones, using rndc reconfig is better practice than restarting bind. rndc reconfig only reloads the service where restarting bind stops the service running for a few seconds then start the service.

rndc reconfig

If you are using ufw (uncomplicated firewall) you will need to allow Port 53 TCP/UDP.

ufw allow 53/tcp
ufw allow 53/udp

For iptables, run the following command.

iptables -A INPUT -p tcp --dport 53 -j ACCEPT
iptables -A INPUT -p udp --dprot 53 -j ACCEPT

Slave DNS Server Configuration

Be sure to edit the following cd /etc/bind/

cd /etc/bind/
nano named.conf.options

Add the following in options {...};

// hide version number from clients for security reasons.
 version "not currently available";

 // disable recursion on authoritative DNS server.
 recursion no;

 // enable the query log
 querylog yes;

 // disallow zone transfer
 allow-transfer { none; };

Save and exit. CTRL X. Y to save.

If you are using ufw (uncomplicated firewall) you will need to allow Port 53 TCP/UDP.

ufw allow 53/tcp
ufw allow 53/udp

For iptables, run the following command.

iptables -A INPUT -p tcp --dport 53 -j ACCEPT
iptables -A INPUT -p udp --dprot 53 -j ACCEPT

We now need to configure out slave server. make changes to /etc/bind/named.conf.local.

Add a Zone, Replace 1.2.3.4 with the IP Address of your Master DNS Server ns1.

zone "your-domain.uk" {
        type slave;
        file "db.your-domain";
        allow-query { any; };
        masters { 1.2.3.4; };
};

The above configuration, we specified that this is the slave DNS server for your-domain.uk. ns2 will accept zone transfers only from the IP we specified in master i.e 1.2.3.4. It is good practice that you restrict this to only allow Zones transfers from ns1.

Save and exit. CTRL X. Y to save.

Verify that there is no syntax errors.

named-checkconf

With the rndc command we need to re-config it’s config.

rndc reconfig

Now run the following to load the zone for your-domain.uk.

rndc reload your-domain.uk

The zone on the slave DNS server loaded from a zone transfer from ns1, after running both rndc reconfig and rndc reload your-domain.uk the Slave will load db.your-domain from the master ns1. to verifiy this you can run the following.

named[31918]: transfer of 'your-domain.uk/IN' from 1.2.3.4#53: Transfer completed: 1 messages, 16 records, 886 bytes, 0.004 secs (221500 bytes/sec)

More about Master and Zone Transfer

Slave DNS server contacts the master again when the refresh time in SOA record 3600 ; refresh ( 1 hour) reaches the freshhold and if the serial number on the master is greater than on the slave, a zone transfer will be initiated

Different types on Zone transfers.

  • Full zone transfer (AXFR): The full copy of zone file is transferred.
  • Incremental zone transfer (IXFR): Only DNS records that are changed are transferred.

The zone transfer uses Port 53.

Reverse DNS / PTR Record

Reverse DNS maps a IP address to a DNS Name, usually we don’t need to configure this on Authoritative Name Servers because this is more likely handled by your ISP. For Example if you are hosting a mail server that has a hostname of mail, your will need to request the ISP to set a PTR Record (Reverse DNS) that maps mail.your-domain.uk to 10.11.12.13. Without a valid PTR Record genuine mail servers will bounce back the mail.

NS Record and Glue Record

You now need to go to your Domain Registrar website to change the NS Record, so the internet would be able to see your Name Servers. Depending on your Registrar you use the hostname of both name servers.

ns1.your-domain.uk

ns2.your-domain.uk

With some Domain Registrar you may require adding the IP Addresses of both ns1.your-domain.uk and ns2.your-domain.uk.

Please be aware that it can take up 24 to 48 Hours for DNS to propagate around the world.

That’s it. Hope this tutorial helps you build your own DNS Authorative Name Servers. Please don’t hesitate to Contact if you have any problems.

Next we will go over configuring DNS Dynamic Updates for Lets Encrypt SSL Certificates. https://www.violetdragonsnetwork.co.uk/how-to-setup-bind9-rfc2136-lets-encrypt/

Scroll to Top