AdGuard Home web UI port set to 443 - pod crash loop¶
Symptoms¶
The AdGuard Home pod enters a crash loop shortly after first-run setup, cycling
through Running → Error → CrashLoopBackOff with a rapidly increasing restart count:
kubectl get pods -n adguard
# NAME READY STATUS RESTARTS AGE
# adguard-home-7bbd7b85f8-vlhw6 0/1 CrashLoopBackOff 38 2h
Pod events show the liveness and readiness probes repeatedly failing on port 3000:
kubectl describe pod -n adguard -l app=adguard-home
# Warning Unhealthy ... Readiness probe failed: dial tcp <pod-ip>:3000: connection refused
# Warning Unhealthy ... Liveness probe failed: dial tcp <pod-ip>:3000: connection refused
# Normal Killing ... Container adguard-home failed liveness probe, will be restarted
The Tailscale proxy for the web UI also logs connection refused errors:
kubectl logs -n tailscale <ts-adguard-home-...> | grep "proxy error"
# http: proxy error: dial tcp 10.43.x.x:3000: connect: connection refused
Root cause¶
The AdGuard Home first-run setup wizard asks for an Admin Web Interface port.
If this is changed from the default 3000 to 443, AdGuard binds its web UI to
port 443 instead of 3000. The Kubernetes liveness and readiness probes are hardcoded
to check http://<pod-ip>:3000/ - they fail immediately, and the kubelet kills and
restarts the container in a loop.
The pod logs confirm AdGuard is running but on the wrong port:
Note: changing the web UI port to 443 is unnecessary in this setup. The Tailscale
Ingress terminates HTTPS externally and proxies to http://<cluster-ip>:3000
internally. AdGuard never needs to serve TLS itself.
Fix¶
1. Suspend Flux reconciliation temporarily¶
Flux will keep reconciling the deployment during the repair. Suspend the kustomization:
2. Scale the deployment to zero¶
kubectl scale deployment adguard-home -n adguard --replicas=0
# Wait for all pods to terminate
kubectl wait --for=delete pod -l app=adguard-home -n adguard --timeout=60s
3. Spin up a debug pod to edit the config¶
The config is stored on the adguard-conf Longhorn PVC at
/opt/adguardhome/conf/AdGuardHome.yaml.
kubectl run adguard-fix -n adguard --restart=Never \
--image=busybox \
--overrides='{
"spec": {
"volumes": [{"name":"conf","persistentVolumeClaim":{"claimName":"adguard-conf"}}],
"containers": [{
"name": "fix",
"image": "busybox",
"command": ["sh","-c","sleep 600"],
"volumeMounts": [{"mountPath":"/conf","name":"conf"}]
}]
}
}'
# Wait for it to start
kubectl wait pod adguard-fix -n adguard --for=condition=Ready --timeout=60s
4. Patch the port in the config file¶
kubectl exec adguard-fix -n adguard -- \
sed -i 's/address: 0.0.0.0:443/address: 0.0.0.0:3000/' /conf/AdGuardHome.yaml
# Verify
kubectl exec adguard-fix -n adguard -- grep 'address:' /conf/AdGuardHome.yaml
# address: 0.0.0.0:3000 ✓
5. Clean up and restore¶
# Remove the debug pod
kubectl delete pod adguard-fix -n adguard
# Resume Flux reconciliation (Flux will scale the deployment back to 1)
flux resume kustomization adguard -n flux-system
6. Verify¶
kubectl get pods -n adguard -w
# adguard-home-...-xxxxx 0/1 ContainerCreating 0 5s
# adguard-home-...-xxxxx 1/1 Running 0 30s ✓
kubectl logs -n adguard -l app=adguard-home | grep "go to http"
# [info] go to http://10.42.x.x:3000 ✓
The web UI should be reachable at https://adguard.tailnet.ts.net within
a few seconds of the pod reaching Running.
Prevention¶
During the AdGuard setup wizard, leave the Admin Web Interface port at 3000.
The Tailscale Ingress handles HTTPS on port 443 externally. See the
first-run setup guide for the full list of recommended
wizard settings.