# Ansible template data structure for dnsmasq.conf?

**URL:** <https://forum.ansible.com/t/ansible-template-data-structure-for-dnsmasq-conf/40586>\
**Category:** Get Help\
**Created:** [February 24, 2025, 11:55am UTC](https://forum.ansible.com/t/ansible-template-data-structure-for-dnsmasq-conf/40586 "2025-02-24T11:55:55Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![microlinux](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/microlinux/32/2968_2.png) [@microlinux](https://forum.ansible.com/u/microlinux)\
**Post date:** [February 24, 2025, 11:55am UTC](https://forum.ansible.com/t/ansible-template-data-structure-for-dnsmasq-conf/40586/1 "2025-02-24T11:55:55Z")

</div>

Hi,

I’m currently writing an Ansible role for automatically setting up Dnsmasq on my routerboard running Rocky Linux.

Here’s the actual `dnsmasq.conf` which I setup manually:

```auto
# /etc/dnsmasq.conf
domain-needed
bogus-priv
interface=enp2s0
dhcp-range=192.168.2.100,192.168.2.200,24h
local=/microlinux.lan/
domain=microlinux.lan
expand-hosts
#server=208.67.222.123
#server=208.67.220.123
#server=8.8.8.8
#server=8.8.4.4
server=1.1.1.1
server=1.0.0.1
no-resolv
log-facility=/var/log/dnsmasq.log
address=/proxy.microlinux.lan/192.168.2.1
address=/rocky-el8.microlinux.lan/192.168.2.10
dhcp-host=50:65:F3:4E:DA:77,alphamule,192.168.2.2
dhcp-host=B0:83:FE:90:4D:64,sandbox,192.168.2.3
dhcp-host=68:54:5A:B2:D0:81,dell-xps,192.168.2.4
dhcp-host=D0:37:45:24:61:BD,44:37:E6:DA:44:72,gustave,192.168.2.5
dhcp-host=3C:DC:BC:00:FB:97,smartphone-nico,192.168.2.6
dhcp-host=AC:AF:B9:D6:93:FA,smartphone-clothilde,192.168.2.7
dhcp-host=52:54:00:00:00:01,testbox-el8,192.168.2.10
dhcp-host=52:54:00:00:00:02,testbox-el9,192.168.2.11
dhcp-host=D4:85:64:B2:B2:1B,oldmule,192.168.2.249
dhcp-host=00:22:64:8A:4C:C2,nestor,192.168.2.250
dhcp-host=00:0D:B9:4B:5B:5C,squidbox,192.168.2.251
dhcp-host=10:62:E5:D4:95:60,hp-officejet,192.168.2.252
dhcp-host=00:11:32:26:63:A5,nas,192.168.2.253

```

And here’s the corresponding `/etc/hosts` file:

```auto
# /etc/hosts
127.0.0.1 localhost.localdomain localhost
192.168.2.1 proxy.microlinux.lan proxy
192.168.2.2 alphamule
192.168.2.3 sandbox
192.168.2.4 dell-xps
192.168.2.5 gustave
192.168.2.6 smartphone-nico
192.168.2.7 smartphone-clothilde
192.168.2.10 testbox-el8
192.168.2.11 testbox-el9
192.168.2.249 oldmule
192.168.2.250 nestor
192.168.2.251 squidbox
192.168.2.252 hp-officejet
192.168.2.253 nas
192.168.2.254 wifi

```

For now my playbook for Ansible looks like this:

```auto
    - name: Configure hosts file
      ansible.builtin.template:
        src: hosts.j2
        dest: /etc/hosts

    - name: Install Dnsmasq
      ansible.builtin.dnf:
        name: dnsmasq
        state: present

    - name: Enable and start Dnsmasq
      ansible.builtin.service:
        name: dnsmasq
        enabled: true
        state: started

    - name: Configure Dnsmasq
      ansible.builtin.template:
        src: dnsmasq.conf.j2
        dest: /etc/dnsmasq.conf
      notify: Restart Dnsmasq

    - meta: flush_handlers

```

Here’s the `hosts.j2` file:

```auto
# /etc/hosts
127.0.0.1 localhost.localdomain localhost
{{address_lan}} {{hostname}}.{{domain_lan}} {{hostname}}

```

And here’s the `dnsmasq.conf.j2` file (using a different network for testing purposes):

```auto
# /etc/dnsmasq.conf
domain-needed
bogus-priv
interface={{interface_lan}}
dhcp-range=192.168.3.100,192.168.3.200,24h
local=/{{domain_lan}}/
domain={{domain_lan}}
expand-hosts
server={{dns1}}
server={{dns2}}
no-resolv
log-facility=/var/log/dnsmasq.log
address=/{{hostname}}.{{domain_lan}}/{{address_lan}}

```

As you can see in the example above, I have a series of clients (`sandbox`, `dell-xps`, `gustave` and so on) each with a corresponding local IP address as well as a MAC address.

> Note that the client `gustave` has two MAC addresses since it can connect by wired interface or by wireless.

Now I could very well hardcode all these clients into my `dnsmasq.conf.j2` and `hosts.j2` templates.

> There’s a slight redundancy here, due to the fact that Dnsmasq needs hostnames in `/etc/hosts`.

But I think a more elegant solution would be to use variables. And now I wonder how the data structure could look like here. I bluntly admit I’m not very proficient with nested dictionaries, nested lists, lists of dictionaries and dictionaries of lists etc.

How could I write a data structure for these client machines to put in my template ?

Cheers,

Niki

---

<div class="post-metadata">

**Author:** ![kristianheljas](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kristianheljas/32/7702_2.png) [@kristianheljas](https://forum.ansible.com/u/kristianheljas)\
**Post date:** [February 24, 2025, 12:51pm UTC](https://forum.ansible.com/t/ansible-template-data-structure-for-dnsmasq-conf/40586/2 "2025-02-24T12:51:31Z")

</div>

You are looking for list of dictionaries .

Your data structure could look like:

```yaml
static_dhcp_leases:
  - mac: "50:65:F3:4E:DA:77"
    hostname: alphamule
    ip: 192.168.2.2
  - mac: "B0:83:FE:90:4D:64"
    hostname: sandbox
    ip: 192.168.2.3

```

Then you could use [for loop](https://jinja.palletsprojects.com/en/stable/templates/#for) to generate the result:

```auto
{% for lease in static_dhcp_leases %}
dhcp-host={{ lease.mac }},{{ lease.hostname }},{{ lease.ip }}
{% endfor %}

```

---

<div class="post-metadata">

**Author:** ![microlinux](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/microlinux/32/2968_2.png) [@microlinux](https://forum.ansible.com/u/microlinux)\
**Post date:** [February 24, 2025, 4:32pm UTC](https://forum.ansible.com/t/ansible-template-data-structure-for-dnsmasq-conf/40586/3 "2025-02-24T16:32:28Z")

</div>

Thank you very much !
