Gentoo Wiki


This article is part of the HOWTO series.
Installation Kernel & Hardware Networks Portage Software System X Server Gaming Non-x86 Emulators Misc



BIND (Berkeley Internet Name Daemon) is an open reference implementation of the Domain Name System (DNS) protocol and provides a redistributable implementation of the major components of the Domain Name System.

The BIND DNS Server is used on the vast majority of name serving machines on the Internet, providing a robust and stable architecture on top of which an organization's naming architecture can be built. The resolver library included in the BIND distribution provides the standard APIs for translation between domain names and Internet addresses and is intended to be linked with applications requiring name service.

My Bind Installation

My personal Bind installation has over 15000 zones and peaks at roughly 500 queries/sec across two servers. This How-To includes many organizational tips for running a large system without administration of it becoming unwieldly. I'll point those out along the way so home users with three or four domains can skip the extra steps. However most of the large system configs are geared towards easier troubleshooting and administration and I encourage all users to use the ISP tweaks I've included. After all most large systems started out as small systems.

Firewall Config

Bind listens on port 53 UDP and TCP. TCP is normally only used during zone transfers so it would appear that you could filter it if you have no slaves. However If the response to a query is greater than 1024 bytes, the server sends a partial response, and client and server will try to redo the transaction with TCP. Responses that big do not happen often, but they happen. And people do quite often block 53/tcp without their world coming to an end. But this is where one usually inserts the story about the Great DNS Meltdown when more root servers were added. This made queries for the root list greater than 1024 and the whole DNS system started to break down from people violating the DNS spec (RFC1035) and blocking TCP.

Installing Bind

This document is based on a fresh install of 2007.0 built on July 31 on a Dell 4700. 3.0Ghz P4 w/HT, gentoo-sources 2.6.24-r4 SMP kernel, glibc built with the NPTL flag, and Bind bind-9.4.2_p1 which is the minimum version you should be running. Newer installs should not differ too greatly from this install.

Bind is in Portage and has a number of USE variables to add functionality. We're going to eliminate most of them for the purpose of this doc to keep things simple.

Choosing your USE flags

For most users I'd recommend removing IPv6 support and any database support. This doc probably won't delve into using a database backend. Users that anticipate several hundred queries per second will definitely want to enable threads to take advantage of multiple CPUs.

File: /etc/portage/package.use
net-dns/bind -ipv6 -ldap -mysql -bind-mysql -postgres -odbc threads


On a fresh install there were no extra dependencies required over the default install using the above USE variables.

azul ~ # emerge -upv bind

These are the packages that I would merge, in order:

Calculating dependencies ...done!
[ebuild  N    ] net-dns/bind-9.4.2_p1  USE="berkdb mysql ssl threads -dlz
-doc -idn -ipv6 -ldap -odbc -postgres -resolvconf (-selinux) -urandom" 0 kB 

Bind as configured above builds in about five minutes on a 3Ghz P4. Your mileage may vary.

Configuring kernel

It's possible that you may need to change your kernel configuration. "Different security models" is optional, but if you have enabled it, you must also enable the default Linux capabilities:

Linux Kernel Configuration: Kernel Configuration
Security options  --->
    [X] Enable different security models
        <*>   Default Linux Capabilities

Additionally if you're installing Bind on a vserver you will want to use -threads when emerging. If you use threads Bind will randomly crash and generally act weird.

Configuring Bind

Gentoo alternates between naming files and directories "named" or "bind" which makes everything confusing. If you're fine with your installation being in /etc/bind while writing it's pid file to /var/run/named/ then you can skip the symlinking. If your Bind configs have lived in named/ for the last ten years doing the following will make your server annoy you less. And any admin that inherits your name server.

I prefer to break customer domains into include files by company. We have a small number of customers with 500+ domains per customer. It's a bit easier to find domains in the config this way and to track changes. I also include the logging config and any acls this way as well. You can put them all into one file if you like.

Creating Dirs and Symlinks

We're going to create some structure for the rest of config files. We're also going to symlink bind dirs to named dirs so that admins unfamilar with Gentoo can still find evertything. It's like that whole /etc/apache vs /etc/httpd problem people new to Gentoo have. This will also keep /var/bind/ from getting littered with files and make an etc-update mishaps less likely to lose all your configs.

ln -sf /etc/bind /etc/named
ln -sf /var/bind /var/named
mkdir /var/bind/conf
mkdir /var/named/reverse
mkdir /var/named/personal
mkdir /var/named/customer1
mkdir /var/named/customer2
chown -R named: /var/bind
mkdir /var/log/bind
ln -sf /var/log/bind /var/log/named
chown -R named: /var/log/bind


I really suggest using this config. Yes you can set Bind up without all the logging, splitting domains into their own file, but troubleshooting is vastly easier when you have done all the groundwork. You will need to change the IP's that are allowed to do recursion to your own IP's. The same will allow transfer and notify as well.

File: /etc/named/named.conf
options {
        directory "/var/named"; // sets root dir, use full path to escape
        statistics-file "/var/named/named.stats"; // stats are your friend
        dump-file "/var/named/named.dump";
        zone-statistics yes;
        allow-recursion {;; }; // allow recursive lookups
        allow-transfer {;; }; // allow transfers to these IP's
        notify yes; // notify the abover IP's when a zone is updated
        also-notify {;; }; // notify these other servers when a zone is updated
        pid-file "/var/run/named/";
        transfer-format many-answers; // Generates more efficient zone transfers
        listen-on { any; };

// Include logging config file
include "/var/named/conf/logging.conf";

// Include to ACLs
include "/var/named/conf/acls.conf";

// Include customer zones
include "/var/named/conf/customer1.conf";
include "/var/named/conf/customer2.conf";

NOTE: The 'listen-on' option can have as many IP addresses as you want separated by ';' or the word 'any' which will make it listen on all IP's on port 53 by default (you can specify other ports as well). The default for this option is '' which will not allow a DNS lookup to your server from any computer other than the one you are running BIND on.

Logging conf

Bind can be chatty in the log files and the sheer amount of data can sometimes make it hard to find interesting logs. Fortunately Bind allows you to separate your logs and rotate them automatically in its config. The following config splits each logging category into separate files, rotates them every 5MB, and keeps three rotations of each log. You can change the length of the log file rotations by changing the versions and size options in each channel. While this config seems quite large and ugly it'll never need to be touched and having log files separated like this can make many common troubleshooting procedures easier.

Note: The directory specified in each channel statement (in this example: /var/log/named) must exist and be writable by the named user
File: /var/named/conf/logging.conf
logging {

  channel default_file { file "/var/log/named/default.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel general_file { file "/var/log/named/general.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel database_file { file "/var/log/named/database.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel security_file { file "/var/log/named/security.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel config_file { file "/var/log/named/config.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel resolver_file { file "/var/log/named/resolver.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel xfer-in_file { file "/var/log/named/xfer-in.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel xfer-out_file { file "/var/log/named/xfer-out.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel notify_file { file "/var/log/named/notify.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel client_file { file "/var/log/named/client.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel unmatched_file { file "/var/log/named/unmatched.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel queries_file { file "/var/log/named/queries.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel network_file { file "/var/log/named/network.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel update_file { file "/var/log/named/update.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel dispatch_file { file "/var/log/named/dispatch.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel dnssec_file { file "/var/log/named/dnssec.log" versions 3 size 5m; severity dynamic; print-time yes; };
  channel lame-servers_file { file "/var/log/named/lame-servers.log" versions 3 size 5m; severity dynamic; print-time yes; };

  category default { default_file; };
  category general { general_file; };
  category database { database_file; };
  category security { security_file; };
  category config { config_file; };
  category resolver { resolver_file; };
  category xfer-in { xfer-in_file; };
  category xfer-out { xfer-out_file; };
  category notify { notify_file; };
  category client { client_file; };
  category unmatched { unmatched_file; };
  category queries { queries_file; };
  category network { network_file; };
  category update { update_file; };
  category dispatch { dispatch_file; };
  category dnssec { dnssec_file; };
  category lame-servers { lame-servers_file; };


ACL conf

The ACL section defines Access Control Lists that Bind uses to group a set of networks by name. In this example, the networks 10.*.*.*, 192.168.1.*, and have been grouped together under the name 'our-networks'. This name can then be used to refer to the entire group when assigning permissions. (See: HOWTO_Setup_a_DNS_Server_with_BIND#Adding an ACL to a Zone)

File: /var/named/conf/acls.conf
acl "our-networks" {;;;

Zone File conf

There are many examples of how to add a zone file to the config. Zone statements can be placed directly in named.conf, or they can be included from an external file using the include statement. In this example we will include one of the two zone statements listed below. Zone configurations can be made in two different formats. Let's call them single-line and multi-line.

This is how a configuration in multi-line format appears:

File: multi-line.conf
zone "" IN {
      type master;
      file "personal/";
zone "" IN {
      type master;
      file "personal/";

And this is the same config with a single zone on each line:

File: single-line.conf
zone "" IN { type master; file "personal/"; };
zone "" IN { type master; file "personal/"; };

You may prefer the single line format for administrative tasks. It's easier to run sort, grep, sed, and other tools against the config file to make mass changes. Any script you write to generate a new slave or master config will be easier and simpler to write. However, it appears that the multi-line config is easier to read in documentation, so we're going to use it through out this How-To for clarity.

Each refers to zone file using the file line to include a map of domain names and their matching IP addresses. Zone files are covered in more detail below.

Note: The examples above use relative paths for each zone file. The directory root is specified by the directory statement in the options section of named.conf. Any directory listed without a leading slash will have the root directory added to the beginning of the path. In this case, personal/ is treated by Bind as /var/named/personal/

Adding a Slave Zone

File: multi-line.conf
zone "" IN {
    type slave;
    file "personal/";
    masters {; };

zone "" IN {
    type slave;
    file "personal/";
    masters {; };

Note: There is a bit of confusion on where these files go. multi-line.conf would be the include you had in /etc/bind/named.conf. In this case you would add the line include "/var/named/conf/multi-line.conf".

Adding an ACL to a Zone

We can use the Access Control Lists to specify permissions for each zone.

 allow-query { our-networks; };

Adding this line to the zone defined below tells Bind that any of the networks specified in the 'our-networks' group has permission to request the name of any IP address in the 10.113.1.* network.

File: /var/named/conf/zone-with-acl.conf
zone "" IN {
    type master;
    file "reverse/";
    allow-query { our-networks; };

Zone Files

Picking Your Zone File

There are a number of example of zone files on the Internet, each with their own little quirks. I would recommend using the layouts below as they are exactly what I use in production. All you should have to do is change the names servers, domain name, and IP address. It is in your best interest to use the same format for all your domains. This will make changes easier and you can script out wholesale changes using sed or other tools if your IP's need to change quickly. There is nothing worse than trying to edit 1000 domains by hand because each was done a different way.

Example of a Zone File for a Domain

File: Sample of Zone File
$TTL 600
@       IN      SOA (
                        2005062601      ; serial
                        12h             ; refresh
                        1h              ; retry
                        2w              ; expire
                        1h              ; minimum

        IN      NS
        IN      NS
        IN      MX      10
@                       IN      A

; host records
localhost               IN      A
mail                    IN      A
*                       IN      A

Domain Zone File Explained


The first number is the time to live of the zone file. The specifies the time we want other name servers to cache the information they received from our name server. I recommend somewhere between five to sixty minutes. Less is usually better on a production system because you'll want people on other systems to pick changes up quickly.


The @ indicates that the domain is the same name as the zone file. After the SOA we list the primary name server and then the email address of the Hostmaster. will be interpreted as

Serial Numbers

Don't forget to update the serial number each time you change a zone file. The new serial number must be anything larger than the previous one. Most systems simply use the date of the change plus two digits as a serial number. For example, a zone file that has been changed for the second time on the third of January 2004 would have
as a serial number. But the serial number can be any number with the maximum value of 9999999999 as long as the new serial number is larger than the previous serial number. If you don't increment your serial number, your DNS slave servers will not accept the changes and keep the old version of the zone file.

Sometimes you'll need to reset your serial number. This is easy to do if you control all your name servers. Change the master server, stop the slave servers, delete the old zone, start the slave servers. However if you do not have access to your slave servers you can set the serial number to 0 on the master server. Once the slave picks up the change you'll be able to use any number as the next serial number. This is usually done when an admin sets the serial to 3005103001 and wants to reset the serial back to 2005103001 or something similar.


As of Bind 9.2.5 MX records are requires to have a weight set, in out case it is the 10 before MX. If you do not set a weight Bind will refuse to load the zone file.

About IP Addresses

When specifying a given IP range using the format, the bytes are given in reverse order. In effect the IP range is For a 16-bit netmask, it would be, equivalent to

Example of a Zone for Reverse DNS

File: reverse
$TTL    600   IN      SOA (
                        2005062601      ; serial
                        12h             ; refresh
                        1h              ; retry
                        2w              ; expire
                        1h              ; default_ttl
                        )  IN      NS
                        IN      NS


21      IN      PTR
22      IN      PTR

31      IN      PTR
32      IN      PTR

Starting Bind

Let's add it to your default run level and start it.

sudo rc-update add named default
sudo /etc/init.d/named start ; tail /var/log/named/general.log

If you update zone files it's better to reload than restart

sudo /etc/init.d/named reload ; tail /var/log/named/general.log

Helper Scripts

# Quick little bash script to create a slave conf based on the current master conf.

echo ""
echo "Current directories are:"
echo "customer1, customer2, customer3"
echo ""
read -p "Enter the directory you wish to create a slave config for:  "

for i in `awk '{print $2}' /var/named/conf/$REPLY.conf | sed 's/\"//g'`
        do echo "zone \""$i"\" IN { type slave; file \""$REPLY/$i"\"; masters {; }; };" >> $REPLY-slave.conf
#  Quick little bash script to create a new master conf by listing the domains in a dir

echo "Current directories are:"
echo "customer1, customer2, customer3"
echo ""
read -p "Enter the directory you wish to create a config for:  "

for i in `ls /var/named/$REPLY`
        do echo "zone \""$i"\" IN { type master; file \""$REPLY/$i"\"; };" >> $REPLY.conf

Default zone

If you are a hosting provider and want to have default zone (if some domain has your NS server as primary, but you haven't added zone for this domain yet) for newly-added domains AND your server is not designed to execute recursive queries, you can use this section:

File: Sample of Default Zone File
zone "." IN {
	type master;
	file "path_to_default_zone_file";

After this, any domain, that cannot be found in your configuration will be passed over "path_to_default_zone_file" ruleset.

File: Bind 8 Zone file example
$ORIGIN com. //note that Bind 8, you need to specify all the domain externsion
*	14440	IN	SOA ( 2008010101 1200 7200 1209600 3600 )
	86400	IN	NS
*	14400	IN	A
File: Bind 9 Zone file example
$TTL 10M //note that you must have TTL for bind 9<br>
@	IN	SOA	( 2008012701 10M 10M 10M 10M)
@	86400	IN	NS
*	IN		A

Further Information

Retrieved from ""

Last modified: Thu, 14 Aug 2008 08:13:00 +0000 Hits: 81,380