Pi-hole: Network-Wide Ad Blocking

← Self-Hosting · Security & Privacy · Replaces: per-device ad blockers, your ISP's DNS

What You'll Build

Every device looks up names like ads.example.net before loading anything. Pi-hole answers those lookups for your whole network and simply refuses the ones on ad and tracker blocklists. Result: fewer ads and trackers on phones, smart TVs, and consoles, with nothing installed on them.

Ports: 53 (DNS), 8081 (web admin) · Time: 30 minutes · Difficulty: Easy

Pi-hole and AdGuard Home do the same job and both need port 53. Install one, not both. Pi-hole has the bigger community; AdGuard Home has built-in encrypted DNS and wildcard rewrites.

What You Need

Step 1: Free Up Port 53 (Ubuntu)

Ubuntu runs its own small DNS helper on port 53. Turn that listener off so Pi-hole can use the port:

# Check what's on port 53
sudo ss -lntup | grep ':53 '

# Turn off systemd-resolved's stub listener (keeps a backup of the file as .orig)
sudo sed -r -i.orig 's/#?DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf

# Point the server's own lookups at the real resolver file
sudo sh -c 'rm /etc/resolv.conf && ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf'
sudo systemctl restart systemd-resolved

Step 2: Start Pi-hole

mkdir -p ~/stacks/pihole && cd ~/stacks/pihole
nano compose.yaml
services:
  pihole:
    image: pihole/pihole:latest
    container_name: pihole
    restart: unless-stopped
    ports:
      - "53:53/tcp"          # DNS
      - "53:53/udp"          # DNS
      - "8081:80/tcp"        # web admin (80 is taken by Nginx Proxy Manager)
    environment:
      TZ: "America/New_York"
      FTLCONF_webserver_api_password: "choose-a-strong-password"
      FTLCONF_dns_listeningMode: "all"     # answer devices on the whole network
    volumes:
      - ./etc-pihole:/etc/pihole           # settings, lists, query history
    cap_add:
      - SYS_NICE                           # lets Pi-hole give itself priority
docker compose up -d
sudo ufw allow 53     # allow DNS from your network

# Test: this should return an IP address…
dig @192.168.1.50 example.com +short
# …and this known ad domain should return 0.0.0.0
dig @192.168.1.50 doubleclick.net +short

(No dig? sudo apt install dnsutils.) Open http://192.168.1.50:8081/admin and log in.

Step 3: Make Every Device Use It

  1. Log in to your router → LAN / DHCP settings → set DNS server to 192.168.1.50. Remove any second DNS server (devices would use it to skip Pi-hole).
  2. Reconnect a device to Wi-Fi (or reboot it) so it picks up the change.
  3. Browse for a minute, then check the Pi-hole dashboard: queries and a "blocked" percentage should be climbing.

If the server goes down, name lookups on your network stop and "the internet is broken". Keep Pi-hole's host reliable, or add a second Pi-hole on a Raspberry Pi and hand out both addresses.

Step 4: Blocklists and Allowlisting

Step 5: Local Names for Your Apps

Make *.home.example.com resolve to your server even if your router blocks it (see the reverse proxy note):

  1. Settings → All settings (switch to Expert mode) → Miscellaneous → misc.dnsmasq_lines.
  2. Add this line → Save & Apply:
# Every name ending in home.example.com → the home server
address=/home.example.com/192.168.1.50

Add It to Your Proxy, Dashboard, and Backups

Troubleshooting

What's Next?

Use Pi-hole on your phone away from home by setting it as your Tailscale DNS server — see Remote Access.

Home Assistant: a smart home without the cloud →