More Adventures in Ansible – Bind Example

Ansible Linux

Following on from a previous article https://geekmungus.co.uk/?p=4510 we now investigate some more into using Ansible for configuration management and installations.

As something we can use as an example, we’re going to setup a simple Bind DNS server, which we can use to explore how to manage the installation of Bind and it’s configuration within Ansible.

We’ll configure it as a Caching DNS Server, which is a recursive DNS server. A Recursive DNS Server performs all the DNS lookups starting from the root down on the behalf of the requesting client. We’ll also then play around with swapping it to a Forwarding DNS Server (a.k.a iterative DNS server), so we can explore how changing the configuration and applying with Ansible can be used to trigger a reload of the Bind daemon.

Getting Started

First we source our Python Virtual Environment (which we set up in the previous article), then change to our ansible directory.

source ~/ansible-env/bin/activate

cd ~/ansible

Prepare our Play and Role

To avoid repeating code here, see my gitlab repository for the Bind Ansible code: https://github.com/tristanhself/ansible, you’ll find the play and the role in folders called “bind” unsurprisingly!

In my configuration I have a server called “dev3” which will be the Bind DNS Server, I have already added this to the “hosts” file, and added it to a group called “bind”, my “bind” play will refer to this group within the Ansible configuration, to only install onto the relevant hosts.

Run the Play

To run the play let’s give it a go! I’m going to use the “–limit” argument and include the “dev3” server name, which will ensure that only the dev3 server is processed, to save a bit of time.

ansible-playbook -i hosts site.yml -u ubuntu --limit dev3

Your results will be a bit different if this is the first time you are running the Ansible, it will first install the Bind DNS Server, then copy in the configuration, so you should see a lot more saying “changed” in yellow.

Assuming the Ansible all runs as expected, you’ve successfully added a Play and a Role. So let’s test to see if the DNS server is working.

Open a command prompt on your Ansible Workstation, then run the following command, you’ll need to substitute in the correct IP address of your Bind DNS Server.

(ansible-env) ubuntu@dev1:~/ansible$ dig @192.168.1.6 www.geekmungus.co.uk

; <<>> DiG 9.18.30-0ubuntu0.22.04.2-Ubuntu <<>> @192.168.1.6 www.geekmungus.co.uk
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25233
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 1d48b90cd6e751c301000000683b14e7f6b8358c4538f1fb (good)
;; QUESTION SECTION:
;www.geekmungus.co.uk.          IN      A

;; ANSWER SECTION:
www.geekmungus.co.uk.   20979   IN      A       178.18.126.4

;; Query time: 0 msec
;; SERVER: 192.168.1.6#53(192.168.1.6) (UDP)
;; WHEN: Sat May 31 15:40:39 BST 2025
;; MSG SIZE  rcvd: 93

Excellent, all appears to be working as you’d expect, our DNS server is resolving queries.

When I ran this for the first time, the firewall rule was not added as expected, so I stopped the Bind9 daemon and re-ran the Ansible, the firewall rule was created as expected. There are ways around this, for example using a “register”, which I’ll likely get to at some point.

Forwarding or Caching

Now we have it running, let’s change some configuration and see what happens. So let’s swap it from between being a Forwarding DNS Server (iterative) to a Caching DNS Server (recursive) or vice versa depending on your current configuration.

Edit the Jinja template which is used to generate the Bind9 configuration file: ~/ansible/roles/bind/templates/named.conf.j2

If you comment or uncomment out the section:

    forward only;
    forwarders {
        8.8.8.8;
        8.8.4.4;
    };

You can swap from “Forwarding” if the above is uncommented (i.e. present) or “Caching” if you comment it out.

Once commented or uncommented, re-run the Ansible Playbook with the below, because of the way the Ansible playbook works, you’ll find that the

ansible-playbook -i hosts site.yml -u ubuntu --limit dev3

Exploring the Ansible Configuration (Handlers)

In the previous section we changed the Jinja template and then re-ran the Ansible, and the daemon was restarted, but why did it restart, that would be down to Handlers. In our case if someone was to update our configuration files, we want Ansible to trigger a re-load of the configuration, we don’t want to have to go and log in to the server afterwards and manually do this. A handler is a method to allow this to be done.

Within the ~/ansible/roles/bind/tasks/main.yml, you’ll find this section:

- name: Copy BIND configuration file
  template:
    src: named.conf.j2
    dest: /etc/bind/named.conf
    owner: root
    group: root
    mode: '0644'
  notify:
    - Reload BIND Service

Notice the last lines “notify” and “Reload BIND Service”, these directives say that if the particular task results in “Changed”, then notify the handler “Reload BIND Service”, the handler configuration can be found in: ~/ansible/roles/bind/handlers/main.yml specifically this section:

- name: Reload BIND Service
  become: yes
  service:
    name: bind9
    state: reloaded

Simply put, it just triggers a reload of the BIND service when it is run, in this case by the task because of the “notify”. You’ll notice however that if you were to run the Ansible again, without making any changes, that it doesn’t notify and reload the service, because nothing has changed.

Conclusion

Hopefully this gives you a bit of an introduction into using Ansible for something actually useful!

Additional Information

https://www.digitalocean.com/community/tutorials/how-to-use-ansible-to-install-and-set-up-lamp-on-ubuntu-18-04

https://www.digitalocean.com/community/tutorials/how-to-configure-bind-as-a-caching-or-forwarding-dns-server-on-ubuntu-14-04

Leave a Reply

Your email address will not be published. Required fields are marked *