Setting up BIND9 and DHCP3 on Ubuntu with Dynamic DNS

I recently built an internal DNS/DHCP server which I wanted to support Dynamic DNS updates. This can sometimes be a bit of a challenge depending on the operating system and available packages, but it’s really quite easy on Ubuntu. The following guide describes what I did to get BIND9 and DHCP3-server installed, configured, and running on an Ubuntu 10.04 LTS system.


My first step was deciding how I wanted the DNS/DHCP server to operate; that is, what sort of IP addresses it should allocate for DHCP, what zones to use for DNS, etc.

The Network:

  • Network:
  • DNS/DHCP Server Address:
  • DNS/DHCP Server Name: eneth
  • Gateway Address:
  • Broadcast Address:

DHCP Server:

  • Dynamic Pool: to
  • Static Pool: to and to

DNS Server:

  • Forward Lookup Zone: aohq.local.
  • Reverse Lookup Zone:

My second step was ensuring that my system was in a proper state to be a DNS/DHCP server… namely, that it had a static IP address and a valid hostname. This involved editing /etc/networks/interfaces to set the IP address of the primary ethernet interface (eth0):

auto eth0
iface eth0 inet static

I also removed the DHCP client so that it wouldn’t be possible for the system to mistakenly receive a dynamic IP address.

sudo apt-get purge dhcp3-client

Note: I performed this step because of some odd issues I’ve had with systems suddenly switching to a dynamically allocated IP address even when I had specifically set a static one for the system.

Setting up BIND9

I started installing required packages for BIND9:

sudo apt-get install bind9

Then, I edited /etc/bind/named.conf.options to add the following:

forward first;
forwarders {;;
max-ncache-ttl 300;

I use a max-ncache-ttl (max negative cache time-to-live) of 300 as we’ve often had issues with our DNS server caching the negative existence of a domain name for far too long when we’re trying to add a new sub-domain to our system.

Next, I edited /etc/bind/named.conf.local to add references to my zone files:

zone "aohq.local" {
	type master;
	forwarders {};
	file "/var/lib/bind/db.aohq.local"
	allow-updates { key rndc-key };
zone "" {
	type master;
	forwarders {};
	file "/var/lib/bind/"
	allow-updates { key rndc-key };

I added “forwarders {};” to override the server-wide forwarders as these zones are internal/local. I also added “allow-update { key rndc-key };” to allow Dynamic DNS updates for these zone (more on that later). I provide a location for the zone files at /var/lib/bind as this is a location which BIND9 can safely read/write without running into Ubuntu’s AppArmor. The default location for zone files is /etc/bind/.

Setting up DHCP3-server

I installed the necessary packages for DHCP3-server:

sudo apt-get install dhcp3-server

Note: Since this will likely start the DHCP server, you should be sure your network is ready. Wouldn’t do to have two competing DHCP servers handing out addresses simultaneously.

Next, I edited /etc/dhcp3/dhcpd.conf to include the following:


ddns-updates on;
ddns-update-style interim;
ddns-rev-domainname "";

option domain-name "aohq.local";
option domain-name-servers;
option ntp-servers;

ignore client-updates;
update-static-leases on;
use-host-decl-names on;

include "/etc/bind/rndc.key";

zone aohq.local. {
  key rndc-key;
zone {
  key rndc-key;

subnet netmask {

  option subnet-mask;
  option routers;

I specifically added “ddns-updates on” to allow Dynamic DNS. I included the RNDC key from bind, located at /etc/bind/rndc.key by default, and associated it with the appropriate zone for DDNS updates. This is what DHCP3-server uses to authenticate itself to BIND9 in order to make updates. (Recall that I earlier allowed updates with this key in the BIND9 configuration).

Before starting things up, I to added details about the DNS/DHCP server to the zone files directly:


$TTL 10800      ; 3 hours IN SOA  eneth.aohq.local. root.aohq.local. (
                                2012040233 ; serial
                                900        ; refresh (15 minutes)
                                900        ; retry (15 minutes)
                                604800     ; expire (1 week)
                                3600       ; minimum (1 hour)
                        NS      eneth.aohq.local.
200 PTR eneth.aohq.local.


$ORIGIN aohq.local.
$TTL 10800      ; 3 hours
aohq.local   IN SOA  eneth.aohq.local. root.aohq.local. (
                                2012040233 ; serial
                                900        ; refresh (15 minutes)
                                900        ; retry (15 minutes)
                                604800     ; expire (1 week)
                                3600       ; minimum (1 hour)
                        NS      eneth.aohq.local.

The Finale

Finally, I was able to restart BIND9 and DHCP3-server to get things going:

sudo service dhcp3-server restart
sudo service bind9 restart

I was able to test that DHCP was working by connecting a new system to the network to receive a static IP address. I tested that the DNS server was working by querying it for details I had placed in the zone files ($ dig eneth.aohq.local @ I tested that DDNS was operating by querying for the hostname of the new system which I had connected to the network based on IP address ($ host


Setting up complex packages like BIND9 and DHCP3-server are bound to result in errors. Be sure to check the appropriate logs (e.g. /var/log/syslog and /var/log/named/bind.log), and adjust configuration parameters as necessary. I went through several iterations of tweaking configuration files and restarting all services before I was satisfied with the result.

  • error: zone [zone-name]/IN: NS ‘[dns-server-hostname]’ has no address records (A or AAAA)
    You’ll probably encounter this if you forget to provide records for your DNS server in your zone files; e.g. [dns-server-name] IN A [dns-server-ip-address]
  • error: [some-zone-file]: create: permission denied
    Check to make sure that permissions on the given file are correct. Configuration files must be readable by the bind user, and zone/journal files must be writable by the bind user.
  • updating zone ‘[zone-name]/IN’: error: journal open failed: unexpected error
    It is possible that Ubuntu’s AppArmor is getting in the way of the zone updates. Make sure you check /var/log/syslog for related messages. Also check the AppArmor configuration at /etc/apparmor.d/usr.sbin.named.
  • error: zone [zone-name]/IN: [some-hostname]/A: bad owner name (check-names)
    The hostname that a client is requesting is invalid for use in a FQDN. Change the client’s hostname.
  • error: zone [zone-name]/IN: journal rollforward failed: journal out of sync with zone
    The zone journal file has gotten out of sync with the zone file (usually occurs with forced restarts, or modifying the zone file while BIND9 is running). Delete the .jnl file (in /var/lib/bind), and restart BIND9.
  • […] found some really nice troubleshooting steps regarding dhcp and dns server here (Thanks to original […]

  • Uniqueraj says:

    Thank you for the informative tutorial. I want the advice regarding same work with IPv6, is it better idea using SLAAC. the main problem is how to change prefix address and maintain the changed update in DNS . any advice will be welcomed.

  • Comments are closed.