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:

nmcli con show

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:

sudo nmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.10/24 sudo nmcli con mod "Wired connection 1" ipv4.gateway 192.168.1.1 sudo nmcli con mod "Wired connection 1" ipv4.dns "1.1.1.1" sudo nmcli con mod "Wired connection 1" ipv4.method manual sudo nmcli con up "Wired connection 1"

Confirm the address applied:

ip addr show eth0

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.

Tip: Also create a DHCP reservation for the Pi's MAC address in your router admin panel. If the OS network config ever resets after a major OS upgrade, the router will still hand out the same address and your network DNS keeps working without manual intervention.

Step 2: Update the Operating System

sudo apt update && sudo apt full-upgrade -y && sudo reboot

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

curl -sSL https://install.pi-hole.net | bash

A blue ncurses dialog walks through the configuration choices. The ones that matter most:

  1. Network interface — select eth0 (or wlan0 if Wi-Fi is unavoidable).
  2. 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.
  3. 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.
  4. Admin web interface — install it. Diagnosing blocked sites without the dashboard is significantly harder.
  5. 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.

Tip: Use the DNS Propagation Checker to verify your Pi-hole's upstream resolver is reaching public DNS correctly — a quick lookup for a known domain tells you whether any upstream issues exist before you blame Pi-hole for a resolution failure.

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:

dig @192.168.1.10 google.com

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:

dig @192.168.1.10 doubleclick.net

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:

nslookup doubleclick.net 192.168.1.10

On modern Linux with systemd-resolved:

resolvectl query doubleclick.net

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:

ip -6 addr show eth0 | grep "scope global"

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:

sudo nmcli con mod "Wired connection 1" ipv6.addresses "fd00::10/64" sudo nmcli con mod "Wired connection 1" ipv6.method manual sudo nmcli con up "Wired connection 1"

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:

dig @192.168.1.10 sigok.verteiltesysteme.net +dnssec

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:

pihole -g

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:

pihole status sudo systemctl status pihole-FTL

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

  1. Update Pi-hole monthly: pihole -up updates both Pi-hole and the web interface. Watch Pi-hole's GitHub releases page for security notices between major versions.
  2. Schedule gravity updates weekly: The cron entry above handles this automatically once set.
  3. 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.
  4. 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.
  5. 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.