I’ve decided for a small project of deploying Pi-hole – DNS server acting as an advertisement and tracking blocker. As I planned to provide this DNS server only to a few selected devices and I also wanted to keep updates and configuration as simple as possible, I went for Pi-hole in a container deployment. My setup at the time was:
- Raspberry Pi 3 model B
- Fedora 33 OS ( freshly installed )
- Podman 2.2.1 container management tool
- pihole:v5.2.4_arm image
I’m already used to podman for container management, but I guess any other tool ( like Docker ) would work as well. Because this container requires publishing of privileged port ( 53 ), it is necessary to run the container as root.
I searched for the pihole image, pulled the latest official version from repository and verified its presence:
sudo podman search pihole
sudo podman pull docker.io/pihole/pihole
sudo podman image ls
Then I created a systemd service file which will manage container as a service and ensure that container starts after reboot:
sudo cat << EOF > /etc/systemd/system/container-pihole.service
ExecStart=/usr/bin/podman run --rm --name %n -e DNS1=192.168.1.1 -e DNS2=192.168.1.1 -e QUERY_LOGGING=false -p 53:53/tcp -p 53:53/udp pihole/pihole
This pi-hole instance will use only one upstream DNS server. For such set ups it is recommended by pi-hole container documentation to set variable DNS2 as “no”. I used pi-hole container version 5.2.4 at the time, which did not properly processed DNS2 variable and instead put a Google DNS server as secondary upstream DNS into configuration. As a quick fix, I’ve set both DNS variables to the same value of upstream DNS server. This resulted in 2 server parameters in dnsmasq configuration in the container, but dnsmasq handled that as one server and no duplicates were sent.
I’ve also disabled query logging:
- A) I wanted to use the pi-hole DNS server as an improvement to security and privacy, so query logging was not desired
- B) I was not interested in statistics
- C) I wanted to minimize writes on RPi memory card so its lifespan is not affected so hard
In case you would be interested in statistics, you can keep the logging enabled, just change the value to true or remove the variable definition altogether – query logging is enabled by default. To access web management, you will need to publish the its port ( add
-p 8080:80/tcp for example, so you can connect via port 8080 to web UI ). Password for the administration is generated by random. You can find it in journal, during service startup. Alternatively, you can just check pi-hole container documentation and define your own password. In such case, don’t forget to put the password in file of environmental variables instead ExecStart line. Command line parameters could be discovered on the system.
Then I started the service and enabled it via systemd, so the service starts after OS reboot automatically:
sudo systemctl enable --now container-pihole.service
You can check in journal, if pi-hole starts and connects successfully.
Then DNS I allowed ports on the firewall in runtime and permanent (post-reboot) configurations:
sudo firewall-cmd --add-service=dns
sudo firewall-cmd --add-service=dns --permanent
And voilá, pi-hole’s DNS service was available on the network ( in my case pi-hole’s IP address was 192.168.1.53 ):
dig +short a example.org @192.168.1.53
I then confirmed yet, that service starts after the reboot successfully and is responding. Update of configuration on the selected devices, which should use pi-hole as their DNS server, was the next topic. This was done either via manual network configuration on device or via DHCP configuration.
As there were no changes done to the image itself, updates were quite easy. Either by re-running the pull command with repository name and then restarting the service, or putting the pull command and service restart into scheduled job ( like systemd timer ).