🎯 New! Master certifications with Performance-Based Questions (PBQ) — realistic hands-on practice for CompTIA & Cisco exams!

Pi-hole Complete Setup Guide 2026: Network-Wide Ad Blocking & DNS Management

Published on January 12, 2026


Introduction

Pi-hole is a powerful, open-source network-wide ad blocker that acts as a DNS sinkhole, protecting all devices on your network from unwanted advertisements, trackers, and malicious domains. Unlike browser-based ad blockers, Pi-hole works at the DNS level, blocking ads before they even reach your devices—including smart TVs, IoT devices, and mobile apps where traditional ad blockers cannot be installed.

Pi-hole is free, open-source (licensed under GPLv2), and community-driven, ensuring no data collection beyond what’s needed for operation. It supports IPv4 and IPv6, caches DNS queries for faster resolution, and includes an optional built-in DHCP server for automatic device configuration.

💡 Current Version: As of January 2026, the latest stable releases are Pi-hole Core v6.3, FTL v6.4, and Web Interface v6.4. Always check the official GitHub releases for the most current version before installation.

This comprehensive guide covers every aspect of Pi-hole deployment, from basic installation on a Raspberry Pi to advanced configurations including Docker deployment, recursive DNS with Unbound, VPN integration, NAS installation, high availability setups, and Home Assistant integration. We’ll explain every command, what it does, and provide platform-specific instructions for Windows, macOS, and Linux.

What is Pi-hole?

Pi-hole intercepts DNS requests from devices on your network and checks them against blocklists containing known advertising, tracking, and malicious domains. If a request matches a blocked domain, Pi-hole returns a null response, effectively “sinking” the request into a black hole—hence the name.

+-------------------------------------------------------------------+
|                    HOW PI-HOLE WORKS                              |
+-------------------------------------------------------------------+
|                                                                   |
|   +----------+     DNS Request      +--------------+              |
|   |  Device  | ------------------->  |   Pi-hole    |              |
|   | (Phone,  |     "ads.com?"       |   (DNS       |              |
|   |  TV, PC) |                      |    Server)   |              |
|   +----------+                      +------+-------+              |
|                                            |                      |
|                           +----------------+----------------+     |
|                           |                                 |     |
|                           v                                 v     |
|                   +---------------+               +-------------+ |
|                   |  On Blocklist |               | Not Blocked | |
|                   |   (Blocked)   |               |  (Allowed)  | |
|                   +-------+-------+               +------+------+ |
|                           |                              |        |
|                           v                              v        |
|                   +---------------+               +-------------+ |
|                   | Returns 0.0.0.0|              | Forwards to | |
|                   | (Ad Blocked!) |               | Upstream DNS| |
|                   +---------------+               +-------------+ |
|                                                                   |
+-------------------------------------------------------------------+

Key Features

FeatureDescription
Network-Wide BlockingBlocks ads and trackers for ALL devices (browsers, apps, smart TVs, IoT) without per-device setup
Web DashboardResponsive UI for stats, query logs, long-term data, audit logs, and privacy controls
DNS CachingCaches DNS results locally for faster response times on frequently accessed domains
Custom BlocklistsAdd or remove domains from blocklists with regex support for fine-tuned blocking
DHCP ServerOptional built-in DHCP server for automatic client configuration
Privacy ModesFour privacy levels: show everything, hide domains, hide domains and clients, or anonymous mode
API & CLIFull REST API and command-line interface for scripting and automation
IPv4 & IPv6Full support for both IPv4 and IPv6 networks
Low Resource UsageCan run on a Raspberry Pi Zero W using ~50MB of RAM
ScalabilityHandles millions of queries on server hardware

📊 Performance: Users typically report 15-30% faster page loads and significant privacy gains from reduced tracker connections.

Pi-hole v6 New Features (February 2025)

Pi-hole v6 introduced major architectural changes:

FeatureDescription
Embedded Web ServerNo longer requires lighttpd or PHP—integrated directly into pihole-FTL
Native HTTPS SupportBuilt-in SSL/TLS support for secure admin interface access
REST APINew comprehensive REST API replacing the legacy PHP-based API
TOML ConfigurationSingle, richly commented configuration file for easier management
Subscribed Allowlists“Antigravity” feature for maintaining curated allowlists
Redesigned UIModern interface with Basic and Expert modes

Who Is This Guide For?

  • Home users wanting to block ads on all devices
  • Privacy enthusiasts seeking to reduce online tracking
  • Home lab enthusiasts building network infrastructure
  • Parents implementing network-level content filtering
  • IT professionals managing small business networks

Estimated Time

Installation MethodEstimated Time
Bare Metal (Raspberry Pi)20-30 minutes
Docker (Linux)15-20 minutes
Docker (Windows/macOS)30-45 minutes
Proxmox LXC30-45 minutes
Synology NAS20-30 minutes
With Unbound SetupAdd 15-20 minutes

Part 1: System Requirements

Hardware Requirements

Pi-hole is extremely lightweight and can run on minimal hardware:

ComponentMinimumRecommendedNotes
RAM512 MB1-2 GBMore RAM helps with large blocklists
Storage2 GB4+ GBSSD recommended for faster performance
CPU1 core2+ coresAny modern CPU is sufficient
NetworkAnyWired EthernetWi-Fi works but wired is more reliable

Raspberry Pi Model Recommendations

ModelSuitabilityNotes
Raspberry Pi Zero 2 W✅ ExcellentBest budget option, low power, sufficient performance
Raspberry Pi 3 B/B+✅ ExcellentGood balance with built-in Ethernet
Raspberry Pi 4 B✅ OverkillOnly needed if running additional services
Raspberry Pi 5✅ OverkillBest for multi-service setups
Raspberry Pi Zero W⚠️ AdequateWorks but Zero 2 W is preferred

💡 Tip: For dedicated Pi-hole use, the Raspberry Pi Zero 2 W with a USB Ethernet adapter is the most cost-effective option.

Software Requirements

ComponentRequired VersionPurpose
Operating SystemSee supported listHost for Pi-hole
Docker20.10+For containerized installations
Docker Composev2.0+Multi-container orchestration

Supported Operating Systems

Pi-hole officially supports actively maintained versions of:

  • Alpine Linux
  • Armbian OS
  • Debian (10+)
  • CentOS Stream
  • Fedora
  • Raspberry Pi OS (formerly Raspbian)
  • Ubuntu (20.04+)

Supported Architectures

Pre-built binaries are available for:

  • x86_64 (amd64 and i686)
  • armv6 (Raspberry Pi Zero/1)
  • armv7 (Raspberry Pi 2/3)
  • armv8/aarch64 (Raspberry Pi 3/4/5 64-bit)
  • riscv64

Network Requirements

RequirementDetails
Static IP AddressPi-hole must have a static IP (DHCP reservation acceptable)
Port 53DNS queries (TCP/UDP)
Port 80/443Web interface (or custom port)
Port 67DHCP server (optional)
Port 123NTP server (optional)

Part 2: General Use Cases

Pi-hole’s primary role is ad and tracker blocking, but its DNS capabilities extend to broader applications for home and enterprise environments.

Primary Use Cases

Use CaseDescription
Ad Blocking in AppsBlocks ads in mobile apps, games, smart TVs, and streaming devices where browser extensions can’t reach
Privacy EnhancementPrevents tracking by sinkholing domains from telemetry services (Google Analytics, Facebook trackers)
Parental ControlsBlock adult content, gambling, or social media sites via custom blocklists
Bandwidth OptimizationReduces data usage by stopping ad downloads—useful for metered connections or mobile hotspots
Network MonitoringLogs DNS queries to identify unusual activity, like malware phoning home
Enterprise FilteringIn small offices or schools, filter phishing and malware domains
IoT SecurityProtects smart devices from connecting to malicious or telemetry servers
VPN IntegrationPair with VPN for ad-free mobile use outside your home network

Home Lab Capabilities with Examples

In a home lab or personal setup, Pi-hole shines as a low-maintenance tool for network management:

CapabilityDescriptionExample
DNS Caching & ForwardingSpeeds up repeated queries; forwards legit requests to upstream DNSConfigure Cloudflare (1.1.1.1) as upstream for faster resolution
DHCP ServerAssigns IPs and auto-configures DNS for devicesEnable DHCP in Pi-hole to simplify device setup
Query AnalysisDashboard shows top blocked domains, clients, and query typesUse query log to troubleshoot why a site isn’t working
Custom BlockingAdd regex for patternsBlock all *.ads.example.com with a single regex rule
High AvailabilityRun multiple instances with sync tools for redundancyTwo Pi-holes with Orbital Sync for fault tolerance
Resource EfficiencyRuns alongside other services on shared hardwareCombine with Unbound on the same Raspberry Pi

Real-World Examples:

  1. Basic Ad Blocking: A family runs Pi-hole and sees no ads on their Roku, smart TV apps, and mobile games—blocking 100,000+ domains out-of-the-box.

  2. IoT Monitoring: Log queries from smart bulbs and cameras to detect anomalies. Block a compromised camera from contacting external servers.

  3. Custom Filters: Whitelist a site if blocking breaks functionality (e.g., allow cdn.example.com for a game). Use the audit log to identify and tweak.

  4. Privacy Testing: Experiment with privacy modes; e.g., anonymous mode hides client IPs in logs for GDPR-like compliance testing.


Part 3: Pre-Installation Preparation

Before installing Pi-hole, complete these preparation steps on your target system.

Step 1: Update Your System

Always start with an updated system to avoid compatibility issues.

Linux (Debian/Ubuntu/Raspberry Pi OS)

# Update package lists and upgrade all packages
sudo apt update && sudo apt full-upgrade -y

# Explanation:
# - sudo: Run with administrator privileges
# - apt update: Refreshes the list of available packages
# - apt full-upgrade: Installs newer versions (handles dependencies better than upgrade)
# - -y: Automatically answer "yes" to prompts

Linux (Fedora/RHEL/CentOS)

sudo dnf update -y

Linux (Alpine)

sudo apk update && sudo apk upgrade

macOS

# Update macOS
softwareupdate -i -a

# If using Homebrew, also run:
brew update && brew upgrade

Windows

  1. Open SettingsUpdate & SecurityWindows Update
  2. Click Check for updates
  3. Install all available updates
  4. Restart if prompted

Step 2: Set a Static IP Address

Pi-hole requires a static IP address for reliable DNS service.

Linux (NetworkManager - GUI)

  1. Open SettingsNetworkWired/Wi-FiSettings (gear icon)
  2. Select IPv4 tab
  3. Change Method to Manual
  4. Enter:
    • Address: 192.168.1.100 (example)
    • Netmask: 255.255.255.0
    • Gateway: 192.168.1.1 (your router)
  5. Click Apply

Linux (Command Line - Debian/Ubuntu)

Edit /etc/network/interfaces or use netplan:

# For netplan (Ubuntu 18.04+)
sudo nano /etc/netplan/01-netcfg.yaml
network:
  version: 2
  ethernets:
    eth0:
      dhcp4: no
      addresses:
        - 192.168.1.100/24
      gateway4: 192.168.1.1
      nameservers:
        addresses:
          - 8.8.8.8
          - 8.8.4.4
# Apply configuration
sudo netplan apply

Raspberry Pi OS

sudo nano /etc/dhcpcd.conf

Add at the end:

interface eth0
static ip_address=192.168.1.100/24
static routers=192.168.1.1
static domain_name_servers=8.8.8.8 8.8.4.4
# Restart networking
sudo systemctl restart dhcpcd

macOS

  1. Open System PreferencesNetwork
  2. Select your connection → AdvancedTCP/IP
  3. Change Configure IPv4 to Manually
  4. Enter your IP, Subnet Mask, and Router
  5. Click OKApply

Windows

  1. Open Control PanelNetwork and Sharing Center
  2. Click your connection → Properties
  3. Select Internet Protocol Version 4 (TCP/IPv4)Properties
  4. Select Use the following IP address
  5. Enter your IP, Subnet mask, and Default gateway
  6. Click OK

Step 3: Configure Firewall

Open required ports for Pi-hole.

Linux (UFW - Ubuntu/Debian)

# Allow DNS traffic
sudo ufw allow 53/tcp
sudo ufw allow 53/udp

# Allow web interface
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# If using Pi-hole's DHCP
sudo ufw allow 67/udp

# Check status
sudo ufw status

Linux (firewalld - Fedora/RHEL)

sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-service=dhcp
sudo firewall-cmd --reload

Linux (iptables)

# Accept DNS
sudo iptables -A INPUT -p tcp --dport 53 -s 192.168.0.0/16 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 53 -s 192.168.0.0/16 -j ACCEPT

# Accept HTTP/HTTPS
sudo iptables -A INPUT -p tcp --dport 80 -s 192.168.0.0/16 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -s 192.168.0.0/16 -j ACCEPT

# Save rules
sudo iptables-save | sudo tee /etc/iptables/rules.v4

Windows Firewall

# Run PowerShell as Administrator
# Allow DNS
New-NetFirewallRule -DisplayName "Pi-hole DNS TCP" -Direction Inbound -Protocol TCP -LocalPort 53 -Action Allow
New-NetFirewallRule -DisplayName "Pi-hole DNS UDP" -Direction Inbound -Protocol UDP -LocalPort 53 -Action Allow

# Allow Web Interface
New-NetFirewallRule -DisplayName "Pi-hole HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "Pi-hole HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow

Part 3: Bare Metal Installation (Linux)

This is the recommended installation method for Raspberry Pi and dedicated Linux servers.

Step 1: Run the Pi-hole Installer

The official one-step installer handles everything automatically:

curl -sSL https://install.pi-hole.net | sudo bash

Command Breakdown:

  • curl: Command-line tool for downloading from URLs
  • -sSL: Silent mode with error display, follow redirects
  • https://install.pi-hole.net: Official installer script
  • | sudo bash: Pipes the script to bash with admin privileges

⚠️ Security Note: While convenient, piping to bash can be risky. For maximum security, download and review the script first:

# Download first, review, then run
curl -sSL https://install.pi-hole.net -o pihole-install.sh
cat pihole-install.sh  # Review the script
sudo bash pihole-install.sh

Step 2: Follow the Installation Wizard

The interactive installer will guide you through:

  1. Static IP Confirmation: Confirms your static IP configuration

  2. Upstream DNS Provider: Choose your preferred DNS resolver:

    • Google (8.8.8.8, 8.8.4.4)
    • OpenDNS (208.67.222.222)
    • Cloudflare (1.1.1.1) - Recommended for speed
    • Quad9 (9.9.9.9) - Security-focused
    • Custom - For Unbound or other local resolvers
  3. Blocklists: Accept default blocklists (StevenBlack’s unified hosts)

  4. Admin Web Interface: Install the web interface (highly recommended)

  5. Web Server: Install lighttpd (for Pi-hole v5) or use built-in (v6+)

  6. Query Logging: Enable logging for troubleshooting

  7. Privacy Mode: Choose your FTL privacy level:

    • 0: Show everything
    • 1: Hide domains
    • 2: Hide domains and clients
    • 3: Anonymous mode

Step 3: Note Your Admin Password

At the end of installation, Pi-hole generates a random admin password:

[✓] Installation complete!

  Configure your router's DHCP options to use Pi-hole as the DNS server
  or set Pi-hole's IP address as the DNS on individual devices.

  Pi-hole web interface: http://192.168.1.100/admin
  Admin password: [randomly generated password]

  Your password can be changed using 'pihole -a -p'

Change the password immediately:

# Set a new admin password
pihole -a -p

# You'll be prompted to enter a new password twice

Step 4: Verify Installation

# Check Pi-hole status
pihole status

# Expected output:
#   [✓] FTL is running
#   [✓] Pi-hole blocking is enabled

# Test DNS resolution
dig @127.0.0.1 example.com

# Check version
pihole -v

Step 5: Access the Web Interface

  1. Open your web browser
  2. Navigate to: http://YOUR_PI_IP/admin or http://pi.hole/admin
  3. Log in with your admin password
  4. Explore the dashboard!

Part 4: Docker Installation

Docker provides isolated, portable, and easily updatable Pi-hole deployments.

Method 1: Docker on Linux

Step 1: Install Docker

# Remove old versions
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do
  sudo apt-get remove -y $pkg 2>/dev/null
done

# Install prerequisites
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg

# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | 
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add Docker repository
echo 
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg]   https://download.docker.com/linux/ubuntu   $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | 
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io 
  docker-buildx-plugin docker-compose-plugin

# Add your user to docker group (optional, avoids sudo)
sudo usermod -aG docker $USER
newgrp docker

# Verify installation
docker --version
docker compose version

Step 2: Create Project Directory

mkdir -p ~/pihole
cd ~/pihole

Step 3: Create docker-compose.yml

nano docker-compose.yml
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      # DNS ports
      - "53:53/tcp"
      - "53:53/udp"
      # Web interface ports (change left side if port conflicts)
      - "80:80/tcp"
      - "443:443/tcp"
      # Uncomment for DHCP (requires --cap-add=NET_ADMIN)
      # - "67:67/udp"
    environment:
      # Set your timezone
      TZ: 'America/New_York'
      # Set a strong admin password
      FTLCONF_webserver_api_password: 'your-secure-password-here'
      # Upstream DNS (Cloudflare example)
      FTLCONF_dns_upstreams: '1.1.1.1;1.0.0.1'
    volumes:
      # Persistent data storage
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'
    cap_add:
      # Required for DHCP functionality
      - NET_ADMIN
    restart: unless-stopped

Environment Variable Explanations:

VariablePurposeExample
TZTimezone for logs and UIAmerica/New_York, Europe/London
FTLCONF_webserver_api_passwordAdmin interface passwordStrong password
FTLCONF_dns_upstreamsUpstream DNS servers1.1.1.1;1.0.0.1

Step 4: Create Data Directories

mkdir -p etc-pihole etc-dnsmasq.d

Step 5: Start Pi-hole

# Pull the image and start
docker compose up -d

# Check container status
docker compose ps

# View logs
docker compose logs -f pihole

Step 6: Access the Web Interface

Navigate to http://YOUR_SERVER_IP/admin and log in.


Method 2: Docker on Windows (WSL2)

Prerequisites

  • Windows 10 (version 2004+) or Windows 11
  • WSL2 enabled
  • Docker Desktop installed

Step 1: Enable WSL2

Open PowerShell as Administrator:

# Enable WSL feature
wsl --install

# Restart your computer when prompted
# After restart, WSL will complete installation

Step 2: Install Docker Desktop

  1. Download Docker Desktop from docker.com
  2. Run the installer
  3. Check “Use WSL 2 instead of Hyper-V”
  4. Complete installation and restart

Step 3: Configure Docker Desktop

  1. Open Docker Desktop
  2. Go to SettingsResourcesWSL Integration
  3. Enable integration with your default distro
  4. Click Apply & Restart

Step 4: Create Project Directory

Open PowerShell:

# Create directory
mkdir C:Users$env:USERNAMEDocumentsDockerpihole
cd C:Users$env:USERNAMEDocumentsDockerpihole

# Create subdirectories
New-Item -ItemType Directory -Path etc-pihole, etc-dnsmasq.d -Force

Step 5: Create docker-compose.yml

notepad docker-compose.yml

Paste the same YAML content from Method 1, but adjust volume paths:

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "8080:80/tcp"  # Changed to avoid conflicts
      - "8443:443/tcp"
    environment:
      TZ: 'America/New_York'
      FTLCONF_webserver_api_password: 'your-secure-password-here'
      FTLCONF_dns_upstreams: '1.1.1.1;1.0.0.1'
    volumes:
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'
    cap_add:
      - NET_ADMIN
    restart: unless-stopped

⚠️ Port 80 Conflict: Windows often uses port 80 for IIS or other services. We use 8080 instead.

Step 6: Start Pi-hole

docker compose up -d
docker compose ps

Step 7: Configure Windows DNS

To use Pi-hole as your DNS:

  1. Open Control PanelNetwork and Sharing Center
  2. Click your connection → Properties
  3. Select Internet Protocol Version 4Properties
  4. Select Use the following DNS server addresses
  5. Enter your Pi-hole IP (use 127.0.0.1 if running locally)

Access the web interface at http://localhost:8080/admin


Method 3: Docker on macOS

Step 1: Install Docker Desktop

  1. Download Docker Desktop for Mac from docker.com
    • Apple Silicon (M1/M2/M3/M4): Download “Apple Chip” version
    • Intel Macs: Download “Intel Chip” version
  2. Drag Docker.app to Applications
  3. Launch Docker from Applications

Step 2: Configure Resources

  1. Docker Desktop → SettingsResources
  2. Allocate at least 2GB RAM (4GB recommended)
  3. Click Apply & Restart

Step 3: Create Project Directory

mkdir -p ~/pihole
cd ~/pihole
mkdir -p etc-pihole etc-dnsmasq.d

Step 4: Create docker-compose.yml

nano docker-compose.yml

Use the same YAML as Linux, but change ports to avoid conflicts:

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      - "5353:53/tcp"  # macOS uses port 53 for mDNSResponder
      - "5353:53/udp"
      - "8080:80/tcp"
      - "8443:443/tcp"
    environment:
      TZ: 'America/Los_Angeles'
      FTLCONF_webserver_api_password: 'your-secure-password-here'
      FTLCONF_dns_upstreams: '1.1.1.1;1.0.0.1'
    volumes:
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'
    cap_add:
      - NET_ADMIN
    restart: unless-stopped

⚠️ macOS Port 53: macOS uses port 53 for mDNSResponder (Bonjour). We use 5353 instead.

Step 5: Start Pi-hole

docker compose up -d
docker compose ps

Step 6: Configure macOS DNS

To use Pi-hole (with custom port):

  1. Open System PreferencesNetwork
  2. Select your connection → AdvancedDNS
  3. Add 127.0.0.1 as DNS server
  4. Then configure your router to point to your Mac’s IP

Access the web interface at http://localhost:8080/admin


Part 5: NAS & Virtualization Installations

Synology NAS (Docker/Container Manager)

Prerequisites

  • Synology DSM 7.0+ with Container Manager installed
  • SSH access enabled (optional but helpful)

Step 1: Install Container Manager

  1. Open Package Center
  2. Search for “Container Manager” (or “Docker” on older DSM)
  3. Click Install

Step 2: Create Folders

  1. Open File Station
  2. Navigate to your docker share (create one if needed)
  3. Create folder structure:
    docker/
    └── pihole/
        ├── etc-pihole/
        └── etc-dnsmasq.d/

Step 3: Create Project

  1. Open Container ManagerProject
  2. Click Create
  3. Enter name: pihole
  4. Set path: /volume1/docker/pihole
  5. Select Create docker-compose.yml

Step 4: Enter Docker Compose Configuration

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "8082:80/tcp"   # Changed to avoid DSM conflicts
      - "4443:443/tcp"
    environment:
      TZ: 'America/New_York'
      FTLCONF_webserver_api_password: 'your-secure-password'
      FTLCONF_dns_upstreams: '1.1.1.1;1.0.0.1'
      PIHOLE_UID: '1026'  # Match your Synology user ID
      PIHOLE_GID: '100'
    volumes:
      - '/volume1/docker/pihole/etc-pihole:/etc/pihole'
      - '/volume1/docker/pihole/etc-dnsmasq.d:/etc/dnsmasq.d'
    cap_add:
      - NET_ADMIN
    restart: unless-stopped

💡 Finding UID/GID: SSH into Synology and run id to find your user’s UID/GID

Step 5: Build and Start

  1. Click NextDone
  2. Container Manager will pull images and start Pi-hole
  3. Access at http://SYNOLOGY_IP:8082/admin

Proxmox LXC Container

LXC containers are lighter than VMs and perfect for Pi-hole.

Step 1: Download Template

# SSH into Proxmox host
pveam update
pveam available | grep debian
pveam download local debian-12-standard_12.2-1_amd64.tar.zst

Step 2: Create LXC Container

Using Proxmox web UI:

  1. Click Create CT
  2. General Tab:
    • CT ID: 100 (or next available)
    • Hostname: pihole
    • Password: Set root password
    • Check Unprivileged container
  3. Template: Select debian-12-standard
  4. Disk: 4-8 GB
  5. CPU: 1-2 cores
  6. Memory: 512-1024 MB
  7. Network:
    • Bridge: vmbr0
    • IPv4: Static IP (e.g., 192.168.1.100/24)
    • Gateway: 192.168.1.1
  8. DNS: Use host settings or 8.8.8.8
  9. Check Start at boot
  10. Under Options: Enable Nesting (required for Pi-hole)

Step 3: Start Container and Install Pi-hole

# Start the container
pct start 100

# Enter the container console
pct console 100

# Update system
apt update && apt upgrade -y

# Install curl
apt install curl -y

# Install Pi-hole
curl -sSL https://install.pi-hole.net | bash

Follow the installation wizard as described in Part 3.

Step 4: Set Admin Password

pihole -a -p

Access at http://192.168.1.100/admin


Part 6: Unbound Recursive DNS Setup

Unbound is a validating, recursive, caching DNS resolver that allows Pi-hole to resolve DNS queries directly from root servers, enhancing privacy by not relying on third-party DNS providers.

Why Use Unbound with Pi-hole?

BenefitDescription
Maximum PrivacyDNS queries never leave your network to third parties
DNSSEC ValidationValidates DNS responses for authenticity
Reduced LatencyLocal caching improves repeat query speed
IndependenceNo reliance on Google, Cloudflare, or other providers

Installation

Step 1: Install Unbound

Linux (Debian/Ubuntu)
sudo apt update
sudo apt install unbound -y
Linux (Fedora/RHEL)
sudo dnf install unbound -y
Linux (Alpine)
sudo apk add unbound

Step 2: Download Root Hints

Root hints tell Unbound where to find the root DNS servers:

# Download root hints
sudo wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.root

# Verify download
ls -la /var/lib/unbound/root.hints

💡 Tip: Update root hints every 6 months. Add to crontab:

echo "0 0 1 */6 * root wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.root" | sudo tee -a /etc/crontab

Step 3: Configure Unbound for Pi-hole

Create Pi-hole specific configuration:

sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf
server:
    # Listen on localhost, port 5335 (Pi-hole will use 53)
    interface: 127.0.0.1
    port: 5335
    
    # Allow queries from localhost only
    access-control: 127.0.0.0/8 allow
    
    # Enable IPv4 and disable IPv6 (adjust if you use IPv6)
    do-ip4: yes
    do-ip6: no
    do-udp: yes
    do-tcp: yes
    
    # Security hardening
    harden-glue: yes
    harden-dnssec-stripped: yes
    harden-large-queries: yes
    harden-algo-downgrade: yes
    
    # Privacy settings
    qname-minimisation: yes
    use-caps-for-id: yes
    
    # Root hints file location
    root-hints: "/var/lib/unbound/root.hints"
    
    # Cache settings
    cache-min-ttl: 3600
    cache-max-ttl: 86400
    prefetch: yes
    prefetch-key: yes
    
    # Performance
    num-threads: 2
    msg-cache-size: 50m
    rrset-cache-size: 100m
    
    # Logging (minimal by default)
    verbosity: 0
    
    # Private addresses - don't forward
    private-address: 192.168.0.0/16
    private-address: 169.254.0.0/16
    private-address: 172.16.0.0/12
    private-address: 10.0.0.0/8

Step 4: Start Unbound

# Restart Unbound
sudo systemctl restart unbound

# Enable on boot
sudo systemctl enable unbound

# Check status
sudo systemctl status unbound

Step 5: Test Unbound

# Test DNS resolution through Unbound
dig example.com @127.0.0.1 -p 5335

# Expected output should show NOERROR status
# ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: xxxxx

Step 6: Configure Pi-hole to Use Unbound

  1. Open Pi-hole web interface (http://pi.hole/admin)
  2. Go to SettingsDNS
  3. Uncheck all default upstream DNS servers
  4. Under Custom 1 (IPv4), enter: 127.0.0.1#5335
  5. Check Use DNSSEC (Unbound handles validation)
  6. Click Save

Docker Unbound + Pi-hole Setup

For Docker environments, run both containers:

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    depends_on:
      - unbound
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80/tcp"
    environment:
      TZ: 'America/New_York'
      FTLCONF_webserver_api_password: 'your-password'
      FTLCONF_dns_upstreams: 'unbound#5335'
    volumes:
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'
    restart: unless-stopped
    networks:
      - pihole_net

  unbound:
    container_name: unbound
    image: mvance/unbound:latest
    volumes:
      - './unbound:/opt/unbound/etc/unbound'
    restart: unless-stopped
    networks:
      - pihole_net

networks:
  pihole_net:
    driver: bridge

Part 7: Configuring Your Network

After installing Pi-hole, you need to configure your network to use it as the DNS server.

This ensures ALL devices automatically use Pi-hole.

General Router Steps

  1. Log into your router’s admin interface
  2. Find DHCP Settings or LAN Settings
  3. Change Primary DNS to your Pi-hole’s IP address
  4. Leave Secondary DNS blank (or set to Pi-hole’s IP)
  5. Save and restart router

⚠️ Important: Leaving Secondary DNS as another provider (like 8.8.8.8) allows devices to bypass Pi-hole!

Option 2: Use Pi-hole’s DHCP Server

If your router doesn’t allow DNS changes, Pi-hole can serve DHCP:

  1. Disable your router’s DHCP server first
  2. In Pi-hole: SettingsDHCP
  3. Check DHCP server enabled
  4. Configure:
    • Range of addresses to assign
    • Router IP (gateway)
    • Lease time
  5. Click Save

Option 3: Static DNS on Devices

Configure individual devices to use Pi-hole:

Windows

# View current DNS
ipconfig /all

# Set DNS (replace with your adapter name)
netsh interface ip set dns "Wi-Fi" static 192.168.1.100 primary

Or via GUI: Network Settings → Advanced → DNS

macOS

# Set DNS
sudo networksetup -setdnsservers Wi-Fi 192.168.1.100

# Verify
scutil --dns

Linux

Edit /etc/resolv.conf or NetworkManager settings:

nameserver 192.168.1.100

iOS

Settings → Wi-Fi → [Network] → Configure DNS → Manual → Add 192.168.1.100

Android

Settings → Network → Wi-Fi → [Network] → Advanced → IP Settings → Static → DNS 1: 192.168.1.100


Part 8: Blocklists Management

Pi-hole’s effectiveness depends on quality blocklists.

BlocklistFocusURL
HaGeZi Multi ProAds, tracking, malwarehttps://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/pro.txt
OISDComprehensivehttps://abp.oisd.nl/
StevenBlack UnifiedAds + malwarehttps://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
Firebog Tick ListCurated safe listsMultiple lists at firebog.net

Adding Blocklists

  1. Go to Group ManagementAdlists
  2. Enter the blocklist URL in the Address field
  3. Add a descriptive Comment
  4. Click Add
  5. Run ToolsUpdate Gravity to activate

Command Line Management

# Update blocklists (gravity)
pihole -g

# Add a blocklist
pihole -a adlist add https://example.com/blocklist.txt

# View current lists
pihole -a adlist list

Whitelisting Domains

Sometimes Pi-hole blocks legitimate sites:

# Add to whitelist
pihole -w example.com

# Remove from whitelist
pihole -w -d example.com

# Add to blacklist
pihole -b example.com

Via Web UI: Domains → Add domain → Select Whitelist


Part 9: VPN Integration

WireGuard + Pi-hole

Use Pi-hole for ad blocking when away from home.

Step 1: Install WireGuard

# Debian/Ubuntu
sudo apt install wireguard -y

# Generate keys
wg genkey | tee privatekey | wg pubkey > publickey

Step 2: Configure WireGuard Server

sudo nano /etc/wireguard/wg0.conf
[Interface]
PrivateKey = YOUR_PRIVATE_KEY
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# Use Pi-hole as DNS
DNS = 192.168.1.100

[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32

Step 3: Start WireGuard

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

Step 4: Configure Pi-hole for VPN Clients

In Pi-hole: SettingsDNSInterface settings:

  • Select Permit all origins to allow VPN client queries

Tailscale + Pi-hole

Tailscale simplifies VPN setup with automatic NAT traversal.

Step 1: Install Tailscale

# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# Authenticate
sudo tailscale up

Step 2: Get Pi-hole’s Tailscale IP

tailscale ip -4
# Example output: 100.x.x.x

Step 3: Configure Tailscale DNS

  1. Log into Tailscale Admin Console
  2. Under Global nameservers, add your Pi-hole’s Tailscale IP: 100.x.x.x
  3. Enable Override local DNS

Step 4: Configure Pi-hole

In Pi-hole SettingsDNSInterface settings:

  • Select Permit all origins

Or specifically add the Tailscale interface (tailscale0)

Now all Tailscale-connected devices use Pi-hole!


Part 10: Home Assistant Integration

Pi-hole integrates with Home Assistant for automation and monitoring.

Setup Integration

  1. In Home Assistant: SettingsDevices & ServicesAdd Integration
  2. Search for Pi-hole
  3. Enter:
    • Host: Pi-hole IP address
    • Port: 80 (or your custom port)
    • API Key/Password: Found in Pi-hole under SettingsAPI (expert mode)
  4. Click Submit

Available Entities

Entity TypeNameFunction
Switchswitch.pi_holeEnable/disable blocking
Sensorsensor.pi_hole_ads_blocked_todayDaily blocked count
Sensorsensor.pi_hole_ads_percentage_blocked_todayBlock percentage
Sensorsensor.pi_hole_dns_queries_todayTotal queries
Sensorsensor.pi_hole_domains_blockedBlocklist size

Example Automation

Disable Pi-hole for 5 minutes when a button is pressed:

automation:
  - alias: "Temporarily Disable Pi-hole"
    trigger:
      - platform: state
        entity_id: input_button.disable_pihole
    action:
      - service: switch.turn_off
        entity_id: switch.pi_hole
      - delay: "00:05:00"
      - service: switch.turn_on
        entity_id: switch.pi_hole

Part 11: Backup, Restore & Migration

Teleporter Backup

Pi-hole’s built-in backup tool:

Web Interface

  1. Go to SettingsTeleporter
  2. Click Backup to download .tar.gz file
  3. Store safely off-device

Command Line

# Create backup
pihole -a -t

# Creates file like:
# pi-hole-ubuntu-teleporter_2026-01-12_20-30-00.tar.gz

Automated Backups

Add to crontab:

# Daily backup at 2am
0 2 * * * pihole -a -t && mv *.tar.gz /path/to/backup/folder/

Restoring Settings

Web Interface

  1. Go to SettingsTeleporter
  2. Click Browse under Restore
  3. Select your .tar.gz backup
  4. Click Restore

Migration to New System

  1. Backup old Pi-hole using Teleporter
  2. Install Pi-hole on new system
  3. Restore backup via Teleporter
  4. If IP changed, run: pihole -r to reconfigure

Part 12: High Availability Setup

For networks requiring redundancy.

Two Pi-hole Instances

Run two Pi-hole servers with synchronized configurations.

Configuration Sync with Nebula-Sync (Pi-hole v6+)

Since Gravity Sync is retired, use Nebula-sync for Pi-hole v6:

# Install on secondary Pi-hole
git clone https://github.com/vmstan/nebula-sync.git
cd nebula-sync
./nebula-sync.sh install

# Configure sync from primary
./nebula-sync.sh configure

Alternative: Orbital Sync (Docker)

For Docker-based deployments, Orbital Sync automates config replication:

# Add to docker-compose.yml
services:
  orbital-sync:
    image: mattwebbio/orbital-sync:latest
    environment:
      PRIMARY_HOST_BASE_URL: 'http://192.168.1.100'
      PRIMARY_HOST_PASSWORD: 'your-primary-password'
      SECONDARY_HOST_1_BASE_URL: 'http://192.168.1.101'
      SECONDARY_HOST_1_PASSWORD: 'your-secondary-password'
      INTERVAL_MINUTES: 60
    restart: unless-stopped

Orbital Sync syncs blocklists, whitelists, blacklists, and settings between Pi-hole instances hourly.

High Availability with keepalived

Use a Virtual IP (VIP) for automatic failover:

Step 1: Install keepalived

sudo apt install keepalived -y

Step 2: Configure Primary Pi-hole

sudo nano /etc/keepalived/keepalived.conf
vrrp_instance PIHOLE {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass YourSecurePassword
    }
    virtual_ipaddress {
        192.168.1.200/24  # Virtual IP
    }
}

Step 3: Configure Secondary Pi-hole

Same configuration but:

  • state BACKUP
  • priority 100

Step 4: Start keepalived

sudo systemctl enable keepalived
sudo systemctl start keepalived

Now configure your network to use 192.168.1.200 as DNS!


Part 13: Troubleshooting

Common Issues

Ads Not Being Blocked

  1. Verify DNS: Run nslookup ads.google.com - should return 0.0.0.0
  2. Check client DNS: Ensure device is using Pi-hole
  3. Browser bypass: Disable DNS-over-HTTPS in browser settings
  4. Update blocklists: Run pihole -g

Web Interface Not Loading

# Check FTL status
pihole status

# Restart FTL
pihole restartdns

# Check which port
ss -tlnp | grep pihole

High CPU/Memory Usage

# Check stats
pihole -c

# Reduce logging
pihole logging off

DNS Resolution Unavailable

# Check resolv.conf
cat /etc/resolv.conf

# Should NOT point to itself during installation
# Temporarily use: nameserver 8.8.8.8

Debug Command

# Generate debug log
pihole -d

# This creates a token you can share for support

Useful Commands Reference

CommandPurpose
pihole statusCheck if Pi-hole is running
pihole -upUpdate Pi-hole to latest version
pihole -gUpdate blocklists (gravity)
pihole restartdnsRestart DNS service
pihole -cReal-time console stats
pihole -tTail the log in real-time
pihole -dGenerate debug token for support
pihole -a -pChange admin password
pihole -b example.comAdd domain to blacklist
pihole -w example.comAdd domain to whitelist
pihole -b -d example.comRemove domain from blacklist
pihole -w -d example.comRemove domain from whitelist
pihole disable 5mDisable blocking for 5 minutes
pihole enableRe-enable blocking
pihole logging onEnable query logging
pihole logging offDisable query logging
pihole checkout core release/v6.0Switch to specific branch

Part 14: Pi-hole vs AdGuard Home

FeaturePi-holeAdGuard Home
Ease of SetupEasySlightly easier
Web InterfaceGood (AdminLTE)Modern, polished
DNS-over-HTTPSRequires setupBuilt-in
DNS-over-TLSRequires setupBuilt-in
Parental ControlsBasicAdvanced built-in
HTTPS FilteringNoYes
Resource UsageVery lowLow
CommunityLarge, activeGrowing
Open SourceYesYes

Recommendation: Pi-hole for pure ad-blocking simplicity; AdGuard Home for advanced features out-of-box.


Official Resources

ResourceURL
Pi-hole Websitepi-hole.net
Documentationdocs.pi-hole.net
GitHubgithub.com/pi-hole
Docker Hubhub.docker.com/r/pihole/pihole
Discourse Forumdiscourse.pi-hole.net
Redditr/pihole

Blocklist Resources


Conclusion

Pi-hole is an essential tool for any home network, providing network-wide ad blocking, enhanced privacy, and improved browsing performance. Whether you’re running it on a $15 Raspberry Pi Zero 2 W or in a Docker container on your NAS, Pi-hole delivers powerful protection with minimal resource overhead.

Key Takeaways:

  1. Start simple: Basic Pi-hole installation takes under 30 minutes
  2. Use quality blocklists: HaGeZi, OISD, and Firebog are excellent choices
  3. Consider Unbound: For maximum privacy, add recursive DNS
  4. VPN integration: Extend protection outside your home with WireGuard or Tailscale
  5. Backup regularly: Use Teleporter for easy backup and migration
  6. Monitor your network: The dashboard provides valuable insights

Happy ad-free browsing! 🎉


Last Updated: January 2026 | Pi-hole v6.4+ | Guide Version 1.0

Comments

Sign in to join the discussion!

Your comments help others in the community.