(K3S - 6/8) Self-host Pi-Hole on Kubernetes and block ads and trackers at the network level
This article is part of the series Build your very own self-hosting platform with Raspberry Pi and Kubernetes
- Introduction
- Install Raspbian Operating-System and prepare the system for Kubernetes
- Install and configure a Kubernetes cluster with k3s to self-host applications
- Deploy NextCloud on Kuberbetes: The self-hosted Dropbox
- Self-host your Media Center On Kubernetes with Plex, Sonarr, Radarr, Transmission and Jackett
- Self-host Pi-Hole on Kubernetes and block ads and trackers at the network level
- Self-host your password manager with Bitwarden
- Deploy Prometheus and Grafana to monitor a Kubernetes cluster
Introduction
Pi Hole is a network-wide ad blocker. In a typical home environment, this can cut out almost all ads to all devices in your home, without having to install an ad blocker on every single device. Technically Pi-Hole acts as a DNS sinkhole which filters out unwanted results using a blacklist domains list. Pi-Hole also offers a great admin interface to configure and analyse your network traffic (DNS, DHCP, Black/White list, regex, etc.).
In this new article, we will learn how to deploy Pi-Hole on a Kubernetes self-hosting platform.
Prerequisite
In order to run entirely the tutorial, we will need:
- A running Kubernetes cluster (see previous articles if you haven’t set this up yet)
- Access to your router admin console to configure Pi-Hole as DNS or disable DHCP (replaced by Pi-Hole)
Namespace
We are going to isolate all the Kubernetes objects related to Pi-Hole in the namespace pihole
.
To create a namespace, run the following command:
1 | $ kubectl create namespace pihole |
Persistence
The first step consists in setting up a volume to store the Pi-Hole config files and data. If you followed the previous articles to install and configure a self-hosting platform using RaspberryPi and Kubernetes, you remember we have on each worker a NFS client pointing to a SSD on /mnt/ssd
.
1. Deploy the Persistent Volume (PV)
The Persistent Volume specify the name, the size, the location and the access modes of the volume:
- The name of the PV is
pihole
- The size allocated is 500MB
- The location is
/mnt/ssd/pihole
- The access is ReadWriteOnce
Create the following file and apply it to the k8 cluster.
1 | ## pihole.persistentvolume.yml |
1 | $ kubectl apply -f pihole.persistentvolume.yml |
You can verify the PV exists with the following command:
1 | $ kubectl get pv |
2. Create the Persistent Volume Claim (PVC)
The Persistent Volume Claim is used to map a Persistent Volume to a deployment or stateful set. Unlike the PV, the PVC belongs to a namespace.
Create the following file and apply it to the k8 cluster.
1 | ## pihole.persistentvolumeclaim.yml |
1 | $ kubectl apply -f pihole.persistentvolumeclaim.yml |
You can verify the PVC exists with the following command:
1 | $ kubectl get pvc -n pihole |
Deployment
In the next part, we are now going to deploy Pi-Hole using a modified version open-source Helm chart pihole-kubernetes.
**1. Install the repo **
1 | $ helm repo add mojo2600 https://mojo2600.github.io/pihole-kubernetes/ && helm repo update |
2. Create a secret to store Pi-Hole admin password
Replace <ADMIN_PASSWORD>
by the password of your choice. This password will be used to connect to the Pi-Hole administration interface.
1 | $ kubectl create secret generic pihole-secret \ |
3. Download the Chart values of the chart locally
Run the following command to download the Chart values into the local file pihole.values.yml
.
1 | $ helm show values mojo2600/pihole >> pihole.values.yml |
If you open the file, you will see the default configuration values to setup Pi-Hole. Instead of using the flag --set property=value
like before, we will use the file pihole.values.yml
to make all the changes.
4. Update the values
We now need to update a few properties before installing the Helm chart. Open the file pihole.values.yml
and change the following properties (replace the information surrounded by
1 | ## pihole.values.yml |
The network config might be different if your need to get DHCP working with Pi-hole.
a. I can override my router default DNS config
1 | ## pihole.values.yml |
b. I can’t override my router DNS config and I need to enable DHCP on Pi-Hole (disable on my router) to force the devices to use Pi-Hole as DNS.
In this case, we are going to use the flag hostNetwork=true
and privileged=true
to let the pod use the node network with root privilege which will enable DHCP through network broadcast on port 67 (more info).
1 | ## pihole.values.yml |
4. Install the Chart
In the part, we will install the Helm chart under the namespace pihole
with pihole.values.yml
as configuration file.
1 | $ helm install pihole mojo2600/pihole \ |
After a couple of minutes, check if the pod and service is up and running:
1 | $ kubectl get pods -n pihole -o wide |
1 | $ kubectl get services -n pihole -o wide |
Ingress
To access Pi-Hole admin, we are now going to deploy an Ingress, responsible of making accessible a service from outside the cluster by mapping an internal service:port
to a host. To choose a host, we need to configure a DNS like we did for NextCloud “nextcloud.<domain.com>” in the previous article. However, unlike NextCloud, Pi-Hole have no reason to be exposed on the Internet, we can pick a host that will be resolved internally to our Nginx proxy (available at 192.168.0.240
: LoadBalancer IP). The simplest solution is to use nip.io which allows us to map an IP (in our case 192.168.0.240
) to a hostname without touching /etc/hosts
or configuring a DNS. Basically it resolves <anything>.<ip>.nip.io
by <ip>
without requiring anything else, Magic !
1. Create the file pihole.ingress.yml
Create the following Ingress config file pihole.ingress.yml
to map the route /
to Pi-Hole HTTP service:
1 | ## pihole.ingress.yml |
2. Deploy the ingress
Deploy the Ingress by applying the file pihole.ingress.yaml
.
1 | $ kubectl apply -f pihole.ingress.yaml |
Result
You can now access Pi-Hole via pihole.192.168.0.240.nip.io/admin.
Click on Login on the left menu and enter the password configured earlier in pihole.values.yml
.
If you configured Pi-Hole to be used as DHCP server, you need to go to Settings / DHCP, enable DHCP, configure the IP range and the IP of your network router.