Skip to content

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

The easiest way to install Pi-hole is using the official one-line installer:

1
2
3
4
5
6
# 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:

  1. 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
  2. Select blocklists:

    • Enable default blocklists (recommended for beginners)
    • You can add more later
  3. Select protocols:

    • IPv4: Yes (required)
    • IPv6: Yes (if your network supports it)
  4. Set static IP address:

    • Pi-hole will detect your current IP
    • Confirm or modify as needed
  5. Install web interface:

    • Select Yes for admin dashboard
    • Install lighttpd web server
  6. Enable query logging:

    • Select Yes to see DNS queries
    • Can be disabled later for privacy
  7. 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:

1
2
3
http://your-pi-ip/admin
# or
http://pi.hole/admin

Login with the password set during installation.

Changing Admin Password

1
2
3
4
5
# Set new password
pihole -a -p

# Or reset to random password
pihole -a -p

Setting Static IP Address

Using dhcpcd (Raspberry Pi OS):

1
2
3
4
5
6
7
8
# 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:

sudo reboot

Configuring DNS on Your Network

This method protects all devices automatically:

  1. Access your router's admin panel (usually 192.168.1.1 or 192.168.0.1)

  2. Find DNS settings (location varies by router):

    • Look for "DHCP Settings" or "LAN Settings"
    • Find "Primary DNS" or "DNS Server"
  3. 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)
    
  4. Save and reboot router

  5. 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:

1
2
3
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:

1
2
3
4
5
6
# 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:

Settings → Blocklists

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:

  1. Go to Group Management → Adlists
  2. Paste blocklist URL
  3. Click Add
  4. Update gravity: Tools → Update Gravity

Adding via Command Line:

1
2
3
4
5
6
7
# 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):

1
2
3
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:

1
2
3
4
5
6
7
8
# 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:

1
2
3
4
5
# 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)

1
2
3
4
5
6
7
8
9
# 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:

1
2
3
4
5
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:

  1. Go to Settings → DNS
  2. Uncheck all upstream DNS servers
  3. Add Custom 1 (IPv4): 127.0.0.1#5053
  4. Save

Method 2: Unbound (Recursive DNS)

For complete DNS privacy, run your own recursive resolver:

1
2
3
4
5
6
7
8
# 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:

1
2
3
4
5
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

Performance Optimization

Database Optimization

1
2
3
4
5
6
# 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:

1
2
3
4
5
6
# 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:

pihole restartdns

System Performance

1
2
3
4
5
6
7
8
# 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

1
2
3
4
5
6
7
8
# 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

1
2
3
4
5
6
7
8
# 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:

1
2
3
4
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:

1
2
3
4
5
6
7
8
# 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:

1
2
3
4
5
6
# 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:

  1. Go to Group Management → Groups
  2. Add group name (e.g., "Kids", "Work", "IoT")
  3. Assign devices to groups
  4. Apply specific blocklists per group

Assigning Clients to Groups:

Group Management → Clients
→ Select client → Assign to group

Conditional Forwarding

For local network name resolution:

1
2
3
4
5
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:

  1. Disable DHCP on your router first!
  2. Go to Settings → DHCP
  3. Enable "DHCP server enabled"
  4. Set range: 192.168.1.100 to 192.168.1.250
  5. Router IP: 192.168.1.1
  6. 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

1
2
3
4
5
# Set strong password
pihole -a -p

# Restrict admin interface to local network only
sudo nano /etc/lighttpd/lighttpd.conf

Add:

1
2
3
$HTTP["remoteip"] !~ "192.168.1.0/24" {
    url.access-deny = ( "" )
}

Enable HTTPS (Optional)

1
2
3
4
5
6
7
8
# 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
1
2
3
4
5
6
7
$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

Set up WireGuard VPN to access Pi-hole remotely:

1
2
3
4
5
6
7
8
# 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

If you must expose Pi-hole publicly:

  1. Set up HTTPS (see Security section)
  2. Use non-standard port (e.g., 8443)
  3. Enable fail2ban for brute-force protection
  4. 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