Published 2026-05-27 · 10 min read

Pi-hole security checklist — admin panel, DNS exposure, and update hygiene

Pi-hole sits in an unusual place on your network. Every DNS query from every device — phones, TVs, laptops, IoT junk — goes through it. That makes it the single highest-leverage box in most homelabs and the one most likely to be running on a Raspberry Pi that hasn't been audited since the day it was flashed. Here are ten hardening checks worth doing this weekend.

For the wider context — what to do before any service becomes reachable from outside the LAN — see before you expose a service to the web. This post is narrower: a Pi-hole that's already running and already in your DNS settings, and the ten things to recheck before you forget about it for another year.

Step 1 — Understand what a compromised Pi-hole actually gives an attacker

Pi-hole's threat model is unusual. Most self-hosted services hold one thing — files, metrics, dashboards. Pi-hole holds the resolver path itself. If someone roots your Pi-hole, they don't just get a Raspberry Pi; they get a full passive view of every DNS lookup on your LAN. Which streaming services you use, which banks, which employer's VPN, which dating apps your kids' phones are talking to. All of it.

That's the passive case. The active case is worse: an attacker who can flip a record in the Pi-hole database can redirect any hostname on the LAN to any IP. github.com goes to a malicious proxy. The OS update server quietly resolves to attacker infrastructure. There's no certificate warning if the attacker holds a wildcard cert for a domain they control and poisons the CNAME to point at it.

The takeaway: Pi-hole isn't "just a DNS server with ad blocking." It's a man-in-the-middle position by design. Treat it accordingly.

Step 2 — Never expose the web admin UI past the LAN

Pi-hole's web interface lives at /admin. The first and most common compromise vector is finding one of these reachable from the public internet, usually because someone port-forwarded port 80 to "check on it from work" and never put auth in front of it.

The admin password lives in different places depending on how Pi-hole was installed. Bare metal:

# Set or change the admin web password
sudo pihole -a -p

# Disable the admin password entirely (only do this on an
# isolated, single-user LAN — and even then, prefer setting one)
sudo pihole -a -p ''

Docker installs almost always set WEBPASSWORD as an environment variable in the Compose file. Two things to check there: that it's set to something non-default, and that the Compose file itself isn't committed to a public Git repo with the password in plaintext (it happens more than you'd think).

Pi-hole has no built-in 2FA. If you genuinely need remote access to the admin UI, the right pattern is to put it behind an authenticating reverse proxy — Authelia, Authentik, or Cloudflare Access in front of the Pi-hole web port. Don't port-forward the admin UI even with a password set; the password protects the app, but the network-level exposure means any future Pi-hole admin CVE turns into your CVE the day it lands. The exposed admin surfaces post covers why this category is the single biggest cause of self-host compromise.

Step 3 — Bind the DNS resolver to the LAN interface only

Pi-hole's whole point is to answer DNS on port 53. The question is where it answers. The default install on a single interface is fine. The dangerous case is a multi-homed host where DNS ends up listening on 0.0.0.0 and the router has a port-forward or the firewall has a hole.

Check what port 53 is bound to:

sudo ss -tulpn | grep ':53 '
# look for 0.0.0.0:53 or [::]:53 — both are wildcard binds
# you want 192.168.x.x:53 or similar (LAN IP only)

In the Pi-hole admin UI, Settings → DNS → Interface listening behaviour controls this. The sensible option is "Allow only local subnets" — Pi-hole will refuse DNS from anything that isn't on a directly-attached subnet. Don't pick "Permit all origins" unless you genuinely intend to run a public resolver, in which case you have a different post to read.

A public Pi-hole isn't just a bad idea for privacy; it's a DNS amplification weapon. Open resolvers are the standard ingredient in reflection DDoS attacks, and most ISPs will eventually notice and shut your line off. Run an external port scan against your public IP and confirm 53 is closed:

nmap -Pn -p 53 -sU -sT your.public.ip.here

Step 4 — Pick a reputable upstream and use encrypted DNS

By default Pi-hole forwards queries to the upstream you picked during install — usually Google, Cloudflare, or your ISP. Two things to fix here. First, get off your ISP if you haven't already; ISPs have a long history of inserting their own answers into DNS responses for "search assistance" and ad tracking. Second, the link between Pi-hole and the upstream should be encrypted, not plain port 53 over the open internet.

The standard pattern is cloudflared or unbound running locally as a DNS-over-HTTPS or DNS-over-TLS bridge:

# Pi-hole → cloudflared (localhost:5053) → 1.1.1.1 over HTTPS
# In Pi-hole DNS settings, set custom upstream:
#   127.0.0.1#5053

# cloudflared config (/etc/cloudflared/config.yml)
proxy-dns: true
proxy-dns-port: 5053
proxy-dns-upstream:
  - https://1.1.1.1/dns-query
  - https://1.0.0.1/dns-query

Quad9 (9.9.9.9) and NextDNS are good alternatives if you don't want Cloudflare. Whichever you pick, the goal is the same: your ISP, your transit, and anyone on the path between your house and the upstream sees encrypted blobs instead of a log of every domain anyone in the household visits.

Step 5 — Audit blocklist sources before adding them

Blocklists are a supply chain. Every list you subscribe to is a remote source of rules that Pi-hole pulls down and applies to every DNS lookup. A malicious or hijacked blocklist could blackhole auth.bank.example.com for a day, or — more subtly — inject entries that interfere with security tooling.

Stick to maintainers with public review and active history:

What to avoid: random pastebins, lists copied from forum posts without provenance, and anything that hasn't been updated in a year. The Pi-hole community periodically rediscovers a list that blackholed a major site for weeks before anyone noticed. Pin blocklist URLs to ones whose maintenance you can verify, and review the active list quarterly. Settings → Adlists in the admin UI; weed out anything you don't recognise.

Step 6 — Audit the FTL daemon

pihole-FTL is the engine — the C daemon that actually answers DNS queries and writes the telemetry database. It listens on a local Unix socket and a TCP port (default 4711) used by the web UI to read live query stats. That port should never leave the host.

# Check FTL is only on localhost
sudo ss -tlnp | grep pihole-FTL
# expected: 127.0.0.1:4711 or [::1]:4711, not 0.0.0.0:4711

The FTL config lives at /etc/pihole/pihole-FTL.conf. Two settings worth looking at: PRIVACYLEVEL controls how much per-client detail FTL stores (set higher than the default if multiple humans share the LAN and you'd rather not have a per-device query log), and the MAXDBDAYS retention period (default 365 days of query history sitting on disk — shorten this if the box gets stolen often or the SD card is small).

If you've ever exposed the Pi-hole host to a wider network for remote management, run ss -tulpn again and confirm nothing besides 53 and the LAN-only web port is reachable from outside the host.

Step 7 — Get Docker port publishing right

Half of all "Pi-hole accidentally public" incidents trace back to one line in a Docker Compose file. The difference between these two:

# BAD — publishes to every interface, including any public IP
ports:
  - "53:53/udp"
  - "53:53/tcp"
  - "80:80/tcp"

# GOOD — publishes only on the LAN IP of the Pi-hole host
ports:
  - "192.168.1.10:53:53/udp"
  - "192.168.1.10:53:53/tcp"
  - "192.168.1.10:80:80/tcp"

Docker's default behaviour is to bind the published port to 0.0.0.0, which on a multi-homed host can mean the WAN interface. Worse, Docker manages its own iptables rules and will happily punch holes through ufw without warning. Even if you ran ufw default deny incoming from the pre-exposure checklist, a Docker port-forward bypasses it.

Three checks for any containerised Pi-hole:

  1. Every ports: entry has an IP prefix limiting it to the LAN address.
  2. docker compose ps shows the bind addresses match what you intended (look at the PORTS column).
  3. An external port scan against the public IP returns nothing on 53, 80, or 443 unless you have a public service that needs those ports.

Step 8 — Back up the configuration and lists

Pi-hole stores its state in two places: /etc/pihole (settings, blocklists, the FTL query DB) and /etc/dnsmasq.d (DNS forwarding rules and local DNS records). The built-in backup tool is the Teleporter:

# Export current configuration to a tar.gz
sudo pihole -a -t
# Output: pi-hole-teleporter_YYYY-MM-DD_HH-MM-SS.tar.gz

# Automate via cron (root crontab)
0 3 * * *  /usr/local/bin/pihole -a -t && \
           mv /root/pi-hole-teleporter_*.tar.gz /backups/pihole/

The Teleporter archive is also what the admin UI's Settings → Teleporter page uses for one-click restore. For a belt-and-braces homelab, also rsync the raw /etc/pihole and /etc/dnsmasq.d directories nightly to a NAS or another host. Disk failures eat Raspberry Pi SD cards on a routine timeline; the day yours dies is not the day to rediscover that the only copy of the local DNS records was on it.

Keep the Teleporter exports somewhere encrypted. The archive includes the admin password hash and any custom DNS records that might reveal your internal hostnames.

Step 9 — Patch Pi-hole and FTL on a real cadence

The Pi-hole project ships updates regularly — both the web UI and the FTL daemon — and most installs are running something a year out of date. The fix is trivial:

# Update Pi-hole core, web UI, and FTL
sudo pihole -up

# For Docker installs, pull the new image
docker compose pull pihole
docker compose up -d pihole

Run it monthly at a minimum. Subscribe to the Pi-hole release notes on GitHub or the project blog so FTL security advisories don't surprise you. The patching gap on self-hosted services covers why this matters more than people expect — homelab software typically lags upstream by 6–18 months, and unlike a packaged distro, there's no unattended-upgrades equivalent watching for you.

Pi-hole runs on top of Linux, so the base system needs the same attention. If it's a Raspberry Pi, the OS-level openssl and sshd are usually the bigger CVE source than Pi-hole itself — see Raspberry Pi outdated OpenSSL for the canonical example. Run apt full-upgrade on the same monthly cadence as pihole -up and reboot when the kernel rolls.

Step 10 — Re-audit after every LAN change

The Pi-hole that was perfectly safe yesterday can be exposed today because something on the network around it changed. The router rebooted and lost its port-forward rules. A new VLAN got added and the firewall didn't get matching ACLs. A guest network was set up that turns out to route DNS through the main subnet. Someone reset the router to factory and the rules vanished.

The audit isn't elaborate. It's the same external scan from Step 3:

# From off-LAN — phone hotspot, $5 VPS, friend's house
nmap -Pn -p 53,80,443 -sU -sT your.public.ip.here

The answer should be the same it was last month. When it isn't, you find out which network change introduced the exposure and reverse it. This is the principle from the monthly homelab security checklist: hardening isn't a state, it's a process. The state regresses on its own — every router firmware update, every new device, every weekend tinkering session is an opportunity for drift.

The 30-minute homelab security baseline is a good companion piece: the Pi-hole audit fits naturally inside the wider monthly sweep.

Where Noxen fits in

Noxen recognises Pi-hole as one of ~70 admin services it fingerprints, and flags it whenever the web UI is reachable on any host it's enrolled. Scheduled scans catch the case where the Pi-hole was safely LAN-only yesterday and a router change exposed /admin today. The Mac-native control plane means the scan history and drift diff live on your desk, not in a SaaS console — important if the whole point of running Pi-hole was getting query logs off third-party infrastructure.

Try Noxen$79 one-time, agentless, diff-from-yesterday reports for your homelab fleet.

Scan your Linux fleet from your Mac

Noxen runs nightly agentless audits over SSH and shows only what changed since the last scan — new CVEs, config drift, newly exposed admin services like Pi-hole. Mac-native control plane, no SaaS round-trip.

Buy Noxen — $79 one-time Download free trial