Running Pi-hole on the UDM in Unifi 3.0+
Since firmware version 3.0 on the Unifi UDM/UDM Pro, podman
is no longer available, so we had to use another method to create a container.
We now use systemd-nspawn
to create a container.
There are 3 steps:
- Create the container.
- Configure the container.
- Install Pi-hole in the container.
Create the container
All commands will be run using ssh
, logging in as a user with root access.
- Install systemd-container and debootstrap
apt -y install systemd-container debootstrap
- Use
debootstrap
to create a directory called debian-custom with a base debian system in /data/custom/machines
mkdir -p /data/custom/machines
cd /data/custom/machines
debootstrap --include=systemd,dbus unstable debian-custom
- Bring up a shell on this container, set the root password, and enable the networking service. Run each command one-by-one.
systemd-nspawn -M debian-custom -D /data/custom/machines/debian-custom
passwd root
systemctl enable systemd-networkd
echo "nameserver 192.168.1.5" > /etc/resolv.conf
echo "debian-custom" > /etc/hostname
exit
Note that the 192.168.1.5 is the IP of my other Pi-hole
Configure the container
- Link the container to /var/lib/machines so we can control it with
machinectl
mkdir -p /var/lib/machines
ln -s /data/custom/machines/debian-custom /var/lib/machines/
- Create a debian-custom.nspawn file in /etc/systemd/nspawn to configure parameters for the container (such as network, bind mounts, etc).
mkdir -p /etc/systemd/nspawn
My /etc/systemd/nspawn/debian-custom.nspawn file:
[Exec]
Boot=on
ResolvConf=off
[Network]
MACVLAN=br5
- Boot up the container and see if it works
machinectl start debian-custom
machinectl enable debian-custom
machinectl status debian-custom
Press
q
to exit the status
Optional: Configure container to use isolated network
If you haven't installed anything from the unifios-utilities, or have inter-VLAN restrictions, I would suggest following these sections:
While I do have inter-VLAN restrictions, I also have those isolated VLANs configured to use public DNS servers and I've been running unifios-utilites for a while.
Install Pi-hole in the container
- Spawn a shell to your container
machinectl shell debian-custom
- Run the automated install command from the pihole documentation and follow the prompts. Refer to the pihole documentation for more details.
apt -y install curl
curl -sSL https://install.pi-hole.net | PIHOLE_SKIP_OS_CHECK=true bash
As with any script you download from the Internet, make sure you are aware and understand what that script does before running it !
- You must use PIHOLE_SKIP_OS_CHECK=true so pihole can be installed on Debian unstable.
- After installation, the debian-custom container has a size of 611 MB after running
apt clean
to delete the package cache.
-
When the install says a static IP is needed, press Continue.
-
Select an upstream DNS provider on the next page, or add your custom DNS provider. Note all these options can be changed later in the admin panel, so you don't need to be perfect here.
-
In the next page, choose "Yes" to include the default list or "No" to not include any block lists at install (you will have to install your own later in that case).
-
On the next page, choose "Yes" to install the Admin web interface, then "Yes" on the next page to install the default web server that pihole uses.
-
On the next two pages, click Yes to enable Query Logging, and enable "Show everything". You can disable query logging or hide information from the log if you prefer.
-
Once the install is finished, it will tell you what your pihole IP and admin password is.
-
You can either use the current admin password the installation gave you, or run
pihole -a -p
to update the password. -
You should now be able to access the pihole admin page at https://10.0.0.5/admin.
Test or update Pi-hole container
- Test Pi-hole to ensure that it works, with 10.0.0.5 being the IP configured in the container:
dig @10.0.0.5 www.google.com
; <<>> DiG 9.20.11-1-Debian <<>> @10.0.0.5 www.google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59283
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: e38e8c30dd83e4ab (echoed)
;; QUESTION SECTION:
;www.google.com. IN A
;; ANSWER SECTION:
www.google.com. 296 IN A 142.250.72.68
;; Query time: 10 msec
;; SERVER: 10.0.0.5#53(10.0.0.5) (UDP)
;; WHEN: Thu July 10 08:55:45 MDT 2025
;; MSG SIZE rcvd: 85
- Update the pihole container, from within the container:
PIHOLE_SKIP_OS_CHECK=true pihole -up
References
Github / unifi-utilities / unifios-utilities / nspawn-container
https://github.com/unifi-utilities/unifios-utilities/tree/main/nspawn-container
Github / unifi-utilities / unifios-utilities / nspawn-container / examples / pihole
https://github.com/unifi-utilities/unifios-utilities/tree/main/nspawn-container/examples/pihole