If you are running multiple devices in a cluster layout, like docker swarm or kubernetes, you may have multiple IPs that could lead to the same service. And to make things easier you probably have set a local DNS record within your piHole to give the service an easier local domain name instead of remembering the IP address. BUT there is a big downside in pihole, as you can only assign ONE IP address per DNS entry in the webinterface.

So if you have a cluster with devices and use Traefik as a load balancer, you will need to settle on one of the four available IPs. And thats okay, unless exactly that node goes down.

So to avoid that, we add additional IPs to our local DNS entries in pihole, that, no matter what, all 4 IPs are returned for our custom local domain name.

In this example we want to give our traefik and unifi controller local DNS entries with 4 IPs associated to.

NOTE: traefik.local.domain.com and unifi.local.domain.com are pure fantasy names. As it is a local DNS entry you can come up with whatever hostname suits you....even stuff like 123happy.funny or whatnot...that said, for sure you will have a better system and layout naming in mind 🙂

First SSH into your pihole main instance. There we check our local DNS entry first with:

dig @localhost traefik.local.domain.com

Depending if you already added this custom domain name in the Local DNS web interface of your pihole, you might get one, or no response. In my case I already had one IP associated with it, and it returned this:

; <<>> DiG 9.16.1-Ubuntu <<>> @localhost traefik.local.domain.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47480
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;traefik.local.domain.com.     IN      A

;; ANSWER SECTION:
traefik.local.domain.com. 0    IN      A       192.168.10.1

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sun Apr 17 17:23:05 CEST 2022
;; MSG SIZE  rcvd: 70

This shows us that we have one IP 192.168.10.1 linked to our custom local domain traefik.local.domain.com.

We will add now 3 more IPs over a custom config file in /etc/dnsmasq.d/.

NOTE: You can now decide to either DELETE the entry in your webinterface, and add all 4 IPs to the custom conf file. Or you leave the one IP in the pihole Local DNS webinterface and only add the additional three IPs in the custom conf file. I decided for the later option, this way I have still a quick overview what domain names I am using and running in the webinterface, whithout the need to SSH into my pihole and take a look into the custom conf file.

There are already multiple conf files in the /etc/dnsmasq.d/ direectory, but DON'T edit any of these! Instead we will create our own new file with:

sudo nano /etc/dnsmasq.d/9-my-custom-pihole-dns.conf

Here we add the following additinal IPs by copy and pasting these lines:

#Traefik docker swarm
host-record=traefik.local.domain.com,192.168.10.2
host-record=traefik.local.domain.com,192.168.10.3
host-record=traefik.local.domain.com,192.168.10.4

#Unifi docker swarm
host-record=unifi.local.domain.com,192.168.10.2
host-record=unifi.local.domain.com,192.168.10.3
host-record=unifi.local.domain.com,192.168.10.4

Great, now exit and save the new config file with STRG + X and confirm with yes and enter.

Before we load our changes, we need to be sure and check the syntax of our conf file with:

pihole-FTL --test

This should return: (if not, check your conf files syntax!)

dnsmasq: syntax check OK. 

Perfect! Next we reload the pihole conf and activate our changes:

sudo service pihole-FTL reload

To verify our changes to the dnsmasq config, enter the dig command again:

dig @localhost traefik.local.domain.com

You should now get a response with 4 IPs:

; <<>> DiG 9.16.1-Ubuntu <<>> @localhost traefik.local.domain.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48030
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;traefik.local.domain.com.       IN      A

;; ANSWER SECTION:
traefik.local.domain.com. 0      IN      A       192.168.10.2
traefik.local.domain.com. 0      IN      A       192.168.10.3
traefik.local.domain.com. 0      IN      A       192.168.10.4
traefik.local.domain.com. 0      IN      A       192.168.10.1

;; Query time: 4 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sun Apr 17 17:38:24 CEST 2022
;; MSG SIZE  rcvd: 116

Perfect, you are done! You might notice now, if you shutdown the node with IP 192.168.10.1, which was our only entry before and made our traefik service unreachable, you will now have the other IPs resolving the DNS query and your service is still reachable. Hurray!