Pi-hole is a DNS sinkhole that blocks advertisements and tracking domains at the network level before they ever reach your devices. Instead of installing a browser extension on every device, Pi-hole runs on a single server — a Raspberry Pi, a Linux VM, or a Docker container — and intercepts DNS queries for known ad domains, returning an empty response. Every phone, tablet, smart TV, gaming console, and IoT device on your network benefits automatically. This guide covers installation, router configuration, blocklist management, local DNS, and performance tuning for Pi-hole in a home or small office environment.

Prerequisites

  • A Raspberry Pi (any model 2+), a spare Linux machine, or an existing Linux server/VM
  • Ubuntu 22.04/24.04, Debian 11/12, or Raspberry Pi OS (64-bit recommended)
  • Static IP address assigned to the Pi-hole host (via router DHCP reservation or manual configuration)
  • Router admin access to change DNS settings
  • Basic familiarity with the Linux command line
  • curl installed (sudo apt install curl)

Installing Pi-hole

The fastest way to install Pi-hole on a bare-metal Linux host is the official one-line installer:

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

The interactive wizard asks you to confirm your network interface, select an upstream DNS provider (Cloudflare 1.1.1.1, Google 8.8.8.8, or others), choose whether to install the web admin interface, and set an admin password. Accept the defaults for most options.

After installation, note your Pi-hole’s IP address. The installer prints it at the end:

Pi-hole installation complete!
  Admin console: http://192.168.1.50/admin

Installing Pi-hole with Docker

If you prefer containers, use the official pihole/pihole image with Docker Compose:

# docker-compose.yml
services:
  pihole:
    image: pihole/pihole:latest
    container_name: pihole
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80/tcp"
    environment:
      TZ: "America/New_York"
      WEBPASSWORD: "your_secure_password"
    volumes:
      - ./etc-pihole:/etc/pihole
      - ./etc-dnsmasq.d:/etc/dnsmasq.d
    restart: unless-stopped
docker compose up -d

The Docker approach makes updates easy (docker compose pull && docker compose up -d) and keeps Pi-hole isolated from your host OS. One caveat: port 53 conflicts if the host runs systemd-resolved. Disable it first:

sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf

Configuring Your Router to Use Pi-hole

Pi-hole is useless unless your devices actually send DNS queries to it. The cleanest way is to configure your router’s DHCP server to advertise Pi-hole’s IP as the DNS server for the entire network.

  1. Log into your router admin panel (typically 192.168.1.1 or 192.168.0.1).
  2. Find DHCP Settings or LAN Settings.
  3. Set Primary DNS to your Pi-hole’s static IP (e.g., 192.168.1.50).
  4. Optionally set Secondary DNS to 1.1.1.1 as a fallback (devices will bypass Pi-hole if it’s unreachable — leave blank if you want strict blocking).
  5. Save and restart the DHCP service (connected devices will pick up the new DNS on their next lease renewal; force it by reconnecting).

Verify blocking works from any device:

nslookup doubleclick.net 192.168.1.50
# Should return 0.0.0.0 (blocked)

Managing Blocklists with Gravity

Pi-hole’s blocklist database is called gravity. The default installation includes the StevenBlack hosts list (~180,000 domains). Extending it significantly improves blocking coverage.

Adding Blocklists via the Admin Dashboard

  1. Open http://YOUR_PIHOLE_IP/admin and log in.
  2. Go to Adlists (under the Group Management section).
  3. Paste blocklist URLs and click Add. Recommended lists from firebog.net:
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts.txt
https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Spam/hosts
https://v.firebog.net/hosts/Easylist.txt
https://v.firebog.net/hosts/Easyprivacy.txt
https://v.firebog.net/hosts/AdguardDNS.txt
  1. After adding lists, update gravity to download and compile them:
pihole -g

A typical setup with 5-6 lists blocks 500,000–1,000,000 domains. Avoid adding too many overlapping lists — diminishing returns kick in quickly above 1.5 million entries.

Scheduling Automatic Updates

Add a weekly cron job to keep gravity fresh:

sudo crontab -e
# Add this line:
0 3 * * 0 pihole -g > /var/log/pihole_gravity.log 2>&1

Pi-hole vs. Alternatives Comparison

FeaturePi-holeAdGuard HomeNextDNSBrowser Extension
Network-wide coverageYesYesYesNo (browser only)
Self-hostedYesYesNo (cloud)N/A
IoT/TV blockingYesYesYesNo
Setup complexityMediumMediumLowVery low
Custom local DNSYesYesLimitedNo
DNSSEC supportYesYesYesNo
Regex blockingNoYesLimitedDepends
CostFreeFreeFree/paidFree/paid

AdGuard Home is a worthy alternative with regex-based blocking and a slightly more modern UI. NextDNS is excellent if you want zero server maintenance. Pi-hole wins for self-hosted, full-control setups.

Real-World Scenario: Homelab with 30+ Devices

You manage a home network with smart TVs, phones, tablets, a few Linux servers, and IoT devices like smart bulbs and cameras. Before Pi-hole, your router’s DNS logs show constant traffic to googleadservices.com, doubleclick.net, and telemetry endpoints from your smart TV manufacturer.

After deploying Pi-hole on a Raspberry Pi 4 with a static IP of 192.168.1.50:

  • Your router’s DHCP advertises 192.168.1.50 as DNS.
  • Every device automatically starts using Pi-hole without any reconfiguration.
  • The dashboard shows 25-40% of all DNS queries are blocked — mostly ads and telemetry.
  • You add local DNS entries so nas.home resolves to your NAS’s IP, and plex.home points to your media server.
  • Your smart TV stops phoning home to analytics servers.

Pi-hole’s query log lets you audit exactly which domains each device is querying, which is invaluable for spotting unexpected network chatter from IoT devices.

Local DNS and CNAME Records

One of Pi-hole’s underrated features is acting as a local DNS resolver for homelab hostnames. Navigate to Local DNS in the admin panel:

  • DNS Records — map hostnames to IPs (e.g., nas.home → 192.168.1.100)
  • CNAME Records — create aliases (e.g., files.home → nas.home)

This lets you access services by name instead of IP address, which is especially useful when IP addresses change.

Gotchas and Edge Cases

Pi-hole goes down, internet stops working. This happens if you set Pi-hole as the only DNS and it crashes or the host reboots. Solutions: set up a secondary Pi-hole instance, or configure a fallback DNS in your router. For critical environments, run two Pi-hole instances.

HTTPS ads are not blocked. Pi-hole only handles DNS. It cannot inspect HTTPS traffic or block ads served from the same domain as content (like YouTube ads, which use youtube.com subdomains). For those, you still need a browser extension like uBlock Origin.

Clients ignoring your DNS settings. Some devices (Chromecast, Google Home) hardcode Google’s 8.8.8.8. You can intercept these with a firewall rule:

# Redirect all DNS traffic to Pi-hole (requires iptables on router/firewall)
iptables -t nat -A PREROUTING -i br0 -p udp --dport 53 ! -d 192.168.1.50 -j DNAT --to 192.168.1.50:53
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 53 ! -d 192.168.1.50 -j DNAT --to 192.168.1.50:53

Gravity update breaks after OS upgrade. After upgrading the host OS, run pihole -r (repair) to restore Pi-hole’s configuration files.

Docker container loses config on restart. Always mount /etc/pihole and /etc/dnsmasq.d as volumes — never rely on the container’s filesystem for persistent data.

Troubleshooting Common Issues

Ads still appearing after setup. Check: (1) Is the device actually using Pi-hole’s IP as DNS? Run nslookup google.com and look at the Server: line. (2) Did the device have a cached DNS response? Flush the device’s DNS cache. (3) Is the ad served from the same domain as content?

Pi-hole dashboard returns 404. The lighttpd web server may not be running. Restart it: sudo systemctl restart lighttpd.

Gravity update fails with certificate errors. Your host’s CA certificates may be outdated. Fix: sudo apt update && sudo apt install ca-certificates.

High query latency. Pi-hole adds ~1ms of latency. If you see much more, enable query caching (already enabled by default) and check that your upstream DNS provider is responsive. Switching to 127.0.0.1#5335 with unbound as a local recursive resolver eliminates reliance on third-party DNS entirely.

Checking Pi-hole status:

pihole status
pihole -c          # real-time stats
pihole tail        # live query log
pihole -q example.com  # test if domain is blocked

Summary

  • Pi-hole is a DNS sinkhole that blocks ads and trackers for every device on your network without installing software on individual devices
  • Install with the one-line installer on any Debian/Ubuntu Linux host, or deploy via Docker Compose
  • Assign a static IP to your Pi-hole host and configure your router’s DHCP to advertise it as DNS
  • Extend coverage by adding curated blocklists from firebog.net and running pihole -g to update gravity
  • Use Pi-hole’s local DNS feature to give homelab services memorable hostnames
  • Pi-hole cannot block HTTPS ads served from the same domain as content (YouTube); pair it with uBlock Origin in your browser for full coverage
  • For redundancy, run a second Pi-hole instance or configure a fallback DNS so internet access survives a Pi-hole outage