--- apiVersion: v1 kind: Namespace metadata: name: pihole --- apiVersion: v1 kind: ConfigMap metadata: name: unbound-config namespace: pihole data: unbound.conf: | server: # Listen only on loopback so only the co-located pihole can query it interface: 127.0.0.1 port: 5335 # IPv4 only for simplicity do-ip4: yes do-udp: yes do-tcp: yes do-ip6: no prefer-ip6: no # Recursive resolver: do not use any forwarders, start from the root servers root-hints: "/opt/unbound/etc/unbound/root.hints" # DNSSEC / hardening harden-glue: yes harden-dnssec-stripped: yes harden-referral-path: yes # Performance / privacy prefetch: yes prefetch-key: yes qname-minimisation: yes aggressive-nsec: yes edns-buffer-size: 1232 num-threads: 1 so-rcvbuf: 1m # RFC1918 / link-local addresses should never come back from the internet private-address: 10.0.0.0/8 private-address: 172.16.0.0/12 private-address: 192.168.0.0/16 private-address: 169.254.0.0/16 private-address: fd00::/8 private-address: fe80::/10 # Hide identity / version hide-identity: yes hide-version: yes --- # Pi-hole config that points dnsmasq at the local unbound sidecar. # Mounted into /etc/dnsmasq.d so it is read on (re)start. apiVersion: v1 kind: ConfigMap metadata: name: pihole-dnsmasq-config namespace: pihole data: 99-unbound.conf: | # Use the recursive unbound sidecar as the only upstream DNS server=127.0.0.1#5335 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pihole-pvc namespace: pihole spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: unbound-pvc namespace: pihole spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Mi --- apiVersion: apps/v1 kind: Deployment metadata: name: pihole namespace: pihole labels: app: pihole spec: replicas: 1 selector: matchLabels: app: pihole template: metadata: labels: app: pihole spec: # The pod itself still needs DNS to (e.g.) download blocklists on gravity # updates. Use the cluster DNS / a public resolver for that - it is NOT # used to answer client queries, which go through the unbound sidecar. dnsPolicy: "None" dnsConfig: nameservers: - 8.8.8.8 - 8.8.4.4 initContainers: - name: unbound-root-hints image: curlimages/curl:8.12.1 command: - /bin/sh - -c - | set -e if [ ! -s /opt/unbound/etc/unbound/root.hints ]; then echo "Downloading root hints..." curl -fsSL https://www.internic.net/domain/named.root -o /opt/unbound/etc/unbound/root.hints else echo "Root hints already present, skipping download." fi volumeMounts: - name: unbound-data mountPath: /opt/unbound/etc/unbound containers: - name: pihole image: pihole/pihole:latest ports: - containerPort: 80 name: http - containerPort: 53 name: dns-tcp protocol: TCP - containerPort: 53 name: dns-udp protocol: UDP env: - name: TZ value: "Europe/Madrid" #- name: WEBPASSWORD #value: "" #- name: FTLCONF_webserver_api_password #value: '' #- name: DNSMASQ_LISTENING #value: "all" - name: FTLCONF_dns_listeningMode value: "all" - name: WEB_PORT value: "80" #- name: VIRTUAL_HOST #value: "pihole" #- name: FTLCONF_LOCAL_IPV4 #value: "0.0.0.0" - name: SKIPGRAVITYONBOOT value: "1" volumeMounts: - name: pihole-data mountPath: /etc/pihole - name: pihole-dnsmasq-config mountPath: /etc/dnsmasq.d/99-unbound.conf subPath: 99-unbound.conf resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m" securityContext: capabilities: add: - NET_ADMIN - SYS_TIME - SYS_NICE - name: unbound image: mvance/unbound:latest ports: - containerPort: 5335 name: unbound-dns-tcp protocol: TCP - containerPort: 5335 name: unbound-dns-udp protocol: UDP volumeMounts: - name: unbound-config mountPath: /opt/unbound/etc/unbound/unbound.conf subPath: unbound.conf - name: unbound-data mountPath: /opt/unbound/etc/unbound resources: requests: memory: "64Mi" cpu: "50m" limits: memory: "256Mi" cpu: "500m" livenessProbe: tcpSocket: port: 5335 initialDelaySeconds: 10 periodSeconds: 30 readinessProbe: tcpSocket: port: 5335 initialDelaySeconds: 5 periodSeconds: 10 volumes: - name: pihole-data persistentVolumeClaim: claimName: pihole-pvc - name: unbound-data persistentVolumeClaim: claimName: unbound-pvc - name: unbound-config configMap: name: unbound-config - name: pihole-dnsmasq-config configMap: name: pihole-dnsmasq-config --- apiVersion: v1 kind: Service metadata: name: pihole-web namespace: pihole labels: app: pihole spec: type: ClusterIP ports: - port: 80 targetPort: 80 protocol: TCP name: http selector: app: pihole --- apiVersion: v1 kind: Service metadata: name: pihole-dns namespace: pihole labels: app: pihole spec: type: LoadBalancer ports: - port: 53 targetPort: 53 protocol: TCP name: dns-tcp - port: 53 targetPort: 53 protocol: UDP name: dns-udp selector: app: pihole