I've recently moved my home web server to a Pi4 (at the time of writing this: Ubuntu Server 20.10) and, having heard good things about Pi-hole, thought about installing it, in parallel, on the same hardware.
Alas, this seemed non-trivial at first, as both the Web server and Pi-hole need to use the very same TCP ports. And limiting bind() to certain IP addresses wasn't an option as that simply dosen't work for dynamically assigned IPv6 addresses.
The solution was pretty easy: Network Name Spaces!
And it's really straight-forward:
ip netns add pihole ip link add link eth0 address 70:69:68:6f:6c:65 virtual0 type macvlan ip link set virtual0 netns pihole ip netns exec pihole ip link set virtual0 name eth0 echo 'send host-name "pi-hole"' > /root/dhclient-pihole.conf ip netns exec dhclient -cf /root/dhclient-iphole.conf eth0 sudo -i ip netns exec pihole bash
Now install Pi-hole from there, the standard way. After that run something like that script for initial start-up:
#!/bin/sh # file name: /root/pihole-start.sh PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin export PATH for S in pihole-FTL lighttpd dhcpcd do systemctl stop $S.service 2> /dev/null systemctl disable $S.service 2> /dev/null done echo 'send host-name "pi-hole"' > /root/dhclient-pihole.conf ip netns add pihole ip link add link eth0 address 70:69:68:6f:6c:65 virtual0 type macvlan ip netns add pihole ip link set virtual0 netns pihole N="ip netns exec pihole" $N ip link set virtual0 name eth0 $N ip addr add 127.0.0.1/8 dev lo $N ip -6 addr add fd00::7069:68ff:fe6f:6c65/64 dev eth0 $N ip link set lo up $N ip link set eth0 up $N dhclient -cf /root/dhclient-iphole.conf eth0 $N /etc/init.d/pihole-FTL start $N /etc/init.d/lighttpd start
You may also wish to add this as a cron job
@reboot /root/pihole-start.sh 2>/dev/null >&2
to start up Pi-hole at boot time.
To keep this intact you just need to remember to run all Pi-hole related commands in that particular NetNS by prefixing them with ip netns exec pihole. That includes any cron-jobs (have a look at /etc/cron.d/pihole, please).
Also, I don't use the Pi-hole DHCP Server, and I've configured my DHCP server to return a static IP for the pi-hole identifier you've seen above.
If you're asking how to cleanly implement this in systemd context: I'm sorry, that's out of scope. I've no idea.