Table of Contents

1. Introduction

Setting up and hosting your own domain name is easy! This document will
hopefully give you all the information you need to set one up using BIND 9.

2. The Domain Name System

If you already know how DNS works, you can skip this section. It is intended
as a brief introduction to the complex behavior of the DNS system in general.

When you perform a DNS query, you are attempting to find the/an IP address
associated with a particular domain name. You as an end user generally have
two DNS servers that you always use to perform lookups. These are generally
run by either you or your Internet access provider, and in most Unix-like
platforms, are listed in /etc/resolv.conf.

When you send a query to your local nameserver, it first looks to see if it is
hosting the domain about which you’re requesting information. If it is, it
simply looks up the information locally and sends the response to you.

If it doesn’t host that domain, it looks to see if it has recently answered a
query for the same record as you are requesting. If it has, and the
Time-To-Live on the cached record data has not yet expired (meaning the record
is still current enough to be accurate), it then just returns the answer from
its cached data.

If it doesn’t have the data cached, and it is set up as a recursive nameserver
(one that will perform the subsequent requests on your behalf instead of
making you do it), it must fetch an authoritative answer. Since it is
impossible to know what the authoritative server is for a particular zone,
that information must be maintained centrally. The servers that store this
information are known as the "root" nameservers. There are currently 13 of
them, with DNS names of A.ROOT-SERVERS.NET through M.ROOT-SERVERS.NET. If
these servers were all to go down, the Internet would become practically

Once your local DNS server has queried a root nameserver for the requested
domain’s authority information, it is given a (short) list of servers that
will be able to return authoritative data for the domain under which your
requested record resides.

It then sends a query to the authoritative servers in turn until it receives
an answer. It then relays the answer to you.

The highly distributed nature of DNS can cause many headaches when you need to
make any changes to a domain’s authoritative servers or any of its records.
Changes can take days to propagate, and knowing how to minimize your downtime
is very important.

3. DNS Hosting Requirements

If you wish to host your own domain name, there are some prerequisites that
must be satisfied.

First, your DNS servers must have completely static IP addresses. Any change
to your IP address will make your domain name completely useless.

Second, you must have one server to function as the primary nameserver, and at
least one separate machine to host the secondary nameserver(s). These are the
servers that will answer DNS queries for your domain in the event that your
primary DNS server is unavailable.

Usually, one of your friends will be willing to be the secondary nameserver
for your domain in return for the same from you. If you don’t have any
friends, you can use www.secondary.com which will be your backup name server
for free.

4. Setting it all up

The steps involved in setting up your own domain name are as follows:

4.1. Register your domain name with a domain name registrar.

You can use any registrar such as http://netsol.com/,
http://gandi.net/, or http://joker.com/. The domain name will cost you
between $8 and $20 per year depending on where you register it.

Some features to look for with a registrar are the ability to make ALL
changes online, especially your administrative and technical contact
information and the name servers registered as authoritative for your

4.2. Register your DNS servers with your registrar, if necessary.

Many registrars require that you register your name servers’ IP addresses
with them before they allow you to use them for your domain. Follow the
instructions on their website to set these up.

You may need to have the DNS server already running on the IP address
before registering it with them, but in most cases, you can just do it
right now. If they request a name for the DNS server, you should use
something like ns1.yourdomain.com and

4.3. Register your DNS servers as authoritative for your domain.

Once you’ve registered the DNS servers, you will need to edit your domain
information and change the name servers listed on there to
ns1.yourdomain.com and ns2.yourdomain.com (assuming that’s what you named

It will now take between 24 and 48 hours for this new domain to be
propagated to the root nameservers, so you will only be able to use it
from your own machine for a while, provided you have set your own
machine’s primary DNS server to in /etc/resolv.conf.

4.4. Install BIND on your host(s) and perform the basic configuration.

I won’t go into the specifics of how to perform the basic installation
(It’s pretty much a straight ./configure && make && make install)
You can download the BIND 9 tarball here:


If you don’t like building from a tarball, you can probably find a package
of BIND made just for your Linux distribution.

4.5. Perform basic configuration

Once you have BIND installed, you will need to create /etc/named.conf.
There are some example configurations in the ARM (see Resources section).
I will go over the basic options that you’ll need to get a more-or-less
typical setup working.

The named.conf syntax is very rigid, but pretty straightforward. Mostly
everything is either just a statement followed by a semicolon, e.g.:

file "example.com.db";

or a block-style option, which requires a semicolon after the closing
brace, as well as after each sub-block’s closing brace, and after each
simple statement it contains:

allow-transfer {;;

The most basic configuration, which will probably suit most needs just
fine, starts out with an options block like this:

options {
/* Base dir; where to look when we see a relative pathname */
directory "/var/named";

/* Write a pidfile on startup so we know the pid of named */

pid-file "/var/run/named.pid";

/* Allow anyone to perform DNS queries to this server */
allow-query { any; };

/* Perform recursive queries for clients. This helps build a cache
* of DNS data, so that fewer external requests are generated in

* the future. */
recursion yes;

/* What interfaces for BIND to listen on */
listen-on {;; };

/* When a change is made to any of the zones for which we are the
* master server, notify the slaves of the update immediately */

notify yes;

Now we need to specify the base zone "." which is used when we need to
make external requests.

zone "." in {
type hint;

file "root.hint";

The file root.hint is found in /var/named/root.hint since we specified
/var/named in the directory directive above. The "type hint;" directive
indicates that this zone file is a listing of the root nameservers, which
provide a "hint" to point you to the authoritative server for a domain.
The root.hint file looks like this. You never need to modify it:



; continue in this fashion...



Now we need reverse resolution for the 127.* range of IP addresses. The
following zone will do it:

zone "0.0.127.in-addr.arpa" in {
type master;
file "0.0.127.in-addr.arpa";

allow-update { none; };

The backwards "in-addr.arpa" system is used to reverse resolve IP
addresses to domain names. It’s a long story why this is the case, but in
a nutshell, it is so that forward resolvers don’t have to be entirely
rewritten to perform reverse resolution as well.

The 0.0.127.in-addr.arpa zone file is very simple, only listing a record
for, or to resolve to "localhost":

@INSOAlocalhost. root.localhost.(

1997022700 ; Serial
28800; Refresh
14400; Retry
3600000; Expire
86400 ); Minimum


I will go over the meaning of these records in more detail when we get to
the section on configuring our zone files.

Finally, let’s set up forward resolution for the "localhost" hostname:

zone "localhost" in {
type master;
file "local";
allow-update { none; };

The "local" file is also very simple; it maps "localhost" to

$TTL 21600
@ IN SOA @ root.localhost. (

86400 )
@ IN NS localhost.
@ IN A

Finally, we must set up a shared key to allow the use of the "rndc" tool
to control the server. The reason it must use a key is that rndc can be
used from any host on the Internet, so we must be able to verify that it
is authorized, as well as be able to encrypt its data.

Before we can add the shared key section to the named.conf, however, we
must, run the rndc-confgen program that comes with bind. This program
generates the content for /etc/rndc.conf for you automatically, with a
randomly generated key. Its output will look something like this:

# Start of rndc.conf
key "rndc-key" {
algorithm hmac-md5;
secret "OpxZPKpwc5vNOCsD/rz9sw==";

options {
default-key "rndc-key";
default-port 953;
# End of rndc.conf

# Use with the following in named.conf, adjusting the allow list as needed:
# key "rndc-key" {
#algorithm hmac-md5;
#secret "OpxZPKpwc5vNOCsD/rz9sw==";
# };
# controls {
#inet port 953
#allow {; } keys { "rndc-key"; };
# };
# End of named.conf

In the commented section of this file, it provides you with the exact
blocks you need to place in named.conf to allow rndc to connect to it
using this rndc.conf. Simply copy these lines onto the end of the
named.conf and save it and exit.

You can now verify the syntax and validity of your config file using the
named-checkconf program that comes with BIND. Make sure everything is
kosher, and you should be ready to progress to the next section! But
first, take a caffeine break 🙂

4.6. Add the new zone to your primary server’s BIND config file (named.conf).

You now need to tell BIND that you want to host the primary DNS for
mydomain.com. This is done by adding a new "zone" block to the named.conf,
as follows:

/* New zone called mydomain.com, of type "in" (Internet) */
zone "mydomain.com" in {

/* We're the master server for this domain */
type "master";

/* Store the data in /var/named/mydomain.com.db */
file "mydomain.com.db";

/* Who will we allow to transfer the entire domain? Normally, the
* only IP addresses listed here should be those of the secondary
* DNS servers for the domain */

allow-transfer {; // ns.resnet.gatech.edu; // secondary.com

At this point, you should be done with the named.conf on the primary DNS
server. You don’t need to do anything else to it. Run named-checkconf to
make sure the file checks out, and you should then be good to go.

4.7. Create and populate the new zone file.

Now’s the fun part. This is where you get to specify all the information
about your domain. Assuming you pointed your named.conf at
/var/named/mydomain.com.db for the information pertatining to mydomain.com
(for which you are listed as the primary DNS server), you should now
create this file with your favorite editor, and proceed with me.

All BIND 9 compatible zone files must start out with a default
time-to-live that will be applied to all the resource records in your
domain. The global TTL specification looks like this:

$TTL 86400

This TTL specification says that for every record in your zone that does
not have a specific TTL set for it, that the TTL should be set to 86400
seconds, or 1 day. BIND 8 did not require this statment, but BIND 9 does.

Now we begin with the resource records. Each record specifies something
about the zone, and follows this general format:


The resource name is usually a hostname in your domain, or the domain name
itself. The protocol is usually IN. This is short for Internet, and
pretty much all records are of type IN. In fact, if you don’t specify a
protocol, BIND will usually assume type IN. The TYPE is usually one of
the following (there are others, but they are rarely used):

Type Description
SOA Start of Authority, some global settings for the zone
NS Specifies a Name Server for the domain
MX Specifies a Mail eXchanger for the domain
A Specifies an IP Address for a particular host/domain
CNAME Specifies the canonical name for this "nickname" entry

The VALUE varies depending on the TYPE. You will begin to see how this all
works as we go over examples.

The first resource record (RR) that comes in every zone file is the SOA
record. It looks something like this:

mydomain.com. IN SOA ns.mydomain.com. hostmaster.mydomain.com. (

200209272 ;serial
14400;retry delay


The resource name is "mydomain.com." since we are specifying the SOA record
for this domain, not one of its subdomains. Please note that we must
place a period after the domain name so that BIND doesn’t automatically
append "mydomain.com" to the end of it, resulting in a record for
"mydomain.com.mydomain.com". This is a common beginner’s mistake. Any
fully qualified domain name (FQDN) that is specified _anywhere_ in a zone
file must be followed by a "." or BIND will append the "origin" domain
name to it.

Note that you can also replace any instance of the zone’s base domain
("mydomain.com.") with an @ sign, so that a single zonefile could be used
for multiple zones that are copies of each other, and the @ will be
replaced with the proper domain name for each. So then the SOA record ends
up looking like this:

@IN SOA ns.mydomain.com. hostmaster.mydomain.com. (
200209272 ;serial
14400;retry delay


The two values after SOA, are, respectively, the primary DNS server name
for this domain (note the period after it), and the email address of the
domain administrator (with a "." instead of the "@").

The serial number is what keeps track of the file’s version. DNS servers
around the world attempt to cache your domain’s information, and will
retrieve updated information from your server only if the serial number
has incremented since last time it checked. Therefore, if you make
changes to your DNS zone, you *must* increment the serial number or it
will not take effect until the number of seconds in the "expire" field has
passed, or until $TTL seconds have passed, whichever comes later.

It is conventional to use some form of the date (e.g. YYYYMMDDNN, where NN
is the number of the revision for that day, so you could revise it up to
100 times in that day). Other people simply like to start their serial
number at 1, and just increment by 1 each time. It’s all a matter of
personal preference.

The refresh, retry delay, and expire are almost always good at their
defaults. The default_ttl is the amount of time that negative responses
for data from your zone should be cached. That is, if someone requests an
IP address for nonexistent.mydomain.com and it doesn’t exist, their DNS
server will cache that negative response for 21600 seconds. This means
that even if you add nonexistent.mydomain.com to your zone within 21600
seconds, they will not notice until that amount of time has passed on
their end.

Now that you’ve specified your SOA record, you need to list the
authoritative name servers for your domain. This will use the NS record
type, and it will look something like this:

@IN NS ns.mydomain.com.

IN NS ns1.secondary.com.
IN NS ns2.secondary.com.

As you can see, we didn’t need to specify the @ for each record, because
if the resource name is omitted, BIND assumes you are still referring to
the last one mentioned.

If you want to receive email at your domain, you must now specify a mail
exchanger. This is the host to which an MTA (e.g. sendmail, qmail) will
send mail when there is mail for someone@mydomain.com. The MX record
specification looks something like this:

@IN MX10mail.mydomain.com.

IN MX20mail.backupmx.com.

The number between the MX and the mail server hostnames is the preference
number. The lower numbered servers are tried first, and if they fail, mail
is sent to a backup MX — one with a higher preference number. This is so
that if the main mail server is down, mail can be sent to another mail
server that will hold the mail until the primary server comes back up.

Now you should specify an A record for the main domain name so when people
go to http://mydomain.com or ping mydomain.com, they get a valid IP

@IN A128.61.48.46

At this point, you’ve taken care of the basic settings for the base
domain. Notice that we have used several hostnames we haven’t yet
defined, such as ns.mydomain.com and mailmydomain.com. We’ll need to add
those domains below.

First, however, let’s set our origin to mydomain.com. so we can be lazy
and specify only hostnames instead of full domain names:

$ORIGIN mydomain.com.

Again, notice the "." after the domain name, as always.

Now we can proceed to specify our hostnames. One rule is that all
nameserver hostnames and mail exchanger hostnames must be defined by A
records, not with CNAME records. It just creates another level of
indirection for lookups, and is against standards.

mailIN A128.61.48.46
nsIN A128.61.48.46
myboxIN A128.61.48.46
lappyIN A192.168.0.2

"mybox" is a name we’re giving to the host at We want to show up when you look up the name mybox.mydomain.com.
lappy.mydomain.com will resolve to, so it is really only
useful inside my network.

Most domains have www and ftp names with it. Assuming we are hosting our
web and ftp service on box1, we can just make these records CNAMEs, so
there will be less switching around of records if we ever change IP


Okay, now say your friend Joe wants to have joe.mydomain.com point to the
same IP address as his website so he can set up some virtual hosting.
Let’s say that www.eatatjoes.com is his normal website, and he wants us to
point joe.mydomain.com there. What we can do to avoid having to change
our record every time he changes his IP address is simply create a CNAME
to point to his domain:


Again, we put a period at the end this time, since it is not a cname for

Now assume that jill decides she wants to have control of
jill.mydomain.com and all its subdomains; she’s going to run her own name
server for jill.mydomain.com. What we do, then, is delegate the zone to
her with an NS record:

jillIN NSns.jillsdomain.com.

That way, requests to jill.mydomain.com and *.jill.mydomain.com will all
be redirected to her name server.

All right! It looks like everything is set up and ready to go! You can use
the named-checkzone program distributed with BIND to check the syntax of
your zone, and make any corrections necessary, and then you’ll be ready to
progress to the next step.

4.8. Start named!

Assuming you (or the named installation) created a nonprivileged user
"named" under which to run named, you’re ready to start named as follows:

named -u named

Then we set up our secondary server…

4.9. Add the new zone to your backup server’s named.conf

Now all you’ve gotta do is tell the secondary server that it’s
authoritative as a slave server for mydomain.com. Assuming they’re running
BIND 9, you can accomplish this by adding a block similar to the following
to their named.conf:

zone "mydomain.com" in {

type slave;
file "com/mydomain";
masters {; // ns.mydomain.com

On this server, the administrator likes to arrange the domain files in a
different structure, placing them in a hierarchy where each component of
the domain name gets its own subdirectory. So if their "directory" was
specified as /etc/named, then when their named is restarted, it will
transfer the zone from us and place it in /etc/named/com/mydomain.

Now reload the zones on the slave server (You can use "rndc reload") and
it should pull down the domain name from your main server.

Congratulations, you’re now hosting your own domain name! Now it’s time to
set up your mail and web servers… But I’m not going to tell you how to do
that here 🙂 That’s for another presentation!

5. Resources