AdGuard Home Helm Chart
A Helm chart for deploying AdGuard Home, a network-wide DNS ad and tracker blocker, on Kubernetes.
Introduction
This chart deploys AdGuard Home on a Kubernetes cluster using the Helm package manager. AdGuard Home is a self-hosted DNS server that blocks ads and trackers for every device on your network, and can also act as a DHCP server, DNS-over-TLS/HTTPS/QUIC resolver, and DNSCrypt server.
Source code: https://github.com/rtomik/helm-charts/tree/main/charts/adguard-home
Prerequisites
- Kubernetes 1.19+
- Helm 3.0+
- PV provisioner support (if persistence is needed)
- A way to route real LAN clients to the DNS Service (LoadBalancer/MetalLB, NodePort, or
hostNetwork: true) if you intend to use it as your network's resolver
Installing the Chart
Uninstalling the Chart
Configuration Examples
Minimal Installation (admin UI only, no DNS exposed on the LAN)
Expose DNS to the LAN via LoadBalancer (e.g. MetalLB)
Enable DNS-over-TLS / DNS-over-QUIC and DNS-over-HTTPS
Enable the DHCP server
DHCP requires hostNetwork: true - it cannot be proxied through a ClusterIP/LoadBalancer Service.
Use an existing PVC
Parameters
Global Parameters
| Name |
Description |
Default |
nameOverride |
Override the release name |
"" |
fullnameOverride |
Fully override the release name |
"" |
Image Parameters
| Name |
Description |
Default |
image.repository |
AdGuard Home image repository |
adguard/adguardhome |
image.tag |
Image tag |
v0.107.79 |
image.pullPolicy |
Image pull policy |
IfNotPresent |
imagePullSecrets |
Image pull secrets |
[] |
Deployment Parameters
| Name |
Description |
Default |
replicaCount |
Number of replicas (keep at 1 - AdGuard Home is not multi-writer safe) |
1 |
revisionHistoryLimit |
Revisions to retain |
3 |
podSecurityContext.runAsNonRoot |
Run as non-root |
true |
podSecurityContext.runAsUser |
User ID |
1000 |
podSecurityContext.runAsGroup |
Group ID |
1000 |
podSecurityContext.fsGroup |
Filesystem group ID |
1000 |
containerSecurityContext.capabilities.add |
Capabilities added (NET_BIND_SERVICE for ports < 1024) |
["NET_BIND_SERVICE"] |
hostNetwork |
Use host networking (required for DHCP, recommended for accurate client IPs) |
false |
nodeSelector |
Node selector |
{} |
tolerations |
Tolerations |
[] |
affinity |
Affinity rules |
{} |
Ports Parameters
| Name |
Description |
Default |
ports.web.port |
Admin dashboard / setup wizard |
3000 |
ports.dns.port |
Plain DNS (TCP+UDP) |
53 |
ports.dot.enabled |
Enable DNS-over-TLS / DNS-over-QUIC |
false |
ports.dot.port |
DoT/DoQ port (TCP+UDP) |
853 |
ports.https.enabled |
Enable DNS-over-HTTPS / HTTPS admin dashboard |
false |
ports.https.port |
HTTPS port (TCP+UDP) |
443 |
ports.dnscrypt.enabled |
Enable DNSCrypt |
false |
ports.dnscrypt.port |
DNSCrypt port (TCP+UDP) |
5443 |
ports.dhcp.enabled |
Enable DHCP server (67/68 UDP, requires hostNetwork: true) |
false |
ports.pprof.enabled |
Enable the debug pprof API |
false |
ports.pprof.port |
pprof port |
6060 |
Service Parameters
| Name |
Description |
Default |
service.type |
Service type |
ClusterIP |
service.annotations |
Service annotations |
{} |
service.loadBalancerIP |
Static LoadBalancer IP (e.g. for MetalLB) |
"" |
Ingress Parameters
| Name |
Description |
Default |
ingress.enabled |
Enable ingress (routes to the admin dashboard only) |
false |
ingress.className |
Ingress class name |
"" |
ingress.annotations |
Ingress annotations |
See values.yaml |
ingress.hosts |
Ingress hosts |
See values.yaml |
ingress.tls |
TLS configuration |
See values.yaml |
Persistence Parameters
| Name |
Description |
Default |
persistence.work.enabled |
Persist /opt/adguardhome/work (query log, filter cache, stats) |
true |
persistence.work.existingClaim |
Use an existing PVC instead of creating one |
"" |
persistence.work.storageClass |
Storage class |
"" |
persistence.work.accessMode |
Access mode |
ReadWriteOnce |
persistence.work.size |
PVC size |
1Gi |
persistence.conf.enabled |
Persist /opt/adguardhome/conf (AdGuardHome.yaml) |
true |
persistence.conf.existingClaim |
Use an existing PVC instead of creating one |
"" |
persistence.conf.storageClass |
Storage class |
"" |
persistence.conf.accessMode |
Access mode |
ReadWriteOnce |
persistence.conf.size |
PVC size |
100Mi |
Resource Parameters
| Name |
Description |
Default |
resources |
Resource limits and requests |
{} |
Health Check Parameters
| Name |
Description |
Default |
probes.liveness.enabled |
Enable liveness probe (TCP check on the admin web port) |
true |
probes.liveness.initialDelaySeconds |
Liveness initial delay |
15 |
probes.liveness.periodSeconds |
Liveness period |
30 |
probes.readiness.enabled |
Enable readiness probe (TCP check on the admin web port) |
true |
probes.readiness.initialDelaySeconds |
Readiness initial delay |
5 |
probes.readiness.periodSeconds |
Readiness period |
10 |
Other Parameters
| Name |
Description |
Default |
extraEnv |
Additional environment variables |
[] |
extraVolumeMounts |
Additional volume mounts |
[] |
extraVolumes |
Additional volumes |
[] |
Notes
- AdGuard Home has no supported way to bootstrap its admin account or DNS settings via
environment variables - complete the setup wizard once at
http://<web-service>:3000
after the first install. The resulting AdGuardHome.yaml is written to the conf PVC,
so it survives pod restarts/upgrades.
- Because AdGuard Home stores state on disk and isn't multi-writer safe, do not scale
replicaCount beyond 1.
- If you plan to use this as your network's DNS resolver, prefer
hostNetwork: true (or
a LoadBalancer Service with externalTrafficPolicy: Local) so AdGuard Home sees real
client IPs rather than a single Service/NAT IP for every device.
Troubleshooting
- Clients all show up as the same IP / filters by client don't work: enable
hostNetwork or use externalTrafficPolicy: Local on a LoadBalancer Service.
- DHCP doesn't hand out leases: DHCP only works with
hostNetwork: true.
- Setup wizard settings don't persist: verify
persistence.conf.enabled is true and the PVC is bound.
Links