Git-driven BIND (plus Fabric)

Step 0. Store your DNS configuration in Git. If you aren’t using some sort of version control system for your zone files and other BIND configuration, you ought to be. May I recommend Git? Put your entire configuration directory in there, but do read the “Downsides” section below for some important security considerations.

Step 1. Create a bare Git repository on your DNS server. Using Fabric, you’d do it something like this:

def config_git():

    # Create bare git repo for direct DNS data pushes:
    sudo('/bin/mkdir /srv/bind.git')
    sudo('/bin/chown ubuntu:ubuntu /srv/bind.git')
    with cd('/srv/bind.git'):
        run('/usr/bin/git init --bare .')
    git_post_receive()

(The above assumes an Ubuntu system, where the “ubuntu” user has sudo privileges, such as on EC2; adjust to your environment as needed.)

Step 2. Add a post-receive hook. Notice that “git_post_receive()” in the fabfile snippet above? That function is nothing more than something like this:

def git_post_receive():
    put('git/post-receive', '/srv/bind.git/hooks/post-receive', mode=0755)

“git/post-receive” – which is, not surprisingly, a post-receive Git hook – is in turn something like this:

#!/bin/sh
sudo GIT_WORK_TREE=/etc/bind /usr/bin/git checkout -f
sudo chmod 0440 /etc/bind/rndc.key

(Again, assuming an Ubuntu environment, where BIND lives in /etc/bind.)

Step 3. Add some orchestration. You could tack on an automatic DNS reload to your post-receive hook, but you may prefer to separate control of BIND into distinct functions in your fabfile, perhaps with some tests run before applying changes:

def test():
    test_zones()
    test_conf()

def test_conf():
    run('/usr/sbin/named-checkconf')

def test_zones():
    with cd('/etc/bind'):
        run('for db in db.*; do zone=`/bin/grep SOA $db | /usr/bin/awk '{ print $1 }'`; echo ${zone}: $db; /usr/sbin/named-checkzone $zone $db; done')

def reload_bind():
    sudo('/usr/sbin/service bind9 reload')

def restart_bind():
    sudo('/usr/sbin/service bind9 restart')

Downsides. Note that you’re putting your rndc.key file (used to secure rndc) into Git if you put all your config files into your repository. In that case, you’ll obviously want to restrict access to the repository.

Of course, it isn’t hard to imagine an adaptation of this system where the rndc.key file is not stored in Git, but is perhaps put in place by the post-receive hook. (Call this an “exercise for the reader.”)

Alternatives. If you are using DNSSEC, a tool like nsdiff might be a better fit to manage updates to your zones.

2 comments

    • Andy

      Hi @sankar,

      Probably best to start with whatever your preferred distro gives you by default with its packages, and adapt it to your purposes – it’s likely to be highly customized to your site.

      -Andy