The following is the GNU All-permissive License as recommended in

Copyright (C) 2024 Free Software Foundation

Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty.

Contributions are welcome. See

bind (DNS name server)

This is mostly FSF internal, a few volunteers have read access to bind.

Cloning bind

git clone

Install dependencies

sudo apt install -y bind9-utils

Adding a new entry

This documentation is easiest to describe with a concrete example. In our example we will create an address for Adjust as necessary.

  • To find an unused address, first look in the masters/*.arpa files to find an address that is no longer used. Unused addresses are ones that start with ; previously decommissioned machines, or development instances that we no longer need. Some research may be required to make sure that the hostname is really not used. Start with ping and look at virtual, and maybe search for the hostname in gluestick and brains.
    • If you have extra time, comment out unused entries with ; to speed up this step the next time.
  • Edit the chosen line in the .arpa file with the new address name. In this example, we are using masters/ which is the address space in reverse. 242 was available so we used that. This means that is the IPv4 address for

    vim masters/

  • Notice that there is a trailing period. The line would look like this:

    242 PTR

  • Edit the associated domain file masters/

    vim masters/

  • Here is an example of how the A (IPv4) and AAAA (IPv6) addresses would look like:

    mwikiserver2p A mwikiserver2p AAAA 2001:470:142:5::242

  • Now we need to update the zones. We have update-zone scripts to make sure this process works correctly. The scripts take an abbreviation of the file names that we used previously. Basically, the same argument, but without masters/db. at the beginning. Start with the .arpa file.


  • Once run, there will be a git commit text entry. Edit the top line to state the change you are making. Save and quit vim with :wq in you are unfamiliar. The program ends with a feed of the DNS queries. If there is no output or a stream of errors, something is wrong. Use CTRL + c to exit the text stream.

  • Repeat the same workflow for the domain file.


  • Now, you can assign the machine or VM to these new addresses.

Adding a new domain name

The new file in masters/ should be similar to others, but may have lower starting serial number. is a good starting point.

cp masters/ masters/
vim masters/
git add masters/


# Important: this deletes all untracked files, like `*~`
# otherwise ``, etc, will get in our configs
git clean -fxd

git add -p
git commit
git push

Now configure the name servers for the domain in Gandi, so they point to ns(1|2|3), etc.

Do not forget to set up email delivery, especially if we are migrating a domain from another hosting provider.

Adding a new name server

  • Make sure it exists in Gandi in the external name servers list for each domain.
  • If needed, update the ns records of each domain
  • Add the new namserver's IP to "allow-transfer" in named.conf, git commit. git push.
  • Install bind9 on the new name server.
  • Check that ./update-slaves has the right name servers and run it.


It is possible to temporarily log DNS lookups on ns1. This type of logging is very verbose, and can reach over 500 MB in 12 hours, so the files need to be frequently pruned.

The /var/log/named/ directory needs to exist and be owned by / writable for the bind user, otherwise the syslog will get flooded when bind tries to rotate files.

chown -R bind:bind /var/log/named/

To make the change, clone the /etc/bind/ repo from, and edit the named.conf file:

logging {


    channel querylog {
        file "/var/log/named/querylog" versions 600 size 20m;
        print-time yes;
        print-category yes;
        print-severity yes;
        severity debug 3;
    category "queries" { "querylog"; };
    //category "queries" { "info"; }; //normal logging level



Updating TTL

Time To Live (TTL) is the time a DNS entry will stay active before expiring. Once expired, other name servers will fetch again when requested. Best practice seems to indicate that 30 minutes or 1 hour is a good middle ground for what this value should be set to under normal conditions.

Last time we changed TTL is documented in the [[!rt 1931475]] ticket.

Example workflow changing TTL from 30 minutes to 1 hour:

Change TTL for all domains at once. Note: Look at the source of this document for proper formatting.

cd bind
grep -R "\$TTL<span class="createlink">:blank:</span>1800" masters/ | sed 's/:.*$//g' | sort -u | xargs sed -i --follow-symlinks 's/\$TTL<span class="createlink">:blank:</span>1800/\$TTL 3600/'

Explanation of parts:

  • Note: Look at the source of this document for proper formatting. grep -R "\$TTL<span class="createlink">:blank:</span>1800" masters/ finds all files that have $TTL 1800 with any number of spaces or tabs between the two values.
  • sed 's/:.*$//g' excludes the matching part leaving only the file name.
  • sort -u sorts the list and only return unique values.
  • xargs sed -i --follow-symlinks 's/\$TTL<span class="createlink">:blank:</span>1800/\$TTL 3600/' uses the output as files to work on and replaces the first instance of $TTL 1800 with $TTL 3600 and saves in-place. --follow-symlinks does not clobber symlinks which is a dangerous default for sed to have.

Verify the output with git.

git status

Create the list of zones that needed updating.

git status | grep modified | sed 's/^.*db.//g' | tr '\n' ' ' && echo

No entry should be anything other than modified.

I took that output and made this command to update all changed zones at once:

./update-zone $(git status | grep modified | sed 's/^.*db.//g' | tr '\n' ' ')

If the commands were not matching the remaining entries for some reason, use this command to find any stragglers that did not have a TTL of 1 hour:

grep -R "\$TTL" masters/ | grep -v 3600 | sed 's/:.*$//g' | xargs vim

Verify the output with git status and update zones.

Check that it succeeded with dig. This example checks the name server for the address.


The second value is the current TTL.