How to deploy pihole and wireguard on kubernetes using a recursive dns

In this tutorial we gonna deploy a dns add-blocker with pihole using a recursive dns as upstream server accessible in LAN network and internet through wireguard vpn. We utilized K3S as kubernetes provider.


  • A computer running any linux distribution (in this tutorial I’m using debian buster)
  • This computer needs to have at least 1 Gb of ram and 2 cores.
  • This computer needs to have an static ip address (in my case, LAN:
  • Configure the firewall to accept inbound connections in the following ports:

53/tcp, 53/udp, 80/tcp, 443/tcp, 51820/udp

  • In order to connect from internet, you need to open the following ports in your ISP’s Router:

80/tcp (Pihole Web Interface HTTP)

443/tcp (Pihole Web Interface HTTPS)

51820/tcp (Wireguard VPN)

  • In order to connect to pihole via web UI from internet you need to have a FQDN that points to your Network (in this tutorial I'm using google domains, you can use duckdns if you don't have a domain)
  • A functional K3S cluster (See Installation guide). This tutorial should work with K8S, but you need to deploy some extra features like Traefik Ingress, Klipper Service Load Balancer
  • You need to have kubectl to perform operations in the K3S cluster





$ kubectl apply -f k8s/01-namespaces.yaml

Dynamic DNS

$ kubectl apply -f k8s/02-dynamic-dns-google.yaml


This manifest comes with:

  • unbound StatefulSet configured as recursive DNS resolver
  • Cluster IP service to 53/tcp and 53/udp
$ kubectl apply -f k8s/03-unbound.yaml

Test Unbound installation

Create directories

$ sudo mkdir -p /var/lib/{pihole,wireguard}


This manifest comes with:

  • Persistent volume type hostPath (/var/lib/pihole)
  • Persistent Volume claim
  • Config Map (Timezone, admin email and upstream dns)
  • Secret (Web Password)
  • Pihole StatefulSet
  • Cluster IP Services (Pihole UI, Pihole DNS)
  • LoadBalancer Services (Pihole DNS bind to host)

You need to configure:

  • Time Zone (pihole-configmap)
  • Admin email (pihole-configmap)
  • Web Password (pihole-secret)
$ kubectl apply -f k8s/04-pihole.yaml

Test Pihole installation


This manifest comes with:

  • Persistent volume type hostPath (/var/lib/wireguard)
  • Persistent Volume claim
  • Config Map (Timezone, server url, number of peers, etc)
  • Wireguard StatefulSet
  • LoadBalancer Service (Wireguard listen port 51820/udp)

You need to configure:

  • Timezone (wireguard-configmap)
  • Server URL (wireguard-configmap)
  • Number of peers (wireguard-configmap)
$ kubectl apply -f k8s/05-wireguard.yaml

Wireguard Client config

You can also copy the config files for each peer located at /var/lib/wireguard/config/peer<N>/peer<N>.conf

Extra (Ingress Configuration for Pihole UI)

Deploy cert-manager

$ kubectl apply -f

Deploy Cluster Issuer (Let’s Encrypt)

$ kubectl apply -f k8s/06-cluster-issuer-letsencrypt.yaml


$ kubectl apply -f k8s/07-ingress.yaml

How to use

If you have been following this tutorial so far you will see the following resources on your kubernetes cluster

And the Pihole admin User Interface accessible through internet via FQDN

Engineer || MSc student || DevOps in progress