For The Love Of Cloud!

Raspberry Pi as Home Router | Part 3 | DHCP and DNS with PiHole

02 Mar 2022

To complete our router, we need a DHCP server and DNS server. The DHCP server will assign IPs to our internal network, while the DNS server will resolve our queries to their corresponding IPs.

Since I like to have a private and ad-free experience when I surf, I’m running Pi-hole as a container. So the first thing I need to do is setup Docker using the official instructions:

Docker installation

Update the apt package index and install packages to allow apt to use a repository over HTTPS:

sudo apt update
sudo apt install ca-certificates curl gnupg lsb-release

Add Docker’s official GPG key:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Use the following command to set up the stable repository.

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Update the apt package index, and install the latest version of Docker Engine and containerd, or go to the next step to install a specific version:

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

Add user to the docker group.

sudo usermod -aG docker $USER

Logout and log in again to reload the permissions, so that we can run docker commands as the logged in user, and not as sudo.

Now, we’ll install Docker Compose by running this command to download the current stable release of Docker Compose:

 sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

And apply executable permissions to the binary:

sudo chmod +x /usr/local/bin/docker-compose

Pi-hole container

We want our Pi-hole container to serve both DHCP and DNS. The following command will create a container named pihole using the latest Pi-hole image. It will use our internal interface lan0 (with its static IP address, 192.168.1.254) and will enable DHCP, using an IP range between 192.168.1.1 and 192.168.1.100:

docker run -d \
    --net=host \
    -e TZ='America/Chicago' \
    -e WEBPASSWORD: '{mysupersecretpassword}' \
    -e ADMIN_EMAIL='{email@domain.com}' \
    -e ServerIP='192.168.1.254' \
    -e INTERFACE='lan0' \
    -e DHCP_ACTIVE='true' \
    -e DHCP_START='192.168.1.1' \
    -e DHCP_END='192.168.1.100' \
    -e DHCP_ROUTER='192.168.1.254' \
    -e PIHOLE_DOMAIN='{homedomain.local}' \
    -v ./pihole/etc-pihole/:/etc/pihole/ \
    -v ./pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/ \
    --cap-add=NET_ADMIN \
    --restart=unless-stopped \
    --name pihole \
    pihole/pihole:latest

After setting up the container, since I’m using Ubuntu, I need to disable the caching DNS stub resolver that it Ubuntu has, since it will prevent Pi-hole from listening on port 53 (the port used by DNS requests). The stub resolver can be disabled with:

sudo sed -r -i.orig 's/#?DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf

After this, I need to change the nameserver settings, which currently point to the stub resolver (which we have just disabled). I need to point the /etc/resolv.conf symlink to /run/systemd/resolve/resolv.conf by running the following command:

sudo sh -c 'rm /etc/resolv.conf && ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf'

Finally, I need to restart systemd-resolved so that our changes are applied:

sudo systemctl restart systemd-resolved

Having done this, our Pi-hole container should start working as both a DHCP and DNS server. All we have to do now is disable our previous DHCP server, in my case my ISP modem.

With this, we have a fully working router with the added benefit of having a privacy and ad-blocking solution incorporated.

Stay tuned!