Reading time: ~12 minutes Audience: Homelabbers wanting network-wide ad and tracker blocking
What Is Pi-hole?
Overview
Pi-hole is a DNS sinkhole that blocks ads, trackers, and malicious domains at the network level. By acting as your LAN’s DNS server, it intercepts queries to known ad domains and returns 0.0.0.0 — blocking ads on every device without installing browser extensions or apps.
Key Benefits
| Benefit | Detail |
|---|---|
| Network-wide | One setup covers phones, TVs, IoT, and guests |
| Device-agnostic | Works on devices that can’t run ad blockers (smart TVs, consoles) |
| Low resource | Runs on a Raspberry Pi or in a Docker container |
| Privacy | Blocks trackers from Google, Facebook, Amazon, and analytics |
| Malware blocking | Filter lists include known malicious domains |
| Custom filtering | Add your own blacklists and whitelists |
| Statistics | See exactly which domains are queried and blocked |
Pi-hole v6 (2025) changes: - Built-in web server (no Lighttpd dependency) - FTL v6 DNS engine (replaces dnsmasq) - TOML configuration format - Improved REST API
Prerequisites
Hardware Requirements
- Any device running Docker (mini PC, Raspberry Pi, NAS, or VM)
- 512MB RAM minimum (1GB recommended)
- 2GB storage for logs and databases
Software Requirements
- Docker Engine 24.x+ and Docker Compose v2+
- Linux host (Debian 12, Ubuntu 22.04/24.04, or Proxmox LXC)
- Router access to change DNS settings
Knowledge Prerequisites
- Basic Docker and Linux commands
- Router admin panel access
- Understanding of DNS basics
Step 1: Create the Docker Compose File
Objective
Set up a reproducible Pi-hole deployment with persistent storage and proper network configuration.
Step-by-Step Instructions
- Create a directory for Pi-hole:
mkdir -p ~/docker/pihole && cd ~/docker/pihole
- Create
docker-compose.yml:
services:
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "8080:80/tcp"
environment:
- TZ=Asia/Singapore
- WEBPASSWORD=ChangeMeStrong123!
- FTLCONF_LOCAL_IPV4=192.168.1.10
- PIHOLE_DNS_=1.1.1.1;1.0.0.1
- FTLCONF_BLOCK_ICLOUD_PR=false
volumes:
- ./etc-pihole:/etc/pihole
- ./etc-dnsmasq.d:/etc/dnsmasq.d
cap_add:
- NET_ADMIN
restart: unless-stopped
networks:
- pihole-net
networks:
pihole-net:
driver: bridge
- Create data directories:
mkdir -p etc-pihole etc-dnsmasq.d
- Deploy:
docker compose up -d
- Verify it’s running:
docker logs pihole | grep -i "finished"
Step 2: Configure Your Router to Use Pi-hole
Objective
Point all devices on your network to Pi-hole for DNS resolution.
Step-by-Step Instructions
Option A: Router DHCP DNS (Recommended)
1. Log into your router admin panel (usually 192.168.1.1 or 192.168.0.1)
2. Find DHCP Server or LAN Settings
3. Set Primary DNS to your Pi-hole IP (e.g., 192.168.1.10)
4. Set Secondary DNS to a backup (e.g., 1.1.1.1) or leave blank
5. Save and reboot the router
Option B: Pi-hole as DHCP Server
If your router doesn’t allow custom DNS, disable its DHCP and let Pi-hole handle it:
1. In Pi-hole admin (Settings → DHCP), enable DHCP server
2. Set range: 192.168.1.100 to 192.168.1.200
3. Set router (gateway) to 192.168.1.1
4. Disable DHCP on your router
5. Renew leases on all devices (reconnect Wi-Fi or reboot)
Option C: Manual Per-Device On each device, set DNS to Pi-hole’s IP. Good for testing before network-wide rollout.
Step 3: Add Blocklists and Whitelists
Objective
Tune blocking to balance ad blocking with website functionality.
Step-by-Step Instructions
- Log into Pi-hole admin at
http://192.168.1.10:8080/admin - Default blocklists (enabled automatically):
- StevenBlack’s unified hosts list
-
AdAway default blocklist
-
Add recommended blocklists (Group Management → Adlists):
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://adaway.org/hosts.txt
https://someonewhocares.org/hosts/zero/hosts
https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt
https://raw.githubusercontent.com/ShadowWhisperer/BlockLists/master/Lists/Tracking
- Update gravity:
docker exec pihole pihole -g
- Common whitelist entries (to avoid breaking sites):
clients4.google.com(Google Play/Android)app-api.twitch.tv(Twitch login)www.msftncsi.com(Windows connectivity check)
Step 4: Enable DNS-over-HTTPS (Optional but Recommended)
Objective
Encrypt DNS queries from Pi-hole to upstream resolvers for privacy.
Step-by-Step Instructions
Use Cloudflare’s cloudflared container as the upstream:
services:
cloudflared:
container_name: cloudflared
image: cloudflare/cloudflared:latest
command: proxy-dns
environment:
- TUNNEL_DNS_UPSTREAM=https://1.1.1.1/dns-query,https://1.0.0.1/dns-query
- TUNNEL_DNS_PORT=5053
- TUNNEL_DNS_ADDRESS=0.0.0.0
restart: unless-stopped
networks:
- pihole-net
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "8080:80/tcp"
environment:
- TZ=Asia/Singapore
- WEBPASSWORD=ChangeMeStrong123!
- PIHOLE_DNS_=cloudflared#5053
volumes:
- ./etc-pihole:/etc/pihole
- ./etc-dnsmasq.d:/etc/dnsmasq.d
cap_add:
- NET_ADMIN
restart: unless-stopped
networks:
- pihole-net
depends_on:
- cloudflared
networks:
pihole-net:
driver: bridge
Pro Tips
Tip 1: Use a MAC Address Reservation
Assign Pi-hole a static IP in your router’s DHCP reservations. If the IP changes, your entire network loses DNS.
Tip 2: Keep a Backup DNS
Set a secondary DNS (e.g., 1.1.1.1) on your router. If Pi-hole goes down, devices can still resolve. The trade-off is that some ads slip through during the outage.
Tip 3: Schedule Gravity Updates
# Add to crontab (docker host)
0 3 * * 0 cd ~/docker/pihole && docker exec pihole pihole -g
Tip 4: Monitor Block Percentage
A healthy Pi-hole blocks 10–30% of queries. If it’s under 5%, your blocklists are too conservative. If it’s over 50%, you’re probably breaking websites.
Troubleshooting Common Issues
Problem 1: “DNS Resolution Not Working”
Cause: Router not pointing to Pi-hole, or Pi-hole container not running.
Fix:
# Check if Pi-hole is running
docker ps | grep pihole
# Test DNS directly
nslookup google.com 192.168.1.10
# Check Pi-hole logs
docker logs pihole
Problem 2: “Some Websites Won’t Load”
Cause: Overly aggressive blocklist.
Fix:
1. Check Pi-hole Query Log for blocked domains
2. Whitelist the domain blocking the site
3. Use the pihole -t command to tail logs in real time
Problem 3: “Container Won’t Start — Port 53 in Use”
Cause: systemd-resolved or another DNS service is using port 53.
Fix:
# On Debian/Ubuntu, disable systemd-resolved
systemctl stop systemd-resolved
systemctl disable systemd-resolved
rm /etc/resolv.conf
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
Conclusion
Summary
Pi-hole in Docker Compose is the easiest way to deploy network-wide ad blocking. With a single docker-compose.yml file, you can block ads on every device in your home, improve privacy, and reduce bandwidth usage.
Next Steps
- Add Unbound for recursive DNS without third-party resolvers
- Set up AdGuard Home as a backup DNS
- Monitor your network with Grafana and Prometheus
Affiliate Opportunities
- Raspberry Pi 5: Alternative hardware for Pi-hole
- Beelink Mini S12 Pro: Mini PC for running Pi-hole + other services
- TP-Link Omada router: Router with good DNS/DHCP control
Internal Linking Strategy
intro→pihole-vs-adguard-homefor DNS blocker comparisonstep-4→pihole-unbound-dnsfor recursive DNS setupconclusion→docker-compose-for-beginnersfor Docker basics
CTA
- [comment] What’s your Pi-hole block percentage? Share your stats and favorite blocklists!
- [newsletter] Subscribe for weekly homelab Docker tutorials and privacy guides.