Pi-hole is a popular, useful Raspberry Pi project for removing ads from your browsing, site-wide. Comitup lets you configure and WiFi-connect a Pi with no keyboard, mouse, monitor, or SD card pre-fiddling required. Together, they provide an effective means to manage your ad-visibility experience at home.

Comitup and Pi-hole both manage DNS, DHCP, and HTTP, which can cause some conflicts. We’ll work around this by letting Comitup start and stop Pi-hole when it is safe to do so.

Start by loading the Pi with the Comitup Image, which is just Raspberry Pi OS with the comitup package installed. Alternately, the comitup package can be added to an existing Raspberry Pi OS installation, but note that this is not a headless operation.

Connect the device to your upstream Access Point.

Install Pi-hole.

Start the Comitup-specific configuration by disabling Pi-hole autostart:

sudo systemctl stop pihole-FTL
sudo systemctl disable pihole-FTL

Add a script for Comitup to manage Pi-hole, using the default external_callback configuration.

$ cat /usr/local/bin/comitup-callback 

if [ $1 == "CONNECTED" ] ; then
  systemctl start pihole-FTL
  if [ $1 == "HOTSPOT" ] ; then
    systemctl stop pihole-FTL

$ sudo chmod 755 /usr/local/bin/comitup-callback
$ sudo chown root.root /usr/local/bin/comitup-callback

Now Pi-hole will only run when the device is connected to the upstream WiFi.

The Pi-hole installation instructions talk about the importance that the IP address of the device be persistent. The preferred mechanism is to configure your router to return a consistent IP configuration for the device. In practice, the upstream router will continue to provide the same pool ip address if the device is generally online. But, if those options are not practical, you can set the current address as static using the NetworkManager nmcli command.

For instance, if ip addr and ip route return:

# ip addr
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER-UP> mtu 1500 qdisc pfifo-fast state UP group default qlen 1000
    link/ether dc:a6:32:02:a5:9b brd ff:ff:ff:ff:ff:ff
    inet brd scope global dynamic noprefixroute wlan0

# ip route
default via dev wlan0 proto dhcp src metric 303 dev docker0 proto kernel scope link src linkdown dev wlan0 proto dhcp scope link src metric 303 

You can set a static configuration for the interface using nmcli. First, determine the connection name:

$ nmcli con show

NAME              UUID                                  TYPE      DEVICE 
ISPRouter         5656e708-8bdc-43ad-bbdd-90b060510f83  wifi      wlan0  
comitup-707-0000  df1367d2-856d-4124-9295-ab048e688110  wifi      --     
dhcp              7c7e0483-1532-4a7e-87aa-8247db11b31f  ethernet  --     
static            6f7f1894-d1ad-42b1-bc28-f46d6fe2e8e5  ethernet  --     

The connection currently controlling wlan0 is ISPRouter.

Set the address and netmask per the information returned by ip addr:

sudo nmcli con mod ISPRrouter ipv4.addresses

Set the gateway per ip route:

sudo nmcli con mod ISPRouter ipv4.gateway

Set up DNS

sudo nmcli con mod ISPRouter ipv4.dns ""

Set the interface to “static”:

sudo nmcli con mod ISPRouter ipv4.method manual

A similar process can be used to set a static IPv6 address.

Reboot, and verify that the device connects to the router, and that Pi-hole is running.