Pi-Hole setup using Quadlets
Tags: podman, raspberrypi, opensuse
Published: 2024-02-22 14:25:59

---
title: Pi-Hole setup using Quadlets
published: true
description: Setup configuration for Pi-Hole using Quadlets
tags: podman, raspberrypi, opensuse
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2024-02-19 23:08 +0000
---

I've had an old *Raspberry Pi Model B* running [Pi-Hole](https://pi-hole.net/) at home for quite a long time, but I always wanted to dig a bit deeper into using containers to deploy applications. Because of that, I recently purchased a RPi 4 and this week found some time to figure out a way to deploy it using podman.

Since I started reading about containers, podman and such, it always looked a bit convoluted the way to run an application from the command line; many parameters basically, I didn't want to have one script launching one 100 characters command.
I then learnt *docker-compose* files, which are nice, but in my absolutely ignorant opinion seem to be only useful for local services (like on a development environment to spin a database); things you don't want to live forever as a service. And the second problem was: I wanted to use podman and, ideally, only native podman-related solutions.
Fast forward until recently. I read about **systemd-units** and **quadlets** and liked what I saw, so here we are.

## Quadlets
I won't go too deep into all the details about podman, systemd and quadlets as [Daniel Schier did it already](https://blog.while-true-do.io/podman-quadlets/) way better than I will ever be able to.
Basically you can split a container deployment within its multiple dependant components (volumes, network, the container itself...) and generate systemd services that can be easily managed. You can either do it manually by running the container from the command line (via `podman`) and then generate the systemd unit with `podman generate systemd` **OR** you can use *quadlets* to have a single centralised set of files that systemd will use to automatically generate the service units for you.

## Decissions and future goals
[x] Use *rootfull* containers for now (it felt easier not having to worry about port mapping).
[x] [openSUSE MicroOS](https://microos.opensuse.org/) will be the host system. I want to automate maintenance as much as possible and using an immutable & self updatable system is a first step.
[ ] Automatically update the container.
[ ] Use [unbound](https://docs.pi-hole.net/guides/dns/unbound/).
[ ] Use rootless containers.

## Deploying Pi-Hole via Quadlets

### Previous step
Without going into much details, first of all make sure there are no processes blocking at least ports 53 (tcp and udp) and 80 tcp if Pi-Hole will only be acting as the DNS server and not DHCP.
For example, here's the default installation of *openSUSE MicroOS* and, as you can see there's nothing listening on those ports. For that we'll use the command `ss -tunlp`.

![Port mapping check in openSUSE MicroOS proving that nothing is listening in ports 53 or 80](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7utqtockzx5fxwv6ip2.png)

By contrast, a default installation of *Fedora* shows the service `systemd-resolved` listening on ports 53.

![Port mapping check in Fedora showing systemd-resolved listening in port 53](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3mpg60wtjjggc6zbwswq.png)

I'll leave that up for research if you need to disable the service, but there's plenty of documentation on the topic.

### Provisioning needed files
As we are going to use a *rootfull* container, we need to place our Quadlets in `/etc/containers/systemd/`. We will create a bunch of files:
- Two *.volume* files for the volumes Pi-Hole needs.
- One *.network* file to configure the network for the container.
- One *.container* file for the main container.

#### pihole-dnsmasq.volume
```
[Unit]
Description=PiHole dnsmasq Container Volume

[Volume]
Label=app=pihole
```

#### pihole-pihole.volume
```
[Unit]
Description=PiHole Data Container Volume

[Volume]
Label=app=pihole
```

#### pihole.network
```
[Unit]
Description=PiHole Container Network

[Network]
Label=app=pihole
DisableDNS=true
```

#### pihole.container
```
[Unit]
Description=PiHole Service Container

[Container]
Label=app=pihole
ContainerName=pihole
HostName=pihole
Image=docker.io/pihole/pihole:latest
Network=pihole.network
Volume=pihole-pihole.volume:/etc/pihole
Volume=pihole-dnsmasq.volume:/etc/dnsmasq.d
AddCapability=NET_ADMIN
AutoUpdate=registry
PublishPort=53:53/tcp
PublishPort=53:53/udp
PublishPort=80:80/tcp
# Ignore the next 2 ones if not using pi-hole as dhcp server and not using https
PublishPort=67:67/udp
PublishPort=443:443/tcp

Environment=DNSMASQ_LISTENING=all
# Next variables to be customised
Environment=WEBPASSWORD="pihole"
Environment=TZ=Europe/Madrid
Environment=DNS1=208.67.222.222
Environment=DNS2=208.67.220.220
Environment=TEMPERATUREUNIT=c

[Service]
Restart=unless-stopped

[Install]
WantedBy=multi-user.target default.target
```

Change the webUI password to something better, set your timezone and temperature unit, and choose an upstream DNS provider (the one above is [OpenDNS](https://www.opendns.com/)).

### Generate and run service
Let's ask systemd to generate services from these files now. Run the following command as root:

```
systemctl daemon-reload
```

And lastly, run the service. As we said at the beginning this service is rootfull, so needs to be run as root. Just run the next command in a terminal and you should be done:

```
systemctl start pihole.service
```

If there are any failures you can check what happened with `systemctl status pihole.service`.

I have created [a repository](https://codeberg.org/franute/pihole-microos) to hold this code for future use.

## References

* [While-true-do: Podman-quadlets](https://blog.while-true-do.io/podman-quadlets/)
* [Podman systemd unit](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html).
* [Red Hat - Make systemd better for Podman with Quadlet ](https://www.redhat.com/sysadmin/quadlet-podman).
* [Red Hat - Deploying a multi-container application using Podman and Quadlet](https://www.redhat.com/sysadmin/multi-container-application-podman-quadlet)
* [openSUSE MicroOS](https://microos.opensuse.org/)