Overview
A Home lab is a great way for engineers and hobbyists to amp up their lives. From having a dedicated sandbox to test their projects to being your own media server, home labs are a fun thing to do. If you’re following this series, you know I’m exploring home labs by building one for myself. This is the fifth post and so far we have covered various aspects of it. We started by understanding the home lab followed by exploring the options, building, assembling and configuring it to make it ready for hosting applications. In the last post we hosted a media server to backup and stream your own media collection. In this post we’re going to host another utility application for your home.
The internet has changed a lot over the years since its inception. It started with the belief that the information should be free for everyone. While that concept does have some merit, it also means that there is less incentive for the content creators and hosts to make it available. This gave rise to another way of monetizing the internet; ads. Whether you’re searching the internet for something you need for work or just browsing through your social media, ads are everywhere. They’re also present in different formats such as banners, pop-ups, product listings, native ads as well as full-screen ads such as the ones on YouTube videos or while playing mobile games.
Ads are at very least annoying if not invading your privacy through internet trackers. Hence, many of us are looking for a way to avoid these ads and a popular way of doing that is to install ad blocker extensions on your browsers. While that does work when you are on your computers, it’s ineffective on other devices such as mobile phones, TVs. This means you need to opt for different solutions on different devices, whereas you may not be able to do anything on some devices such as TVs. What if I told you that you can install a single solution for all the devices in your home to block ads with minimal configuration.
Enter the Pi-hole. Pi-hole is a DNS sinkhole for your network DHCP server. It helps you block advertisements and internet trackers by blocking the DNS lookups to known ad servers. It works at your network level which means it will block ads for all the devices connected to it, as opposed to some apps and extensions that work only at the device or browser level. Hence it’s a one-stop solution for all your devices irrespective of whether the individual devices offer you to install ad blocking apps/services or not.
My Setup
If you are following this series on Home Labs, then you would be aware that I have a Home Lab set up with four Intel NUC mini PCs. I have installed a K3s Kubernetes cluster on them which I can use to host multiple containerized applications.
Pi-hole also offers a container image which you can use to run it either with container runtimes, such as docker directly or run it with a container orchestrator such as Kubernetes.
I would be using the Pi-hole container image and hosting it on my K3s cluster using Acorn. Acorn is an open source, simple application deployment framework for Kubernetes. It helps you define and package the application container configurations in a single artifact, which can be consistently deployed across multiple environments.
Running Pi-hole application
Installing Acorn
To run any application using Acorn, you first need to install Acorn CLI on your machine. You can then use the Acorn CLI and then install Acorn on the target Kubernetes cluster using the same. Since I’ve already done that for the Plex Media Server Installation, I don’t need to do it again. Pls refer to the Install Acorn section in my previous post if you do need to install it for you.
Creating NFS volumes
We also need a couple of persistent volumes to mount onto the Pi-hole container. The container will use them to store and retrieve the Pi-hole configuration. Just like we created volumes to install Plex on our home lab setup, We’ll use NFS volumes for this purpose. Hence we’ll first need to create 2 NFS shares on the storage node of our cluster.
Create below 2 directories at desired locations to share them over NFS. I’ve chosen the same location where I had mounted my 1 TB partition in the previous post. You may choose a different location based on whether or not you have a separate disk for persistent data and where it’s mounted.
$ mkdir -p /mnt/sda1/pihole/{etc,dnsmasq} # Create 2 directories for NFS
Update the /etc/exports
file to export the above directories as NFS shares. Add below two lines at the end of the file.
/mnt/sda1/pihole/etc 192.168.31.0/24(rw,sync,no_root_squash,no_subtree_check)
/mnt/sda1/pihole/dnsmasq 192.168.31.0/24(rw,sync,no_root_squash,no_subtree_check)
Restart the NFS service for above changes to take effect.
$ sudo systemctl restart nfs-kernel-server
Creating Acornfile
The Acornfile for Pi-hole deployment has just two sections. First one to define the Pi-hole container and the second to define the volumes to use with the container.
containers: {
pihole: {
env: {
"WEBPASSWORD": "<PIHOLE_ADMIN_PASSWORD>"
"TZ": "Asia/Kolkata"
"DHCP_ROUTER": "<YOUR_DHCP_SERVER_IP"
"FTLCONF_LOCAL_IPV4": "<LOAD_BALANCER_IP>"
}
image: "ghcr.io/pi-hole/pihole"
ports: {
publish: [
"53/tcp",
"5353:53/udp",
"67/udp",
"8080:80/tcp",
"8443:443/tcp"
]
}
dirs: {
"/etc/pihole": "volume://pihole-pv-nfs-etc"
"/etc/dnsmasq.d": "volume://pihole-pv-nfs-dnsmasq"
}
}
}
...
The environment variables mentioned in the container below are the minimum number of variables you would need to provide, except one. The first one with the key WEBPASSWORD
is the admin password to login to the Pi-hole console. You may skip this one in your Acornfile
and the Pi-hole container will generate a random password for you. Use the below command to retrieve it from the logs. If you do mention it here, replace the placeholder above with a secure password.
$ export PIHOLE_NS=$(kubectl get appinstances -n acorn pi-hole -ojson | jq -r '.status.namespace')
$ kubectl logs $(kubectl get po -oname -n $PIHOLE_NS) -n $PIHOLE_NS | grep 'random password'
Acorn can also generate various types of secrets for your applications. You can read more about it in the Acorn secrets documentations. This Acorn feature is especially useful for you want to install an application across different environments with a single Acornfile.
The next argument sets your current time zone. The next one is your DHCP server address. It usually is the same as your router IP address, unless you’re running a DHCP server of your own. Pi-hole can also serve as a DHCP server, if you want to use it. In this post we’re only going to focus on its DNS capabilities to filter out ads.
The last one is supposed to be the node IP address on which the container is running, on which the Pi-hole services will be served. Since Kubernetes can run the container on any of the four nodes, we can’t specify the node address. So instead I provided one of the external IPs that the ServiceLB assigns to the services it exposes with Load Balancer.
Also, in the Ports section, I had to remap the exposed 80
and 443
ports to 8080
and 8443
. This is because the ServiceLB load balancer uses the underlying node ports to expose the services and K3s uses these ports for Traefik Ingress Controller deployment.
...
volumes: {
"pihole-pv-nfs-etc": {
size: 1G
class: "nfs-etc"
accessModes: "readWriteMany"
}
"pihole-pv-nfs-dnsmasq": {
size: 1G
class: "nfs-dnsmasq"
accessModes: "readWriteMany"
}
}
The second section is the list of Volumes used with the container. If you are familiar with the Kubernetes deployment manifests, the volumes section here maps to the PVC section workloads. In fact, it does create corresponding PVCs with the given names and configuration.
Create Persistent Volumes
Since we don’t have an external provisioner for NFS volumes, we’ll have to create the PVs manually, along with the storage classes. The volumes section above will match the volume sizes, storage class and access modes with the pre-existing volumes and bind to them. Hence we first need to create the storage classes and PVs before we can run our application.
Run below commands to clone the remote repository and update the kubernetes manifests with your NFS share details.
$ git clone https://github.com/samkulkarni20/pi-hole-acorn.git #clone the repo
$ cd pi-hole-acorn
$ sed -i 's/NFS_SERVER_IP/<YOUR_NFS_SERVER_IP>/g' {sc.yaml,pv.yaml}
$ sed -i 's/PIHOLE_ETC_NFS_PATH/<CONF_DIR_PATH_ON_SERVER>/g' {sc.yaml,pv.yaml}
$ sed -i 's/PIHOLE_DNSMASQ_NFS_PATH/<DATA_DIR_PATH_ON_SERVER>/g' {sc.yaml,pv.yaml}
Apply the manifests to create storage classes and PVs.
$ kubectl create -f sc.yaml # Create storage classes
$ kubectl create -f pv.yaml # Create the persistent volumes
Run Pi-hole
With all above steps done, we are now ready to run the Pi-hole application. Run the following Acorn CLI command for the same.
$ acorn run -n pi-hole .
This command will build a Pi-hole container with the given configuration and upload it to the local container repository on the cluster. It will also create all the required Kubernetes objects, such as deployments, services, etc. and return when all the pods for the application are in “Ready” state.
Once the command returns successfully, get the load balancer external ip(s) and open the link http://<LB_IP>:8080/admin
. Use the below command to get the load balancer ip(s).
$ kubectl get svc -n $(kubectl get appinstances -n acorn pi-hole -ojson | jq -r '.status.namespace')

If you haven’t configured a specific password to run the Pi-hole application, then use the previously mentioned commands to find the random generated password and use your password to login to the web console.
Pi-hole uses block lists to maintain a list of ad domains to block access to. Pi-hole has a block list that is configured out of the box, but you can also configure additional blocklists from external sources such as this block list organized by categories. Add the blocklists by clicking on Adlists.

When done, navigate to the ‘Update Gravity’ menu under ‘Tools’ and click on update. This will update Pi-hole with the domains from the block lists.

Configure Pi-hole As Primary DNS
With the Pi-hole application up and configured, all we need to do is to configure it as the primary DNS on the network’s DHCP server and see it work. Once it’s configured as DNS, Pi-hole will only allow DNS lookups for the sites which aren’t in the blocklists we’ve configured. Here we will see how to configure it on the routers’ DHCP server. If you’re running a separate DHCP server yourself, you would have to follow a process appropriate for it.
Open your router’s management console and navigate to the DHCP configuration location. Typically you’d find it under Network -> LAN. Put the Pi-hole IP address as your primary and only DNS, save and restart your router if required.

This completes your Pi-hole setup. Now open your favorite websites and see Pi-hole blocking most of the ads on it. Another way to test it is with AdBlock tester sites e.g. https://adblock-tester.com/, which test various methods by which ads are displayed and gives you a score of your AdBlockers effectiveness.
Conclusion
In this post we saw how Pi-hole helps you block ads easily and efficiently on all devices across your network. We saw how to install Pi-hole on your home lab and configure it as the primary DNS provider for your network.
We installed the Pi-hole app using Acorn, which is a simple application deployment framework for Kubernetes. You can learn more about Acorn at https://docs.acorn.io/ or by joining a hands-on training class.
Below are the previous posts in this series on Home Lab. Pls go through them if you haven’t already.
- Building a Kubernetes Home Lab from the Ground Up
- Hardware and Networking Setup for My Home Lab
- Software Setup for My Home Lab
- Hosting Plex Media Server On My Home Lab
In the next and last post of the series, we will create a dashboard for the applications we have installed or will install in the future in our home lab.
Sameer Kulkarni is a software engineer with 14+ years of experience and is working as a Principal Engineer at InfraCloud. You can chat with him on Twitter and read more of his work on Medium.