What is Pi-hole?
Pi-hole is a DNS sinkhole that protects devices on your network by blocking ads, trackers, and malware at the DNS level. Instead of blocking ads in your browser, Pi-hole blocks them before they reach your devices.
What you'll need
- A Linux system (Ubuntu, Raspberry Pi OS, or Debian)
- Docker and Docker Compose installed
- A static IP address (or DHCP reservation) for your Pi-hole host
- Access to your router's DNS/DHCP settings
Note: Pi-hole needs ports 53/tcp and 53/udp. If
systemd-resolvedis running on Ubuntu, see the troubleshooting section below.
Part 1: Install Docker
Update your system and install Docker:
sudo apt update && sudo apt upgrade -y
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
newgrp docker
docker --version
Install Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
Part 2: Deploy Pi-hole
Create directories for persistent data:
sudo mkdir -p /opt/pihole/etc-pihole
sudo mkdir -p /opt/pihole/etc-dnsmasq.d
sudo chown -R $USER:$USER /opt/pihole
mkdir -p ~/docker/pihole
cd ~/docker/pihole
Create docker-compose.yml (replace timezone and password):
version: '3.8'
services:
pihole:
image: pihole/pihole:latest
container_name: pihole
restart: unless-stopped
environment:
TZ: 'America/Chicago'
WEBPASSWORD: 'your_secure_password_here'
DNS1: '1.1.1.1'
DNS2: '8.8.8.8'
volumes:
- '/opt/pihole/etc-pihole:/etc/pihole'
- '/opt/pihole/etc-dnsmasq.d:/etc/dnsmasq.d'
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp"
cap_add:
- NET_ADMIN
Start Pi-hole:
docker-compose up -d
docker-compose logs -f pihole
Wait for: dnsmasq: listening on
Verify
docker ps --filter name=pihole
hostname -I
Open the admin UI at http://<your-ip>/admin/ and log in with your password.
Part 3: Point your network to Pi-hole
Option A — Router DHCP (recommended)
- Log into your router admin panel
- Find DNS settings under WAN or DHCP
- Set Primary DNS to your Pi-hole IP (e.g.
192.168.1.50) - Set Secondary DNS to
1.1.1.1as fallback - Save and renew client leases
Option B — Per-device DNS
Set DNS manually on each client to the Pi-hole IP.
Verify from a client
nslookup google.com <pi-hole-ip>
Check the Pi-hole Query Log — you should see blocked and allowed queries.
Part 4: Maintenance
Add blocklists
- Pi-hole admin → Adlists
- Add:
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts - Click Update Gravity
Update Pi-hole
cd ~/docker/pihole
docker-compose pull
docker-compose up -d
Troubleshooting: port 53 already in use
Check what's using port 53:
sudo ss -lntup | grep ':53 ' || true
sudo ss -lnup | grep ':53 ' || true
If systemd-resolved is the blocker:
sudo nano /etc/systemd/resolved.conf
Set:
DNSStubListener=no
Apply:
sudo systemctl restart systemd-resolved
sudo rm -f /etc/resolv.conf
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
docker restart pihole