Setting Up Your Own Linux DNS Server

Many teams want to control the domain name resolution for their application by setting up their own DNS server. This blog will show you how to do so using the BIND software package. If you need to understand more about DNS and how it works, this post is a great place to get started.

A Quick Intro to BIND

From the Udemy course on BIND1:

BIND is open source software that enables you to publish your Domain Name System (DNS) information on the Internet, and to resolve DNS queries for your users. The name BIND stands for “Berkeley Internet Name Domain”.

BIND is open source, it is one of the oldest, most widely used DNS servers, and it is super easy to set up.

Let's get started!


You can download the software through the BIND website or just use you native package installer like yum. It is also installed for you in the script in a later section.

yum install -y bind*  

We use the * because we want all BIND packages, especially bind-chroot and bind-utils. The service BIND uses is called "named", so you can check that the installation was successful by issuing the following command:

systemctl status named  

If everything went well your system should find the named service and we can move on to the configuration.

Configuring the OS and the 'named' Service Files

In this section, we will create and update the configuration files needed to ensure named is running properly. We will also make a few minor OS changes that are necessary if using CentOS 7 on AWS.

Rather than explain it all file by file, I have put the steps into a script. It should be pretty straightforward if you have a basic understanding of bash scripting. Just copy and paste the text below into a .sh file on your system and make sure it is executable by running chmod +x

The script will configure the OS, install bind, and configure all the appropriate files to get you up and running. I have left comments that explain each step (they have a # in front) and also summarized the steps below. You just need to change the $HOSTNAME and $DOMAIN variables.

  1. Set the hostname of your server
  2. Update the /etc/hosts file
  3. Remove any cloud configs that revert hostname changes
  4. Reboot the server
  5. Install bind
  6. Edit the /etc/named.conf file
  7. Create forward and reverse domain configs under /var/named
  8. Start the service
  9. Update IPtables or firewall rules as well as the AWS security group(s) to allow UDP on 53
  10. Test!
#Set variables to be used in the configuration of the OS and named service
#Hostname of the DNS machine  
#IP of the DNS machine
MY_IP=$(ifconfig -a | grep inet | awk '{print $2}' | sed -n '1p')  
#IP of the DNS machine reversed
REV_IP= $(echo $MY_IP | rev)  
#Last octet of the DNS machine IP
FINAL_OCTET=$(awk -F. '{print $NF}' <<< $MY_IP)

#Set the hostname of the server in all the appropriate places
hostnamectl set-hostname $HOSTNAME  
hostname $HOSTNAME  
sed -ie "s|^HOSTNAME=.*|HOSTNAME=$HOSTNAME|" /etc/sysconfig/network

#Add the hostname to the /etc/hosts file, overwriting what was there
echo "$MY_IP $HOSTNAME" >> /etc/hosts

#Remove unwanted cloud configs that overwrite the hostname upon machine reboot (if using AWS)
touch /etc/cloud/cloud.cfg.d/90_unmanage.cfg  
echo "preserve_hostname: true" > /etc/cloud/cloud.cfg.d/90_unmanage.cfg  
echo "manage_etc_hosts: false" >> /etc/cloud/cloud.cfg.d/90_unmanage.cfg

#Reboot to ensure all changes take effect

#Install the software
yum install bind* -y

#vim /etc/named.conf
#    - add IP to "listen-on" and "allow-query"

#Add appropriate zones to /etc/named.conf
echo "zone “$HOSTNAME” IN {" >> /etc/named.conf  
echo "type master;" >> /etc/named.conf  
echo "file “fwd.$DOMAIN”;" >> /etc/named.conf  
echo "allow-update { none; };" >> /etc/named.conf  
echo "};" >> /etc/named.conf  
echo " " >> /etc/named.conf  
echo "zone “$” IN {" >> /etc/named.conf  
echo "type master;" >> /etc/named.conf  
echo "file “rev.$DOMAIN”" >> /etc/named.conf  
echo "allow-update { none; };" >> /etc/named.conf  
echo "};" >> /etc/named.conf

#Create and populate the config files for forward and reverse domain lookup under /var/named
cd /var/named  
touch fwd.$DOMAIN  
echo "$TTL 86400" >> fwd.$DOMAIN  
echo "@     IN     SOA     ns.$HOSTNAME.     root.$HOSTNAME. (" >> fwd.$DOMAIN  
echo "             2019041801  ;Serial" >> fwd.$DOMAIN  
echo "             3600        ;Refresh" >> fwd.$DOMAIN  
echo "             1800        ;Retry" >> fwd.$DOMAIN  
echo "             604800      ;Expire" >> fwd.$DOMAIN  
echo "             86400       ;Minimum TTL" >> fwd.$DOMAIN  
echo ")" >> fwd.$DOMAIN  
echo "@     IN     NS      ns.$HOSTNAME." >> fwd.$DOMAIN  
echo "@     IN     A       $MY_IP" >> fwd.$DOMAIN  
echo "ns    IN     A       $MY_IP" >> fwd.$DOMAIN  
touch rev.$DOMAIN  
echo "$TTL 86400" >>rev.$DOMAIN  
echo "@     IN     SOA     ns.$HOSTNAME.     root.$HOSTNAME. (" >> rev.$DOMAIN  
echo "             2019041801  ;Serial" >> rev.$DOMAIN  
echo "             3600        ;Refresh" >> rev.$DOMAIN  
echo "             1800        ;Retry" >> rev.$DOMAIN  
echo "             604800      ;Expire" >> rev.$DOMAIN  
echo "             86400       ;Minimum TTL" >> rev.$DOMAIN  
echo ")" >> rev.$DOMAIN  
echo "@     IN     NS      ns.$HOSTNAME." >> rev.$DOMAIN  
echo "@     IN     A       $MY_IP" >> rev.$DOMAIN  
echo "$FINAL_OCTET    IN     PTR     ns.$HOSTNAME." >> rev.$DOMAIN

#Start the service with the new configs (or use restart if it was already running)
systemctl start named

#IPtables or firewall - enable tcp 53 and udp 53
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
-A OUTPUT -p udp -m udp --sport 53 -j ACCEPT

#Test that the named service is working properly
named-checkconf /etc/named.conf  
named-checkzone $HOSTNAME /var/named/fwd.$DOMAIN  
named-checkzone $HOSTNAME /var/named/rev.$DOMAIN  

There are a million reasons to set up your own DNS server, so I hope you found this information useful. Let me know if you have any questions!
[email protected]

For More

This page has a lot of really good, comprehensive information and examples of DNS.


  1. Basics of BIND