Pi-hole DNS Ad Blocking: Complete Setup Guide
Set up Pi-hole on Docker to block ads and tracking at the DNS level across your entire network — no browser extensions, no per-device setup.
Pi-hole is a DNS sinkhole. Instead of every device on your network reaching out to ad servers and trackers, they ask Pi-hole first. Pi-hole checks the domain against a blocklist and either returns the real IP or returns nothing. Ads and trackers get nothing. It works for every device on your network — phones, TVs, smart home devices, everything — without installing anything on each device.
I’ve been running it for years. The web dashboard shows you exactly what’s being blocked across your entire household. It’s one of those installs you forget about after setup because it just works.
What Pi-hole Does and Doesn’t Do
Pi-hole blocks at the DNS level. If you request ads.example.com and that domain is on a blocklist, Pi-hole intercepts it and returns nothing. The ad never loads.
What it doesn’t block: ads served from the same domain as the content (YouTube’s ad serving is the main example — it comes from googlevideo.com which also serves the actual videos, so you can’t block one without breaking the other). For those, you still need browser-level blocking.
For everything else — network-level tracking, smart TV data harvesting, IoT phone-home traffic — Pi-hole handles it.
Running Pi-hole on Docker
Create the directory:
mkdir -p /opt/pihole
Create /opt/pihole/docker-compose.yml:
services:
pihole:
image: pihole/pihole:latest
container_name: pihole
network_mode: host
environment:
TZ: "America/Chicago"
WEBPASSWORD: "changeme"
PIHOLE_DNS_: "1.1.1.1;1.0.0.1"
DNSMASQ_LISTENING: "all"
volumes:
- /opt/pihole/etc-pihole:/etc/pihole
- /opt/pihole/etc-dnsmasq.d:/etc/dnsmasq.d
restart: unless-stopped
cap_add:
- NET_ADMIN
network_mode: host — Pi-hole needs to listen on port 53 (DNS) on your actual host IP. Host networking is the cleanest way to accomplish this without complex port mapping.
TZ — Set your timezone. This affects the timestamps in your query log.
WEBPASSWORD — The password for the Pi-hole web admin. Change this to something real before starting.
PIHOLE_DNS_ — The upstream DNS servers Pi-hole uses for non-blocked domains. Cloudflare (1.1.1.1) and its backup (1.0.0.1) are what I use. You can use 8.8.8.8/8.8.4.4 for Google or 9.9.9.9 for Quad9.
cap_add: NET_ADMIN — Required for Pi-hole to manage its DHCP and DNS listener properly.
Start it:
cd /opt/pihole
docker compose up -d
Access the admin interface at http://YOUR_SERVER_IP/admin. Log in with the password you set in WEBPASSWORD.
Pointing Your Network at Pi-hole
Pi-hole only works if your devices actually use it for DNS. Two ways to do this:
Option 1: Router DHCP (recommended)
Log into your router and find the DHCP settings. Look for “DNS Server” or “Primary DNS.” Change it to your server’s IP address. Every device that gets an IP from your router via DHCP will automatically use Pi-hole for DNS. No per-device configuration needed.
The exact menu path varies by router manufacturer:
- Unifi: Networks > [network name] > DHCP > DNS Server
- TP-Link: Advanced > DHCP Server > Primary DNS
- ASUS: LAN > DHCP Server > DNS and WINS Server Settings
Set the secondary DNS to a real DNS server (like 1.1.1.1) as a fallback for when Pi-hole is down. This is a tradeoff — the fallback means Pi-hole goes down silently without ads coming back, but it bypasses ad blocking when Pi-hole isn’t running.
Option 2: Per-device
Set the DNS server on each device manually to your server IP. More work but useful if you only want Pi-hole on specific devices, or if your router doesn’t let you customize DHCP DNS.
On most devices:
- Windows: Network adapter settings > IPv4 properties > Preferred DNS
- macOS: System Settings > Network > [interface] > DNS
- iPhone/iPad: Settings > WiFi > [network] > Configure DNS
- Android: WiFi settings > Modify network > Advanced > IP settings: Static > DNS
Adding Blocklists
Pi-hole comes with a default blocklist that covers the basics. To add more lists, go to Adlists in the admin panel.
Some lists worth adding:
- StevenBlack Hosts — a curated unified list:
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts - OISD (full) — comprehensive, well-maintained, low false positives:
https://big.oisd.nl - HaGeZi Multi PRO — strong tracking and ad blocking:
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/pro.txt
After adding lists, go to Tools > Update Gravity to download them. The number of blocked domains jumps significantly after adding a few good lists.
Don’t add too many lists. More lists means more false positives (legitimate sites getting blocked) and slower gravity updates. Three or four good lists are better than fifteen mediocre ones.
Handling False Positives (Whitelisting)
Something breaks and you suspect Pi-hole. Check Query Log in the admin panel. Find the domain that’s being blocked (it shows in red with the blocklist that caught it). Click the domain and add it to the whitelist.
Common false positives:
- Microsoft Teams and Office 365 use domains that appear on some lists
- Smart TV features (weather, firmware updates) get caught occasionally
- Some banking apps use CDNs that land on tracking lists
The whitelist is per-domain — you’re allowing just that specific domain, not disabling blocking entirely.
Local DNS Records
One underused Pi-hole feature: Local DNS Records under Settings. You can assign domain names to local IPs, so instead of bookmarking 192.168.1.100:3001, you visit uptime.home.arpa or whatever you want to call it.
This is essentially a lightweight local DNS resolver for your homelab. It’s not as flexible as a full local DNS setup (see the Technitium DNS guide if you want more control), but for basic name-to-IP mapping it’s convenient.
Monitoring Your Blocked Queries
The dashboard shows:
- Total queries over the past 24 hours
- Percentage blocked
- Top blocked domains
- Top clients (which device is making the most queries)
I check mine occasionally out of curiosity. A smart TV that sends thousands of telemetry queries per day shows up clearly. That visibility alone is worth the install.
Backups
Back up /opt/pihole/etc-pihole. That directory contains your blocklists, whitelist, local DNS records, and settings. The etc-dnsmasq.d directory is worth backing up too if you’ve added custom dnsmasq config.
tar -czf /backup/pihole-$(date +%Y%m%d).tar.gz /opt/pihole/
Updating
cd /opt/pihole
docker compose pull
docker compose up -d
Pi-hole releases are infrequent but meaningful. The gravity database (blocklists) updates automatically on a weekly schedule by default — you can also update it manually from the admin panel under Tools > Update Gravity.