Installing Pi-hole as a Linux-VServer Guest on Debian 10

Published 14 October 2022

Historical note: This article describes a Pi-hole installation on Debian 10 (Buster) running as a Linux-VServer guest in 2022. Pi-hole and Debian have changed since then, so some installation commands and configuration-file locations may no longer apply to current versions.

Pi-hole combines DNS filtering with optional DHCP services and can block many advertising and tracking domains at DNS level. Although originally popular on the Raspberry Pi, it can also run on Debian. This article describes the extra work required to run it inside a Linux-VServer guest.

Base system installation

The host running my guest servers was itself a Debian Buster system with a Linux-VServer-enabled kernel.

See also: Installing Linux-VServer on Buster and running Buster guests .

I already had a Debian Buster VServer template, so I used that as the starting point. I normally create guests from a small shell script, since there are several parameters such as hostname, context number, network interface and IP address that need to be set consistently.

The following is the script I used for the Pi-hole guest.

#!/bin/bash
#
XNAME=pihole
XCTX=1020
XIP=192.168.10.20

XSRV_PATH=/etc/vservers/.defaults/vdirbase
XTMPL=$XSRV_PATH/.templates/debian_10.11_buster.tgz

# Build from template
vserver $XNAME build -m template \
  --context $XCTX \
  --hostname $XNAME.my.local.domain \
  --interface enp4s0:$XIP/24 \
  -- -d buster \
  -t $XTMPL

echo "$XNAME" > $XSRV_PATH/$XNAME/etc/hostname
echo "$XIP $XNAME.my.local.domain $XNAME" \
  >> $XSRV_PATH/$XNAME/etc/hosts

cp $XSRV_PATH/.templates/etc/resolv.conf \
   $XSRV_PATH/$XNAME/etc

cp $XSRV_PATH/.templates/etc/rsyslog-j2.conf \
   $XSRV_PATH/$XNAME/etc/rsyslog.d

# Remove restriction on /tmp
sed -i "s/size=16m,//g" /etc/vservers/$XNAME/fstab

# Remove restrictions needed by Pi-hole/DHCP
echo "CAP_NET_RAW" > /etc/vservers/$XNAME/bcapabilities
echo "SYS_ADMIN" >> /etc/vservers/$XNAME/bcapabilities
echo "NET_ADMIN" >> /etc/vservers/$XNAME/bcapabilities
echo "CAP_SYS_RESOURCE" >> /etc/vservers/$XNAME/bcapabilities

vserver $XNAME start
vserver $XNAME exec apt-get update
vserver $XNAME exec apt-get -y upgrade
vserver $XNAME exec apt-get -y install sudo

vserver-stat

My template's /etc/resolv.conf initially contained:

domain my.local.domain
search my.local.domain
nameserver 10.2.10.100
nameserver 8.8.8.8

This needs to be changed later if the Pi-hole guest itself is to use its own DNS service.

I also copied an rsyslog configuration that forwards logs to my central logging server:

*.*    @10.2.10.2

VServer capabilities

The additional entries in bcapabilities were added because Pi-hole's DHCP service needed access to network functions that are normally restricted inside a VServer guest.

Without the required capability I observed errors such as:

Oct 10 13:02:22 dnsmasq-dhcp[5778]:
ARP-cache injection failed: Operation not permitted

After adding the capabilities above, DHCP started working correctly.

I did not determine the minimal capability set at the time. I added several capabilities until the problem disappeared. Granting unnecessary capabilities weakens container isolation, so for a new installation the required set should be determined more carefully.

Tweaking the Pi-hole VServer

After creating and starting the guest, enter it with:

vserver pihole enter

My VServer guest was not booted with systemd as PID 1. Consequently, running systemctl produced:

root@pihole:/# systemctl
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

That was not a problem for the guest itself, but the Pi-hole installer detected systemctl and attempted to use it. In the version I installed in 2022 this caused installation to fail when starting lighttpd.

My workaround was simply to temporarily rename systemctl so that the installer could not find it:

apt-get -y install curl
mv /usr/bin/systemctl /usr/bin/systemctl.bak
curl -sSL https://install.pi-hole.net | bash
This was a workaround for the Pi-hole installer as it behaved in 2022. Do not assume that a current Pi-hole installer needs or supports the same workaround.

I selected a custom upstream DNS server during installation, but that choice depends on the network.

Moving clients to Pi-hole

Initially my router was still acting as DHCP server. I changed the DHCP option for DNS server so that clients received the IP address of the Pi-hole guest.

After renewing their DHCP leases, clients began using Pi-hole for DNS lookups. On many systems simply disconnecting and reconnecting the network interface is enough to obtain a new lease.

Once Pi-hole was installed and DNS queries were reaching it, the web interface was available at:

http://pi.hole/admin

In my installation Pi-hole's own DHCP service was initially disabled, probably because another DHCP server was already active. I later disabled DHCP in the router and enabled Pi-hole's DHCP server instead.

Post-installation notes

Letting the Pi-hole host use itself for DNS

Once everything was working, I configured the guest itself to query its local Pi-hole resolver.

My /etc/resolv.conf then looked approximately like:

domain my.local.domain
search my.local.domain

nameserver 127.0.0.1

#nameserver 10.2.10.100
#nameserver 8.8.8.8
Do not make this change until the local DNS resolver is known to work. Otherwise the guest can lose DNS resolution, which also prevents operations such as apt-get from locating package servers.

Fixed IP addresses

In the Pi-hole version I used, static DHCP mappings were stored in:

/etc/dnsmasq.d/04-pihole-static-dhcp.conf

The format was:

dhcp-host=MAC-address,IP-address,hostname

For example:

dhcp-host=00:67:98:BA:DD:25,192.168.10.97,ipcam-2ysec
dhcp-host=28:80:23:8C:B9:00,192.168.10.4,hp1810-ge-8c-b9-00

Local hostnames

Local hostname mappings were stored in:

/etc/pihole/custom.list

The format was simply:

IP-address hostname

For example:

192.168.10.1  gw.my.local.domain
192.168.10.21 z590a.my.local.domain

Log flooded with lookups

When I opened Pi-hole's web administration interface in Firefox and selected Tools → Tail pihole.log, I sometimes saw a continuous stream of queries similar to:

Oct 17 06:24:03: query[A] pi.hole from 192.168.10.72
Oct 17 06:24:03: Pi-hole hostname pi.hole is 192.168.10.20
Oct 17 06:24:03: query[A] pi.hole from 192.168.10.72
Oct 17 06:24:03: Pi-hole hostname pi.hole is 192.168.10.20
...

Here 192.168.10.20 was the Pi-hole server and 192.168.10.72 was my workstation.

In my tests this behaviour was associated with Firefox. Using another browser avoided the repeated lookups. I did not investigate the cause further.

See also