Why Pi-hole?
Ads aren’t just annoying — they’re a privacy leak, a bandwidth hog, and a security risk. Running Pi-hole on your network means every device gets ad-blocking without installing anything. No browser extensions, no per-device configuration. Just clean, fast, private DNS for your whole house.
And the best part? You can set it up in about 15 minutes with Docker Compose.
What You’ll Need
- A Linux machine, Raspberry Pi, or any always-on server on your network
- Docker and Docker Compose installed
- Basic familiarity with the terminal
- About 15 minutes
Step 1: Create the Project Directory
mkdir -p ~/docker/pihole && cd ~/docker/pihole
Simple enough. Keeping your Docker Compose files organized in ~/docker/ makes it easy to back up and management later.
Step 2: Write Your Docker Compose File
Create docker-compose.yml:
services:
pihole:
image: pihole/pihole:latest
container_name: pihole
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "8080:80/tcp"
environment:
TZ: "America/New_York"
WEBPASSWORD: "your-secure-password-here"
DNSMASQ_LISTENING: "all"
volumes:
- "./etc-pihole:/etc/pihole"
- "./etc-dnsmasq.d:/etc/dnsmasq.d"
cap_add:
- NET_ADMIN
Let’s break down what matters here:
- Port 53 (TCP and UDP): This is DNS. Pi-hole needs to listen on the standard DNS port to intercept queries from other devices.
- Port 8080: This maps the Pi-hole admin dashboard to port 8080 on the host (since port 80 might already be taken by Nginx or another web server).
- WEBPASSWORD: Set this to something strong. You’ll use it to log into the admin panel.
- TZ: Set your timezone. Accurate timestamps matter when you’re reading query logs.
- Volumes: These persist your blocklists, whitelist, and settings across container restarts and updates.
- NET_ADMIN: Required for Pi-hole to manage DNS properly inside the container.
Step 3: Update That Password
Seriously. Replace your-secure-password-here with an actual strong password. If you leave the default, anyone on your network can access your Pi-hole admin panel.
WEBPASSWORD: "correct-horse-battery-staple-42!"
Generate a random one if you want:
openssl rand -base64 24
Step 4: Launch It
docker compose up -d
Give it about 30 seconds to initialize. Then check that it’s running:
docker compose logs -f pihole
You should see it start up, pull blocklists, and report “FTL Started”. Hit Ctrl+C to stop following the logs.
Step 5: Test It
Before pointing your whole network at Pi-hole, verify it works on the host machine:
nslookup doubleclick.net 127.0.0.1
If Pi-hole is working, this should resolve to 0.0.0.0 — meaning the ad domain is blocked. Try a real domain too:
nslookup google.com 127.0.0.1
That should resolve normally. Ad domains get sinkholed; everything else passes through.
Step 6: Point Your Router at Pi-hole
This is the magic step. Log into your router’s admin panel and change the DNS server setting to point to your Pi-hole’s IP address.
Find your server’s local IP:
hostname -I
Then in your router’s settings (usually under Internet → DNS or LAN → DHCP), set the DNS to that IP address. Every device that gets a DHCP lease from your router will now use Pi-hole automatically.
Router doesn’t let you change DNS? No problem — you can configure devices individually, or set up Pi-hole as your DHCP server (disable the router’s DHCP and enable Pi-hole’s in Settings → DHCP on the admin panel).
Step 7: Explore the Dashboard
Open your browser to:
http://<your-server-ip>:8080/admin
Log in with your web password. You’ll see:
- Queries Blocked: The number of DNS requests Pi-hole has sinkholed.
- Percent Blocked: Usually 20-40% on a typical home network. Higher if you have smart TVs (they’re terrible for ads).
- Top Domains: See who’s phoning home the most.
- Top Blocked: The usual suspects — doubleclick.net, googlesyndication.com, and friends.
- Query Log: Real-time view of every DNS request on your network. Weirdly addictive.
Step 8: Add Blocklists (Optional but Recommended)
Pi-hole ships with a decent default blocklist, but you can add more. Go to Adlists in the admin panel and paste in URLs like:
# Steven Black's Unified List
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
# OISD Full (comprehensive, low false-positive rate)
https://big.oisd.nl/
# Anti-Amazon tracking on Fire devices
https://raw.githubusercontent.com/nextdns/metadata/master/privacy/native/amazon.txt
After adding lists, update gravity:
docker exec pihole pihole -g
Or click “Update Gravity” in the admin panel.
Word of caution: More blocklists = more blocking, but also more chance of breaking something. If a site stops working, check the query log for blocked domains and whitelist them.
Common Pitfalls
“Pi-hole works on my server but not other devices”
Most likely a firewall issue. Make sure UDP and TCP port 53 are open on the Pi-hole server:
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
“My DNS is slow after setting up Pi-hole”
Check your upstream DNS servers. In Pi-hole admin, go to Settings → DNS and pick fast upstream resolvers like Cloudflare (1.1.1.1) or Quad9 (9.9.9.9). Avoid your ISP’s default DNS — that’s half the reason you set up Pi-hole in the first place.
“Docker Compose port 53 is already in use”
On Ubuntu, systemd-resolved grabs port 53. Disable it:
sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
“I blocked something I shouldn’t have”
In the admin panel, go to Query Log, find the blocked domain, and click “Whitelist”. Problem solved in under 5 seconds.
Keeping It Updated
Pi-hole updates are straightforward:
cd ~/docker/pihole
docker compose pull
docker compose up -d
docker exec pihole pihole -up
Set up a cron job to do this weekly if you want to be hands-off:
0 3 * * 0 cd ~/docker/pihole && docker compose pull && docker compose up -d && docker exec pihole pihole -up
Going Further
Once you have Pi-hole running, you might want to explore:
- Unbound as an upstream resolver — Recursive DNS that doesn’t rely on Cloudflare or Google. True DNS privacy.
- Pi-hole + WireGuard — Route your phone’s DNS through Pi-hole even when you’re away from home. Combine with the WireGuard Docker container for a complete VPN plus ad-blocking setup.
- Custom block pages — Replace the default “blocked” page with something more fun. A pixel art cat. A rude message. Whatever brings you joy.
- DNS-over-HTTPS (DoH) blocking — Some apps bypass DNS entirely and use their own encrypted DNS. Block known DoH endpoints by IP to prevent this.
The Bigger Picture
Pi-hole is one of those rare tools that pays for itself immediately. Within the first hour, you’ll see how many devices on your network are silently phoning home to ad trackers, analytics services, and telemetry endpoints. It’s a revelation — and a little unsettling.
But here’s the thing: running Pi-hole isn’t just about blocking ads. It’s about taking back a small piece of your digital privacy with a single Docker Compose file. It’s one of the easiest, highest-impact things you can do for your home network — and it works for every device, including that smart TV that doesn’t let you install browser extensions.
Fifteen minutes of setup. Years of cleaner, faster, more private internet. That’s a trade worth making.
Leave a Reply