15 KiB
Pi-hole - Network-Wide Ad Blocker
Table of Contents
- Overview
- What is Pi-hole?
- Why Use Pi-hole?
- How It Works
- Configuration in AI-Homelab
- Official Resources
- Educational Resources
- Docker Configuration
- Setup and Management
- Advanced Topics
- Troubleshooting
Overview
Category: Infrastructure / Network
Docker Image: pihole/pihole
Default Stack: infrastructure.yml
Web UI: https://pihole.${DOMAIN}/admin or http://SERVER_IP:8181/admin
Authentication: Admin password set via environment variable
DNS Port: 53 (TCP/UDP)
What is Pi-hole?
Pi-hole is a network-level advertisement and internet tracker blocking application that acts as a DNS sinkhole. Originally designed for Raspberry Pi, it now runs on any Linux system including Docker. It blocks ads for all devices on your network without requiring per-device configuration.
Key Features
- Network-Wide Blocking: Blocks ads on all devices (phones, tablets, smart TVs)
- DNS Level Blocking: Intercepts DNS queries before ads load
- No Client Software: Works for all devices automatically
- Extensive Blocklists: Millions of known ad/tracking domains blocked
- Web Interface: Beautiful dashboard with statistics
- Whitelist/Blacklist: Custom domain control
- DHCP Server: Optional network DHCP service
- DNS Over HTTPS: Encrypted DNS queries (DoH)
- Query Logging: See all DNS queries on network
- Group Management: Different blocking rules for different devices
- Regex Filtering: Advanced domain pattern blocking
Why Use Pi-hole?
- Block Ads Everywhere: Mobile apps, smart TVs, IoT devices
- Faster Browsing: Pages load faster without ads
- Privacy Protection: Block trackers and analytics
- Save Bandwidth: Don't download ad content
- Malware Protection: Block known malicious domains
- Family Safety: Block inappropriate content
- Network Visibility: See what devices are connecting where
- Free: No subscription fees
- Customizable: Full control over blocking
How It Works
Device (Phone/Computer/TV)
↓
DNS Query: "ads.example.com"
↓
Router/DHCP → Pi-hole (DNS Server)
↓
Is domain in blocklist?
├─ YES → Return 0.0.0.0 (blocked)
└─ NO → Forward to upstream DNS → Return real IP
Blocking Process
- Device makes request: "I want to visit ads.google.com"
- DNS query sent: Device asks "What's the IP for ads.google.com?"
- Pi-hole receives query: Checks against blocklists
- If blocked: Returns 0.0.0.0 (null IP) - ad doesn't load
- If allowed: Forwards to real DNS (1.1.1.1, 8.8.8.8, etc.)
- Result cached: Faster subsequent queries
Network Setup
Before Pi-hole:
Device → Router DNS → ISP DNS → Internet
After Pi-hole:
Device → Router (points to Pi-hole) → Pi-hole → Upstream DNS → Internet
↓
(blocks ads)
Configuration in AI-Homelab
Directory Structure
/opt/stacks/infrastructure/pihole/
├── etc-pihole/ # Pi-hole configuration
│ ├── gravity.db # Blocklist database
│ ├── custom.list # Local DNS records
│ └── pihole-FTL.db # Query log database
└── etc-dnsmasq.d/ # DNS server config
└── custom.conf # Custom DNS rules
Environment Variables
# Web Interface Password
WEBPASSWORD=your-secure-password-here
# Timezone
TZ=America/New_York
# Upstream DNS Servers
PIHOLE_DNS_=1.1.1.1;8.8.8.8 # Cloudflare and Google
# PIHOLE_DNS_=9.9.9.9;149.112.112.112 # Quad9 (privacy-focused)
# Web Interface Settings
WEBTHEME=default-dark # or default-light
VIRTUAL_HOST=pihole.yourdomain.com
WEB_PORT=80
# Optional: DHCP Server
DHCP_ACTIVE=false # Set true if using Pi-hole as DHCP
DHCP_START=192.168.1.100
DHCP_END=192.168.1.200
DHCP_ROUTER=192.168.1.1
Official Resources
- Website: https://pi-hole.net
- Documentation: https://docs.pi-hole.net
- GitHub: https://github.com/pi-hole/pi-hole
- Docker Hub: https://hub.docker.com/r/pihole/pihole
- Discourse Forum: https://discourse.pi-hole.net
- Reddit: https://reddit.com/r/pihole
- Blocklists: https://firebog.net
Educational Resources
Videos
- Pi-hole - Network-Wide Ad Blocking (NetworkChuck)
- Ultimate Pi-hole Setup Guide (Techno Tim)
- How DNS Works (Explained)
- Pi-hole Docker Setup (DB Tech)
Articles & Guides
Concepts to Learn
- DNS (Domain Name System): Translates domains to IP addresses
- DNS Sinkhole: Returns null IP for blocked domains
- Upstream DNS: Real DNS servers Pi-hole forwards to
- Blocklists: Lists of known ad/tracker domains
- Regex Filtering: Pattern-based domain blocking
- DHCP: Network device IP assignment
- DNS Over HTTPS (DoH): Encrypted DNS queries
- Local DNS: Custom local domain resolution
Docker Configuration
Complete Service Definition
pihole:
image: pihole/pihole:latest
container_name: pihole
restart: unless-stopped
hostname: pihole
networks:
- traefik-network
ports:
- "53:53/tcp" # DNS TCP
- "53:53/udp" # DNS UDP
- "8181:80/tcp" # Web Interface (remapped to avoid conflict)
# - "67:67/udp" # DHCP (optional, uncomment if using)
volumes:
- /opt/stacks/infrastructure/pihole/etc-pihole:/etc/pihole
- /opt/stacks/infrastructure/pihole/etc-dnsmasq.d:/etc/dnsmasq.d
environment:
- TZ=America/New_York
- WEBPASSWORD=${PIHOLE_PASSWORD}
- PIHOLE_DNS_=1.1.1.1;8.8.8.8
- WEBTHEME=default-dark
- VIRTUAL_HOST=pihole.${DOMAIN}
- DNSMASQ_LISTENING=all
cap_add:
- NET_ADMIN # Required for DHCP functionality
labels:
- "traefik.enable=true"
- "traefik.http.routers.pihole.rule=Host(`pihole.${DOMAIN}`)"
- "traefik.http.routers.pihole.entrypoints=websecure"
- "traefik.http.routers.pihole.tls.certresolver=letsencrypt"
- "traefik.http.services.pihole.loadbalancer.server.port=80"
Important Notes
- Port 53: DNS must be on port 53 (cannot be remapped)
- Web Port: Can use 8181 externally, 80 internally
- NET_ADMIN: Required capability for DHCP and network features
- Password: Set strong password via WEBPASSWORD variable
Setup and Management
Initial Setup
- Deploy Pi-hole: Start the container
- Wait 60 seconds: Let gravity database build
- Access Web UI:
https://pihole.yourdomain.com/admin - Login: Use password from WEBPASSWORD
- Configure Router: Point DNS to Pi-hole server IP
Router Configuration
Method 1: DHCP DNS Settings (Recommended)
- Access router admin panel
- Find DHCP settings
- Set Primary DNS: Pi-hole server IP (e.g., 192.168.1.10)
- Set Secondary DNS: 1.1.1.1 or 8.8.8.8 (fallback)
- Save and reboot router
Method 2: Per-Device Configuration
- Set DNS manually on each device
- Not recommended for whole-network blocking
Dashboard Overview
Main Dashboard Shows:
- Total queries (last 24h)
- Queries blocked (percentage)
- Blocklist domains count
- Top allowed/blocked domains
- Query types (A, AAAA, PTR, etc.)
- Client activity
- Real-time query log
Managing Blocklists
Add Blocklists:
- Group Management → Adlists
- Add list URL
- Update Gravity (Tools → Update Gravity)
Popular Blocklists (Firebog):
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://v.firebog.net/hosts/AdguardDNS.txt
https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt
https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt
Update Gravity:
# Via CLI
docker exec pihole pihole -g
# Or Web UI: Tools → Update Gravity
Whitelist/Blacklist
Whitelist Domain (Allow):
- Whitelist → Add domain
- Example:
example.com - Supports wildcards:
*.example.com
Blacklist Domain (Block):
- Blacklist → Add domain
- Example:
ads.example.com
Via CLI:
# Whitelist
docker exec pihole pihole -w example.com
# Blacklist
docker exec pihole pihole -b ads.example.com
# Regex whitelist
docker exec pihole pihole --regex-whitelist "^example\.com$"
# Regex blacklist
docker exec pihole pihole --regex "^ad[sx]?[0-9]*\..*"
Query Log
View Queries:
- Query Log → See all DNS requests
- Filter by client, domain, type
- Whitelist/Blacklist directly from log
Privacy Modes:
- Show Everything
- Hide Domains
- Hide Domains and Clients
- Anonymous Mode
Advanced Topics
Local DNS Records
Create custom local DNS entries:
Via Web UI:
- Local DNS → DNS Records
- Add domain → IP mapping
- Example:
nas.local → 192.168.1.50
Via File:
# /opt/stacks/infrastructure/pihole/etc-pihole/custom.list
192.168.1.50 nas.local
192.168.1.51 server.local
Group Management
Different blocking rules for different devices:
-
Create Groups:
- Group Management → Groups → Add Group
- Example: "Kids Devices", "Guest Network"
-
Assign Clients:
- Group Management → Clients → Add client to group
-
Configure Adlists per Group:
- Group Management → Adlists → Assign to groups
Regex Filtering
Advanced pattern-based blocking:
Common Patterns:
# Block all subdomains of ads.example.com
^ad[sx]?[0-9]*\.example\.com$
# Block tracking parameters
.*\?utm_.*
# Block all Facebook tracking
^(.+[_.-])?facebook\.[a-z]+$
Add Regex:
- Domains → Regex Filter
- Add regex pattern
- Test with Query Log
DNS Over HTTPS (DoH)
Encrypt DNS queries to upstream servers:
Using Cloudflared:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
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
pihole:
environment:
- PIHOLE_DNS_=cloudflared#5053 # Use cloudflared as upstream
Conditional Forwarding
Forward specific domains to specific DNS:
Example: Local domain to local DNS
# /opt/stacks/infrastructure/pihole/etc-dnsmasq.d/02-custom.conf
server=/local/192.168.1.1
DHCP Server
Use Pi-hole as network DHCP server:
environment:
- DHCP_ACTIVE=true
- DHCP_START=192.168.1.100
- DHCP_END=192.168.1.200
- DHCP_ROUTER=192.168.1.1
- DHCP_LEASETIME=24
- PIHOLE_DOMAIN=lan
ports:
- "67:67/udp" # DHCP port
Steps:
- Disable DHCP on router
- Enable DHCP in Pi-hole
- Restart network devices
Troubleshooting
Pi-hole Not Blocking Ads
# Check if Pi-hole is receiving queries
docker logs pihole | grep query
# Verify DNS is set correctly on device
# Windows: ipconfig /all
# Linux/Mac: cat /etc/resolv.conf
# Should show Pi-hole IP
# Test DNS resolution
nslookup ads.google.com PIHOLE_IP
# Should return 0.0.0.0 if blocked
# Check gravity database
docker exec pihole pihole -g
DNS Not Resolving
# Check if Pi-hole is running
docker ps | grep pihole
# Check DNS ports
sudo netstat -tulpn | grep :53
# Test DNS
dig @PIHOLE_IP google.com
# Check upstream DNS
docker exec pihole pihole -q
Web Interface Not Accessible
# Check container logs
docker logs pihole
# Verify port mapping
docker port pihole
# Access via IP
http://SERVER_IP:8181/admin
# Check Traefik routing
docker logs traefik | grep pihole
High CPU/Memory Usage
# Check container stats
docker stats pihole
# Database optimization
docker exec pihole pihole -q database optimize
# Reduce query logging
# Settings → Privacy → Anonymous mode
# Clear old queries
docker exec pihole sqlite3 /etc/pihole/pihole-FTL.db "DELETE FROM queries WHERE timestamp < strftime('%s', 'now', '-7 days')"
False Positives (Sites Broken)
# Check query log for blocked domains
# Web UI → Query Log → Find blocked domain
# Whitelist domain
docker exec pihole pihole -w problematic-domain.com
# Or via Web UI:
# Whitelist → Add domain
# Common false positives:
# - microsoft.com CDNs
# - google-analytics.com (breaks some sites)
# - doubleclick.net (ad network but some sites need it)
Blocklist Update Issues
# Manually update gravity
docker exec pihole pihole -g
# Check disk space
df -h
# Clear cache
docker exec pihole pihole -r
# Choose: Repair
Security Best Practices
- Strong Password: Use complex WEBPASSWORD
- Authelia Protection: Add Authelia middleware for external access
- Firewall Rules: Only expose port 53 as needed
- Update Regularly: Keep Pi-hole container updated
- Backup Config: Regular backups of
/etc/piholedirectory - Query Privacy: Enable privacy mode for sensitive networks
- Upstream DNS: Use privacy-focused DNS (Quad9, Cloudflare)
- Monitor Logs: Watch for unusual query patterns
- Network Segmentation: Separate IoT devices
- HTTPS Only: Use HTTPS for web interface access
Performance Optimization
environment:
# Increase cache size
- CACHE_SIZE=10000
# Disable query logging (improves performance)
- QUERY_LOGGING=false
# Optimize DNS settings
- DNSSEC=false # Disable if not needed
Database Maintenance:
# Optimize database weekly
docker exec pihole sqlite3 /etc/pihole/pihole-FTL.db "VACUUM"
# Clear old queries (keep 7 days)
docker exec pihole pihole -f
Backup and Restore
Backup
Via Web UI:
- Settings → Teleporter
- Click "Backup"
- Download tar.gz file
Via CLI:
# Backup entire config
tar -czf pihole-backup-$(date +%Y%m%d).tar.gz /opt/stacks/infrastructure/pihole/
# Backup only settings
docker exec pihole pihole -a -t
Restore
Via Web UI:
- Settings → Teleporter
- Choose file
- Click "Restore"
Via CLI:
# Restore from backup
tar -xzf pihole-backup-20240112.tar.gz -C /opt/stacks/infrastructure/pihole/
docker restart pihole
Summary
Pi-hole provides network-wide ad blocking by acting as a DNS server that filters requests before they reach the internet. It:
- Blocks ads on all devices automatically
- Improves browsing speed and privacy
- Provides visibility into network DNS queries
- Offers extensive customization
- Protects against malware and tracking
Setup Priority:
- Deploy Pi-hole container
- Set strong admin password
- Configure router DNS settings
- Add blocklists (Firebog)
- Monitor dashboard
- Whitelist as needed
- Configure DoH for privacy
- Regular backups
Remember:
- DNS is critical - test thoroughly before deploying
- Keep secondary DNS as fallback
- Some sites may break - use whitelist
- Monitor query log initially
- Update gravity weekly
- Backup before major changes