Pi-hole turns your Raspberry Pi into a network-wide DNS sinkhole that blocks ads, trackers, and malware domains before they reach any device on your LAN — no browser extensions, no per-device configuration. On a Raspberry Pi 5 running Raspberry Pi OS Bookworm, setup takes about 20 minutes: assign a static IP using nmcli, run the one-line installer, point your router's DNS at the Pi, and every connected device is covered automatically.
Why Pi 5 and Bookworm Break Older Install Guides
The Raspberry Pi 5 ships with Raspberry Pi OS Bookworm (Debian 12, 64-bit), which replaces dhcpcd with NetworkManager as the default network manager. Older Pi-hole guides tell you to edit /etc/dhcpcd.conf — on Bookworm, that file either does not exist or is ignored entirely. This single difference accounts for most Pi 5 installs that appear to complete successfully but then fail with intermittent DNS or a shifting IP address.
Pi-hole is also at version 6 as the stable release. The installer no longer depends on lighttpd — Pi-hole FTL v6 includes its own built-in web server. Configuration is unified into a single file rather than scattered across several config files. The install command itself is unchanged from previous versions.
What You Need Before You Start
- Raspberry Pi 5 (any RAM tier; 4 GB is more than sufficient)
- Raspberry Pi OS Bookworm, 64-bit — the Lite image is enough if you manage via SSH
- Wired Ethernet connection (strongly preferred over Wi-Fi for a DNS server)
- SSH access or a keyboard and monitor attached to the Pi
- The admin password for your router — you will set its DNS server in step 5
- A free IP address outside your router's DHCP pool (if DHCP assigns .100–.200, pick something like .10)
Step 1: Assign a Static IP Using NetworkManager
A DNS server must have a fixed address. If the Pi's IP changes, every device on your network silently loses DNS resolution until the router pushes a new server address. On Raspberry Pi OS Bookworm, the correct tool is nmcli.
First, list your network connections to get the exact connection name:
The wired interface is typically listed as Wired connection 1. Substitute your own values for the IP address, gateway, and connection name. This example assumes a 192.168.1.x network — adjust the subnet to match your router:
Confirm the address applied:
You should see your chosen IP with the correct prefix length. For Wi-Fi, substitute your SSID as the connection name and wlan0 in the verify command, though Ethernet is strongly recommended for a device acting as the DNS server for your entire network.
Step 2: Update the Operating System
The reboot ensures any kernel updates are running before you install Pi-hole, and confirms the Pi comes back up with the static IP intact. On a fresh Pi 5 image this takes 3–6 minutes.
Step 3: Run the Pi-hole Installer
A blue ncurses dialog walks through the configuration choices. The ones that matter most:
- Network interface — select
eth0(orwlan0if Wi-Fi is unavoidable). - Upstream DNS provider — Cloudflare (1.1.1.1) or Google (8.8.8.8) work well as defaults. You can change this later in Settings → DNS without reinstalling.
- Default blocklists — leave the StevenBlack combined list checked. It covers the most common ad and tracking domains with few false positives out of the box.
- Admin web interface — install it. Diagnosing blocked sites without the dashboard is significantly harder.
- Query logging — enable it. Without query logs you cannot determine whether a broken site is being blocked by Pi-hole or has an unrelated DNS problem.
When the installer finishes, it prints your admin URL and a randomly generated admin password. Copy that password now. If you lose it, connect to the Pi and run pihole setpassword to set a new one.
Step 4: Open the Admin Dashboard and Confirm It Works
Open a browser and navigate to http://192.168.1.10/admin (use your Pi's static IP). Log in with the password from the installer. The summary page shows total queries, blocked percentage, and the size of your gravity blocklist. A fresh install with the default StevenBlack list typically shows around 150,000–200,000 blocked domains.
Before continuing, go to Settings → DNS and confirm the upstream resolvers are correct. This is also where you will enable DNSSEC and IPv6 listening in later steps.
Step 5: Point Your Router's DNS at Pi-hole
Log into your router and change the primary DNS server in the DHCP server settings — not the WAN or internet DNS settings, which affect the router's own lookups, not client devices — to your Pi's static IP. Menu paths vary by brand and firmware version:
- Asus (asusrouter.com or 192.168.1.1): LAN → DHCP Server → DNS Server 1
- TP-Link (tplinkwifi.net or 192.168.0.1): Advanced → Network → DHCP Server → Primary DNS
- Netgear Orbi (orbilogin.com): Advanced → Setup → Internet Setup → Domain Name Server
- Linksys (linksyssmartwifi.com): Connectivity → Local Network → DHCP settings
- D-Link (192.168.0.1): Setup → Network Settings → Primary DNS Server
- OpenWrt: Network → Interfaces → LAN → DHCP Server → Advanced Settings → add DHCP option
6,192.168.1.10 - DD-WRT: Setup → Basic Setup → Network Address Server Settings → Local DNS
For secondary DNS: leaving it blank means all DNS stops if Pi-hole goes offline, which you notice immediately and have a clear signal to fix. Setting a public resolver (1.1.1.1) as secondary gives silent fallback but some DHCP clients will use whichever server responds fastest, bypassing Pi-hole intermittently. For a home network with reliable hardware, leaving secondary DNS blank is cleaner.
After saving router settings, force client devices to renew their DHCP leases. Windows: ipconfig /release && ipconfig /renew. macOS: toggle Wi-Fi off and on. Linux: sudo dhclient -r && sudo dhclient. Mobile: toggle airplane mode.
Step 6: Verify with CLI Tools
From a device that has renewed its lease, confirm Pi-hole is answering queries:
A valid response shows an A record in the ANSWER section and a query time under 30 ms on a local network. Now test that blocking is active:
A blocked domain returns 0.0.0.0 for IPv4 (and :: for IPv6). If it returns a real IP address, that domain is not in your blocklist. On Windows, use nslookup:
On modern Linux with systemd-resolved:
Cross-check using the DNS Lookup tool — if a domain resolves correctly from external vantage points but returns 0.0.0.0 from your Pi-hole, the block is working as intended. Check the Pi-hole Query Log to see which blocklist entry matched.
IPv6: The Step Most Guides Skip in 2026
If your ISP provides IPv6 (most residential connections do in 2026) and your router advertises an IPv6 DNS server that is not your Pi-hole, every device with IPv6 support bypasses Pi-hole entirely for those lookups. Ad networks and trackers with AAAA records load as if nothing is blocked. This is the most common reason Pi-hole appears to stop working on modern dual-stack networks.
Find the Pi's current IPv6 address:
In Pi-hole Settings → DNS, enable listening on that IPv6 address. Then set your router's IPv6 DNS server (in the IPv6 or RA settings) to that same address. If your router does not allow a custom IPv6 DNS server, the practical workaround is to disable IPv6 DNS advertisement in Router Advertisements entirely and rely on IPv4 DNS only.
For a stable IPv6 address that does not rotate when your ISP changes its delegation prefix, assign a ULA address (fd00::/8 range) to the Pi:
Encrypting Upstream DNS Queries
By default Pi-hole forwards queries to its upstream resolver over plain UDP port 53, which your ISP can observe and log. Two practical options to encrypt that traffic in 2026:
Option 1 — Unbound (recursive, no third-party resolver): Unbound queries root servers directly using DNSSEC-validated responses, meaning no upstream provider sees your query history. Install it with sudo apt install unbound -y, configure it to listen on 127.0.0.1 port 5335, then set Pi-hole's upstream DNS to 127.0.0.1#5335. The official Pi-hole documentation has a tested Unbound config block for this exact setup — use it rather than a third-party guide, as the required options change between Unbound releases.
Option 2 — cloudflared (DNS-over-HTTPS proxy): Install the ARM64 build of cloudflared from Cloudflare's GitHub releases page, configure it as a local DoH proxy listening on port 5053, then set Pi-hole's upstream DNS to 127.0.0.1#5053. DoH wraps queries in HTTPS, making them indistinguishable from normal web traffic to your ISP. The trade-off is Cloudflare becomes your resolver rather than a neutral recursive resolver.
DNSSEC Validation
Pi-hole can validate DNSSEC signatures for all clients on the network simultaneously. Enable it under Settings → DNS → Advanced DNS settings → Use DNSSEC. Your upstream resolver must also support DNSSEC validation — Cloudflare, Google, Quad9, and a correctly configured Unbound instance all do. Verify it is active:
Look for the ad (Authenticated Data) flag in the flags line of the response. Its presence confirms DNSSEC validation is working end-to-end from client through Pi-hole to the upstream resolver.
Common Misdiagnoses
Pi-hole is running but nothing is blocked
Devices still hold a DHCP lease that points them at the old DNS server. Check which DNS server a device is actually using: Windows — ipconfig /all, look at the DNS Servers line. macOS — System Settings → Network → interface → Details → DNS tab. Linux — resolvectl status. Force a DHCP renewal on the device and retest.
Specific sites stop working after adding blocklists
A blocklist entry is too broad and has caught a legitimate domain. In the admin dashboard open Query Log, filter for the domain of the broken site, and look for entries with a blocked status. The matching blocklist and the specific entry that triggered the block appear in the detail view. Whitelist the domain from the admin UI or via CLI: pihole -w example.com. Always check Query Log before assuming the problem is network-layer.
Android devices bypass Pi-hole
Android 9 and later includes a Private DNS setting (DNS-over-TLS) that defaults to Automatic mode. In this mode Android may query a DoT server directly, completely bypassing the DHCP-advertised DNS. Go to Settings → Network & Internet → Private DNS and set it to Off, or configure it to point at a DoT endpoint you control (requires Unbound with TLS termination).
iOS devices partially bypass Pi-hole
Apple devices with iCloud Private Relay enabled (iOS 15+, iCloud+ subscribers) route DNS queries through Apple's relay infrastructure regardless of local DNS settings. To force DNS through Pi-hole on those devices, disable iCloud Private Relay under Settings → Privacy & Security → iCloud → Private Relay, or block the relay hostnames network-wide via a custom Pi-hole blocklist entry. This is the single biggest DNS bypass factor introduced in 2024–2026 for Apple households.
New blocklists added but blocking has not changed
After adding blocklist URLs in the admin dashboard, Pi-hole does not apply them until you run a gravity update:
Without this step, lists are saved but not compiled into the active blocklist database. Schedule a weekly update with cron: sudo crontab -e, add 0 3 * * 0 pihole -g for every Sunday at 3 AM.
Admin interface unreachable after install
In Pi-hole v6, the built-in web server in pihole-FTL replaces the lighttpd dependency. If the admin panel is unreachable, check the FTL service:
View recent logs with journalctl -u pihole-FTL -n 50 to identify the cause. Port conflicts on 80 or 53 from another service running on the Pi are the most common reason.
Keeping Pi-hole Reliable Long-Term
- Update Pi-hole monthly:
pihole -upupdates both Pi-hole and the web interface. Watch Pi-hole's GitHub releases page for security notices between major versions. - Schedule gravity updates weekly: The cron entry above handles this automatically once set.
- Back up your config: In the admin dashboard, go to Settings → System → Teleporter to export a backup zip of all your lists, settings, whitelist, and blacklist entries. Store it off the Pi.
- Enable conditional forwarding: In Settings → DNS, enable Use Conditional Forwarding and enter your router's IP. This lets Pi-hole resolve local hostnames (printers, NAS devices, local servers) by querying the router's DHCP server, rather than returning NXDOMAIN for anything not in public DNS.
- Monitor port 53: A simple TCP monitor set to alert when port 53 on the Pi is unreachable means you know before your household notices network-wide DNS failure.