Files
EZ-Homelab/docs/service-docs/pihole.md
kelinfoxy cba45556c7 Complete documentation refactoring with 57 service docs
- Refactored README.md, getting-started.md, quick-reference.md
- Enhanced setup-homelab.sh with 9-step automated process
- Created services-overview.md with all stacks
- Added comprehensive documentation for 57 services in docs/service-docs/
- All services include: overview, configuration, resources, educational content
- Coverage: Core, Infrastructure, Dashboards, Media, Media-Extended, Home Assistant, Productivity, Utilities, Monitoring, Development stacks
- Educational focus with links to tutorials, videos, and guides
2026-01-12 18:03:12 -05:00

15 KiB

Pi-hole - Network-Wide Ad Blocker

Table of Contents

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?

  1. Block Ads Everywhere: Mobile apps, smart TVs, IoT devices
  2. Faster Browsing: Pages load faster without ads
  3. Privacy Protection: Block trackers and analytics
  4. Save Bandwidth: Don't download ad content
  5. Malware Protection: Block known malicious domains
  6. Family Safety: Block inappropriate content
  7. Network Visibility: See what devices are connecting where
  8. Free: No subscription fees
  9. 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

  1. Device makes request: "I want to visit ads.google.com"
  2. DNS query sent: Device asks "What's the IP for ads.google.com?"
  3. Pi-hole receives query: Checks against blocklists
  4. If blocked: Returns 0.0.0.0 (null IP) - ad doesn't load
  5. If allowed: Forwards to real DNS (1.1.1.1, 8.8.8.8, etc.)
  6. 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

Educational Resources

Videos

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

  1. Port 53: DNS must be on port 53 (cannot be remapped)
  2. Web Port: Can use 8181 externally, 80 internally
  3. NET_ADMIN: Required capability for DHCP and network features
  4. Password: Set strong password via WEBPASSWORD variable

Setup and Management

Initial Setup

  1. Deploy Pi-hole: Start the container
  2. Wait 60 seconds: Let gravity database build
  3. Access Web UI: https://pihole.yourdomain.com/admin
  4. Login: Use password from WEBPASSWORD
  5. Configure Router: Point DNS to Pi-hole server IP

Router Configuration

Method 1: DHCP DNS Settings (Recommended)

  1. Access router admin panel
  2. Find DHCP settings
  3. Set Primary DNS: Pi-hole server IP (e.g., 192.168.1.10)
  4. Set Secondary DNS: 1.1.1.1 or 8.8.8.8 (fallback)
  5. 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:

  1. Group Management → Adlists
  2. Add list URL
  3. 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):

  1. Whitelist → Add domain
  2. Example: example.com
  3. Supports wildcards: *.example.com

Blacklist Domain (Block):

  1. Blacklist → Add domain
  2. 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:

  1. Query Log → See all DNS requests
  2. Filter by client, domain, type
  3. 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:

  1. Local DNS → DNS Records
  2. Add domain → IP mapping
  3. 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:

  1. Create Groups:

    • Group Management → Groups → Add Group
    • Example: "Kids Devices", "Guest Network"
  2. Assign Clients:

    • Group Management → Clients → Add client to group
  3. 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:

  1. Domains → Regex Filter
  2. Add regex pattern
  3. 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:

  1. Disable DHCP on router
  2. Enable DHCP in Pi-hole
  3. 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

  1. Strong Password: Use complex WEBPASSWORD
  2. Authelia Protection: Add Authelia middleware for external access
  3. Firewall Rules: Only expose port 53 as needed
  4. Update Regularly: Keep Pi-hole container updated
  5. Backup Config: Regular backups of /etc/pihole directory
  6. Query Privacy: Enable privacy mode for sensitive networks
  7. Upstream DNS: Use privacy-focused DNS (Quad9, Cloudflare)
  8. Monitor Logs: Watch for unusual query patterns
  9. Network Segmentation: Separate IoT devices
  10. 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:

  1. Settings → Teleporter
  2. Click "Backup"
  3. 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:

  1. Settings → Teleporter
  2. Choose file
  3. 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:

  1. Deploy Pi-hole container
  2. Set strong admin password
  3. Configure router DNS settings
  4. Add blocklists (Firebog)
  5. Monitor dashboard
  6. Whitelist as needed
  7. Configure DoH for privacy
  8. 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