Pi-hole: Network-Wide Ad Blocking DNS Server
Transform your Raspberry Pi into a powerful network-wide ad blocker that protects every device on your network! Pi-hole acts as a DNS sinkhole, blocking ads, trackers, and malicious domains before they reach your devices—improving privacy, security, and browsing speed across your entire home network.
Introduction
Pi-hole is a network-level advertisement and internet tracker blocking application that acts as a DNS sinkhole. Unlike browser extensions that only protect individual browsers, Pi-hole protects every device on your network, including smartphones, smart TVs, IoT devices, and gaming consoles.
Benefits of Pi-hole
Deploying Pi-hole on your Raspberry Pi provides numerous advantages:
- Network-Wide Protection: Block ads on all devices automatically
- Improved Performance: Faster page loads by blocking resource-heavy ads
- Enhanced Privacy: Block tracking domains and telemetry
- Better Security: Protect against malicious domains and phishing
- Bandwidth Savings: Reduce data usage by blocking unwanted content
- Customizable: Full control over blocklists and whitelist
- Visibility: See exactly what domains your devices are accessing
- Low Resource Usage: Runs efficiently on even Raspberry Pi Zero
Prerequisites
Hardware Requirements
Recommended Raspberry Pi Models:
- Raspberry Pi 4 (2GB+ RAM): Best performance for large networks
- Raspberry Pi 3B+: Suitable for home networks
- Raspberry Pi Zero 2 W: Budget option for small networks
- Raspberry Pi 5: Excellent performance with PCIe expansion
Network Components:
- Ethernet Connection: Recommended for reliability (WiFi also supported)
- Static IP Address: Required for consistent DNS resolution
- Router Access: For configuring network-wide DNS settings
Software Requirements
- Raspberry Pi OS (Lite or Desktop)
- At least 512MB free disk space
- Root/sudo access
Installation
Method 1: Automated Installation (Recommended)
The easiest way to install Pi-hole is using the official one-line installer:
| # Update system first
sudo apt update
sudo apt upgrade -y
# Download and run Pi-hole installer
curl -sSL https://install.pi-hole.net | bash
|
Installation Wizard Steps:
-
Choose upstream DNS provider:
- Google:
8.8.8.8 and 8.8.4.4
- Cloudflare:
1.1.1.1 and 1.0.0.1
- OpenDNS:
208.67.222.222 and 208.67.220.220
- Quad9:
9.9.9.9 and 149.112.112.112
-
Select blocklists:
- Enable default blocklists (recommended for beginners)
- You can add more later
-
Select protocols:
- IPv4: Yes (required)
- IPv6: Yes (if your network supports it)
-
Set static IP address:
- Pi-hole will detect your current IP
- Confirm or modify as needed
-
Install web interface:
- Select Yes for admin dashboard
- Install
lighttpd web server
-
Enable query logging:
- Select Yes to see DNS queries
- Can be disabled later for privacy
-
Select privacy mode:
- Show everything (recommended for home use)
- Hide domains or Anonymous mode for more privacy
After installation, note the admin password displayed at the end!
Method 2: Docker Installation
For containerized deployment:
| # Install Docker if not already installed
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add user to docker group
sudo usermod -aG docker $USER
# Create Pi-hole directory
mkdir -p ~/pihole/{etc-pihole,etc-dnsmasq.d}
# Run Pi-hole container
docker run -d \
--name pihole \
-p 53:53/tcp -p 53:53/udp \
-p 80:80 \
-e TZ="America/New_York" \
-e WEBPASSWORD="your-secure-password" \
-v "$(pwd)/pihole/etc-pihole:/etc/pihole" \
-v "$(pwd)/pihole/etc-dnsmasq.d:/etc/dnsmasq.d" \
--dns=127.0.0.1 --dns=1.1.1.1 \
--restart=unless-stopped \
--hostname pi.hole \
pihole/pihole:latest
# Check container status
docker ps
docker logs pihole
|
Initial Configuration
Accessing the Admin Dashboard
Open your web browser and navigate to:
| http://your-pi-ip/admin
# or
http://pi.hole/admin
|
Login with the password set during installation.
Changing Admin Password
| # Set new password
pihole -a -p
# Or reset to random password
pihole -a -p
|
Setting Static IP Address
Using dhcpcd (Raspberry Pi OS):
| # Edit dhcpcd configuration
sudo nano /etc/dhcpcd.conf
# Add at the end (adjust for your network):
interface eth0
static ip_address=192.168.1.100/24
static routers=192.168.1.1
static domain_name_servers=127.0.0.1
|
Reboot after saving:
Configuring DNS on Your Network
Method 1: Router-Level Configuration (Recommended)
This method protects all devices automatically:
-
Access your router's admin panel (usually 192.168.1.1 or 192.168.0.1)
-
Find DNS settings (location varies by router):
- Look for "DHCP Settings" or "LAN Settings"
- Find "Primary DNS" or "DNS Server"
-
Set Primary DNS to your Pi-hole IP:
| Primary DNS: 192.168.1.100 (your Pi-hole IP)
Secondary DNS: (leave blank or use backup like 1.1.1.1)
|
-
Save and reboot router
-
Renew DHCP leases on devices:
- Restart devices or wait for DHCP lease renewal
- Or manually renew: disconnect/reconnect WiFi
Common Router Brands:
- TP-Link: Advanced → Network → DHCP Server
- Netgear: Advanced → Setup → LAN Setup
- Asus: LAN → DHCP Server → DNS Server
- Linksys: Connectivity → Local Network → DHCP Server Settings
Method 2: Individual Device Configuration
For testing or devices you want to configure manually:
Windows:
| Control Panel → Network and Sharing → Change adapter settings
Right-click adapter → Properties → IPv4 → Properties
Use the following DNS server addresses: 192.168.1.100
|
macOS:
| System Preferences → Network → Advanced → DNS
Add DNS Server: 192.168.1.100
|
Linux:
| # Edit resolv.conf
sudo nano /etc/resolv.conf
# Add: nameserver 192.168.1.100
# Or use NetworkManager
nmcli connection modify "Connection Name" ipv4.dns "192.168.1.100"
|
iOS:
| Settings → Wi-Fi → (i) next to network
Configure DNS → Manual → Add Server: 192.168.1.100
|
Android:
| Settings → Network & Internet → Wi-Fi → Long press network
Modify Network → Advanced → DNS 1: 192.168.1.100
|
Testing DNS Configuration
| # Check if using Pi-hole DNS
nslookup pi.hole
# Should return your Pi-hole IP
# Test an ad domain (should be blocked)
nslookup doubleclick.net
# Should return 0.0.0.0 or Pi-hole IP
# Check from remote device
dig @192.168.1.100 google.com
|
Managing Blocklists
Default Blocklists
Pi-hole comes with curated blocklists. View and manage them in the admin dashboard:
Adding Custom Blocklists
Popular Blocklist Sources:
| # Steven Black's Unified Hosts (comprehensive)
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
# OISD Big List (aggressive blocking)
https://big.oisd.nl/
# Energized Protection (balanced)
https://block.energized.pro/blu/formats/hosts.txt
# Ad and tracking servers
https://v.firebog.net/hosts/AdguardDNS.txt
# Malware domains
https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareHosts.txt
|
Adding via Web Interface:
- Go to Group Management → Adlists
- Paste blocklist URL
- Click Add
- Update gravity: Tools → Update Gravity
Adding via Command Line:
| # Add blocklist to database
sqlite3 /etc/pihole/gravity.db \
"INSERT INTO adlist (address, enabled, comment) \
VALUES ('https://example.com/blocklist.txt', 1, 'Description');"
# Update gravity database
pihole -g
|
Whitelist Management
Whitelist a Domain (Web Interface):
| Whitelist → Domain
Enter: example.com
Add to Whitelist
|
Whitelist via Command Line:
| # Add single domain
pihole -w example.com
# Add multiple domains
pihole -w example1.com example2.com example3.com
# Whitelist with regex
pihole --white-regex '.*\.example\.com$'
# View whitelist
pihole -w -l
|
Common Domains to Whitelist:
| # Microsoft services
pihole -w msftncsi.com www.msftncsi.com
# Apple services
pihole -w captive.apple.com
# Amazon Echo
pihole -w device-metrics-us.amazon.com
# Google Play Store
pihole -w android.clients.google.com
# YouTube
pihole -w s.youtube.com video-stats.l.google.com
|
Blacklist Management
Blacklist via Command Line:
| # Add domain to blacklist
pihole -b ads.example.com
# Add regex blacklist (block all subdomains)
pihole --regex '(^|\.)example\.com$'
# View blacklist
pihole -b -l
|
Regex Filtering (Advanced)
Regex allows powerful pattern matching for blocking or whitelisting:
Common Regex Patterns
| # Block all subdomains of a domain
pihole --regex '(^|\.)trackingdomain\.com$'
# Block domains starting with "ad-"
pihole --regex '^ad-.*'
# Block specific TLD endings
pihole --regex '.*\.click$'
# Block numeric domains (often malicious)
pihole --regex '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
# Block known tracking parameters
pihole --regex '\?.*utm_'
|
Testing Regex Patterns
Use the Pi-hole query log or external tools:
| # Test regex pattern
echo "test.example.com" | grep -P '(^|\.)example\.com$'
# Online regex testers:
# https://regex101.com/
|
DNS over HTTPS (DoH) / DNS over TLS (DoT)
Encrypt DNS queries for enhanced privacy.
Method 1: Cloudflared (DoH)
| # Install cloudflared
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb
sudo dpkg -i cloudflared-linux-arm64.deb
# Configure cloudflared
sudo useradd -s /usr/sbin/nologin -r -M cloudflared
# Create configuration file
sudo nano /etc/default/cloudflared
|
Add configuration:
| CLOUDFLARED_OPTS=--port 5053 --upstream https://1.1.1.1/dns-query --upstream https://1.0.0.1/dns-query
|
Create systemd service:
| sudo nano /etc/systemd/system/cloudflared.service
|
| [Unit]
Description=cloudflared DNS over HTTPS proxy
After=syslog.target network-online.target
[Service]
Type=simple
User=cloudflared
EnvironmentFile=/etc/default/cloudflared
ExecStart=/usr/local/bin/cloudflared proxy-dns $CLOUDFLARED_OPTS
Restart=on-failure
RestartSec=10
KillMode=process
[Install]
WantedBy=multi-user.target
|
Enable and start:
| sudo systemctl enable cloudflared
sudo systemctl start cloudflared
# Test DNS resolution
dig @127.0.0.1 -p 5053 google.com
|
Configure Pi-hole to use Cloudflared:
- Go to Settings → DNS
- Uncheck all upstream DNS servers
- Add Custom 1 (IPv4):
127.0.0.1#5053
- Save
Method 2: Unbound (Recursive DNS)
For complete DNS privacy, run your own recursive resolver:
| # Install Unbound
sudo apt install unbound
# Download root hints
sudo wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache
# Configure Unbound
sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf
|
Unbound configuration:
| server:
# Listen on localhost
interface: 127.0.0.1
port: 5335
# Access control
access-control: 127.0.0.1/32 allow
access-control: 0.0.0.0/0 refuse
# Privacy settings
hide-identity: yes
hide-version: yes
harden-glue: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
# Performance
num-threads: 2
msg-cache-slabs: 4
rrset-cache-slabs: 4
infra-cache-slabs: 4
key-cache-slabs: 4
rrset-cache-size: 256m
msg-cache-size: 128m
so-rcvbuf: 1m
# Privacy
prefetch: yes
qname-minimisation: yes
# Root hints
root-hints: "/var/lib/unbound/root.hints"
|
Start Unbound:
| sudo systemctl enable unbound
sudo systemctl start unbound
# Test
dig @127.0.0.1 -p 5335 google.com
|
Configure Pi-hole (Settings → DNS):
- Custom 1 (IPv4): 127.0.0.1#5335
Database Optimization
| # Optimize gravity database
sudo su -
cd /etc/pihole
sqlite3 gravity.db 'VACUUM;'
sqlite3 gravity.db 'REINDEX;'
exit
|
Query Log Management
| # Disable query logging (privacy + performance)
pihole logging off
# Enable logging
pihole logging on
# Clear query database
pihole flush
# Set database size limit (default: 365 days)
sudo nano /etc/pihole/pihole-FTL.conf
|
Add:
| MAXDBDAYS=90
DBINTERVAL=1.0
|
Caching Configuration
Edit /etc/dnsmasq.d/01-pihole.conf:
| # Increase cache size (default 10000)
cache-size=50000
# Set TTL minimum for faster responses
min-cache-ttl=300
max-cache-ttl=3600
|
Restart Pi-hole:
| # Monitor resource usage
htop
# Check Pi-hole FTL performance
pihole -c
# View real-time statistics
pihole chronometer
|
Monitoring and Maintenance
Dashboard Metrics
The admin dashboard provides real-time insights:
- Queries Today: Total DNS queries processed
- Queries Blocked: Percentage of blocked queries
- Blocklist Entries: Number of domains on blocklists
- Clients: Active devices using Pi-hole
Query Log Analysis
| # View recent queries
pihole -t
# Check top blocked domains
pihole -c -j | jq '.top_blocked'
# Search for specific domain in logs
grep "example.com" /var/log/pihole.log
|
Updating Pi-hole
| # Update Pi-hole core and web interface
pihole -up
# Update gravity (blocklists)
pihole -g
# Check Pi-hole version
pihole -v
|
Automated Maintenance Script
Create /usr/local/bin/pihole-maintenance.sh:
| #!/bin/bash
LOG_FILE="/var/log/pihole-maintenance.log"
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
log_message "Starting Pi-hole maintenance"
# Update gravity
pihole -g >> "$LOG_FILE" 2>&1
# Optimize database
sqlite3 /etc/pihole/gravity.db 'VACUUM; REINDEX;' >> "$LOG_FILE" 2>&1
# Clean old logs
find /var/log/pihole*.log -mtime +30 -delete
# Restart FTL
pihole restartdns
log_message "Maintenance completed"
|
Schedule with cron:
| sudo crontab -e
# Run maintenance weekly on Sunday at 3 AM
0 3 * * 0 /usr/local/bin/pihole-maintenance.sh
|
Backup and Restore
Backup Configuration:
| # Backup via web interface
Settings → Teleporter → Backup
# Or manually backup files
sudo tar -czf pihole-backup-$(date +%Y%m%d).tar.gz \
/etc/pihole \
/etc/dnsmasq.d \
/etc/pihole/pihole-FTL.conf
|
Restore Configuration:
| # Via web interface
Settings → Teleporter → Restore
# Or manually
sudo tar -xzf pihole-backup-20240101.tar.gz -C /
pihole restartdns
|
Advanced Features
Group Management
Organize devices and rules by groups:
Creating Groups:
- Go to Group Management → Groups
- Add group name (e.g., "Kids", "Work", "IoT")
- Assign devices to groups
- Apply specific blocklists per group
Assigning Clients to Groups:
| Group Management → Clients
→ Select client → Assign to group
|
Conditional Forwarding
For local network name resolution:
| Settings → DNS → Advanced DNS settings
Enable "Use Conditional Forwarding"
Local network in CIDR notation: 192.168.1.0/24
IP address of DHCP server: 192.168.1.1
Local domain name: home.local
|
DHCP Server
Pi-hole can replace your router's DHCP server:
Enable Pi-hole DHCP:
- Disable DHCP on your router first!
- Go to Settings → DHCP
- Enable "DHCP server enabled"
- Set range:
192.168.1.100 to 192.168.1.250
- Router IP:
192.168.1.1
- Save
Benefits:
- Automatic DNS configuration for all devices
- Better hostname resolution
- Custom DHCP options
Troubleshooting
Pi-hole Not Blocking Ads
| # Check if Pi-hole is running
pihole status
# Verify DNS configuration
nslookup doubleclick.net
# Should return 0.0.0.0 or your Pi-hole IP
# Check gravity database
pihole -g
# Verify blocklist count
pihole -c
# Test with known ad domain
dig @192.168.1.100 ads.google.com
|
DNS Resolution Slow
| # Check upstream DNS response time
pihole query test google.com
# Test upstream DNS directly
dig @1.1.1.1 google.com
# Increase cache size
# Edit /etc/dnsmasq.d/01-pihole.conf
cache-size=50000
# Restart DNS
pihole restartdns
|
Web Interface Not Accessible
| # Check lighttpd status
sudo systemctl status lighttpd
# Restart web server
sudo systemctl restart lighttpd
# Check ports
sudo netstat -tulpn | grep :80
# Check FTL status
pihole status
|
High CPU or Memory Usage
| # Check resource usage
htop
# Reduce database queries
pihole logging off
# Reduce log retention
sudo nano /etc/pihole/pihole-FTL.conf
# Add: MAXDBDAYS=30
# Clear old data
pihole flush
|
Devices Not Using Pi-hole
| # Verify DHCP settings on router
# Check if devices received correct DNS
# On the device, check DNS servers:
# Windows: ipconfig /all
# macOS/Linux: cat /etc/resolv.conf
# Force DHCP renewal
# Windows: ipconfig /release && ipconfig /renew
# macOS: sudo dscacheutil -flushcache
# Linux: sudo dhclient -r && sudo dhclient
|
Pi-hole Update Fails
| # Check free disk space
df -h
# Check for system updates
sudo apt update
sudo apt upgrade
# Repair Pi-hole installation
pihole -r
# Select "Repair"
# Check logs
cat /var/log/pihole_install.log
|
Security Considerations
Securing Admin Interface
| # Set strong password
pihole -a -p
# Restrict admin interface to local network only
sudo nano /etc/lighttpd/lighttpd.conf
|
Add:
| $HTTP["remoteip"] !~ "192.168.1.0/24" {
url.access-deny = ( "" )
}
|
Enable HTTPS (Optional)
| # Install certbot
sudo apt install certbot
# Get certificate (requires domain and port forwarding)
sudo certbot certonly --standalone -d pihole.yourdomain.com
# Configure lighttpd for HTTPS
sudo nano /etc/lighttpd/external.conf
|
| $HTTP["host"] == "pihole.yourdomain.com" {
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/letsencrypt/live/pihole.yourdomain.com/fullchain.pem"
ssl.privkey = "/etc/letsencrypt/live/pihole.yourdomain.com/privkey.pem"
}
}
|
Firewall Configuration
| # Install UFW
sudo apt install ufw
# Allow SSH
sudo ufw allow 22/tcp
# Allow DNS
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
# Allow HTTP (admin interface)
sudo ufw allow 80/tcp
# Optional: Allow HTTPS
sudo ufw allow 443/tcp
# Enable firewall
sudo ufw enable
|
Remote Access
VPN Access (Recommended)
Set up WireGuard VPN to access Pi-hole remotely:
| # Install WireGuard
sudo apt install wireguard
# Generate keys
wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey
# Configure WireGuard
sudo nano /etc/wireguard/wg0.conf
|
Port Forwarding (Not Recommended)
If you must expose Pi-hole publicly:
- Set up HTTPS (see Security section)
- Use non-standard port (e.g., 8443)
- Enable fail2ban for brute-force protection
- Consider using Cloudflare Tunnel instead
Conclusion
Pi-hole transforms your Raspberry Pi into a powerful network-wide ad blocker that provides privacy, security, and performance benefits across your entire network. With features like customizable blocklists, DNS over HTTPS, and comprehensive monitoring, Pi-hole offers enterprise-level DNS management for home users.
Key Takeaways
- Set and Forget: Once configured, Pi-hole works silently in the background
- Privacy First: Block trackers and telemetry across all devices
- Highly Customizable: Fine-tune blocking with whitelists, blacklists, and regex
- Low Maintenance: Automated updates keep blocklists current
- Educational: Learn about DNS and network traffic patterns
Whether you're building a privacy-focused home network, protecting IoT devices from telemetry, or simply tired of intrusive ads, Pi-hole on Raspberry Pi provides an effective, low-cost solution that puts you in control of your network traffic.
Further Reading