Pi Hole

Raspberry Pi Projects

Project 2 — Setting up a Pi-hole (Network-Wide Ad Blocker)

What you will build A network-wide DNS-based ad and tracker blocker covering every device in your home
Difficulty Beginner — one installer script does most of the work
Time to complete 30 – 60 minutes
Recommended hardware Any Raspberry Pi (even a Pi Zero W works well for this project)

What is Pi-hole?

Pi-hole is a DNS sinkhole — it acts as a DNS server for your whole network and intercepts requests for known ad-serving and tracking domains, returning nothing instead of the ad. Because it works at the DNS level, it blocks ads in every app and on every device — phones, smart TVs, game consoles, tablets — without installing anything on those devices.

📱 Your device
🍓 Pi-hole DNS
🌐 Real website
— ad request intercepted —
📱 Your device
🍓 Pi-hole DNS
🚫 ads.example.com
~20% of DNS requests are typically blocked on an average home network
100K+ domains in the default blocklist
0 apps to install on any device you want to protect

What You Will Need

🍓 Raspberry Pi Any model. A Pi Zero 2W is perfect — Pi-hole is lightweight and doesn't need much power.
💾 Raspberry Pi OS Lite The headless (no desktop) version is ideal. 8 GB SD card is more than enough.
🔌 Wired connection Ethernet is strongly recommended — your whole network depends on this Pi staying reachable.
📡 Router access You will change the DNS server setting in your router to point to your Pi. Admin credentials required.
🔒 Static local IP Your Pi must keep the same IP address. Set a DHCP reservation in your router, or configure a static IP on the Pi.
💻 SSH access All steps run in the terminal. Enable SSH in Raspberry Pi Imager before flashing.

Step 1 — Update Your Pi

Start with a clean, up-to-date system:

pi@raspberrypi:~$ sudo apt update && sudo apt upgrade -y
pi@raspberrypi:~$ sudo reboot

Reconnect via SSH after about 30 seconds.

Step 2 — Set a Static IP Address

Before installing Pi-hole, give your Pi a fixed local IP. If your router restarts and assigns the Pi a different IP, DNS will break for your whole network — so this step is important.

Option A (recommended): DHCP reservation in your router. Find the MAC address of your Pi and tell your router to always give it the same IP. The MAC address is shown by:

pi@raspberrypi:~$ ip link show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
    link/ether dc:a6:32:ab:12:34 brd ff:ff:ff:ff:ff:ff

Option B: Static IP in /etc/dhcpcd.conf (see Project 1 for the full configuration snippet).

Write down the IP you choose — you will need it when configuring your router's DNS. Something like 192.168.1.100 works well and is easy to remember.

Step 3 — Run the Pi-hole Installer

Pi-hole provides a single installer script that handles everything. The project recommends inspecting the script before running it — you can view it at install.pi-hole.net.

pi@raspberrypi:~$ curl -sSL https://install.pi-hole.net | bash

The installer launches a blue text-based setup wizard. Work through the screens:

  • Network interface: choose eth0 (wired) or wlan0 (Wi-Fi). Wired is preferred.
  • Upstream DNS provider: choose who Pi-hole asks when a domain is not blocked. See the options below — Cloudflare (1.1.1.1) is a good default choice.
  • Blocklists: accept the default StevenBlack list. You can add more lists later from the admin dashboard.
  • Admin web interface: select On. This gives you the statistics dashboard.
  • Web server (lighttpd): select On — this serves the admin interface.
  • Log queries: select On — useful for seeing what is being blocked.
  • Privacy level: Show everything gives you the most useful statistics on a home network.

At the end of the install, the wizard will display your admin dashboard URL and the randomly generated admin password. Copy this password now — you will need it to log in.

  [i] The install log is in /etc/pihole/install.log

  Pi-hole installation complete!
  ──────────────────────────────────────────────────────────
  Web interface address: http://192.168.1.100/admin
  Admin password:       a7fX92mQ           ← copy this!
  ──────────────────────────────────────────────────────────
Forgot to copy the password? You can change it any time with: pihole -a -p

Step 4 — Choose Your Upstream DNS

Pi-hole only handles blocked domains itself. For everything else it forwards the query to an upstream DNS provider. You set this during install but can change it at any time in the admin dashboard.

☁ Cloudflare
1.1.1.1  /  1.0.0.1
Fast, privacy-focused, does not log queries after 25 hours. Good all-round choice.
🔍 Google
8.8.8.8  /  8.8.4.4
Very reliable and fast. Google does collect some query data for service improvement.
🛡 Quad9
9.9.9.9  /  149.112.112.112
Blocks malicious domains at the DNS level on top of Pi-hole's blocklist. Privacy-focused, non-profit.
🏠 Your Router
192.168.1.1 (typically)
Pi-hole asks your router, which asks your ISP. Simplest setup but your ISP can see all queries.

Step 5 — Point Your Router to Pi-hole

This is the step that makes Pi-hole work for every device on your network. You need to change your router's DNS setting to use the Pi's IP address instead of your ISP's DNS servers.

  1. Log in to your router admin panel (usually http://192.168.1.1)
  2. Find the DHCP settings — not the WAN/Internet DNS, but the DNS that your router hands out to local devices
  3. Set the Primary DNS to your Pi's IP (e.g. 192.168.1.100)
  4. Set the Secondary DNS to a fallback such as 1.1.1.1 (optional — see note below)
  5. Save and apply
Should you set a secondary DNS? If you set a secondary DNS (like 1.1.1.1), devices will fall back to it if Pi-hole is unreachable — meaning they will get ads again but won't lose internet. If you leave secondary DNS blank (or set it to the same Pi IP), you get more consistent blocking but lose internet if Pi-hole goes down. On a home network, setting a secondary is the safer choice.

After saving your router settings, reconnect a device (or wait for its DHCP lease to renew) then verify it is using Pi-hole as its DNS:

# On Windows:
nslookup google.com
Server:  192.168.1.100    ← this should show your Pi's IP
Address: 192.168.1.100#53

# On Mac / Linux:
dig google.com | grep "SERVER:"
;; SERVER: 192.168.1.100#53(192.168.1.100)

Step 6 — Explore the Admin Dashboard

Open http://192.168.1.100/admin (replace with your Pi's IP) in a browser and log in with the password from Step 3.

Dashboard overview

The home screen shows your key statistics at a glance:

StatWhat it means
Queries todayTotal DNS lookups made by all devices on your network today
Queries blockedNumber (and %) of queries blocked as ads/trackers
Domains on blocklistTotal number of domains currently blocked
DNS queries / 10 minLive traffic graph — great for spotting unusual activity

Useful dashboard sections

SectionWhereWhat you can do
Query LogTools → Query LogSee every DNS request in real time — which device asked for what, and whether it was blocked
Top Blocked DomainsDashboard homeSee which ad/tracker domains are most active on your network
Top ClientsDashboard homeSee which device makes the most DNS queries
WhitelistWhitelist menuUn-block domains that Pi-hole incorrectly blocks (false positives)
BlacklistBlacklist menuManually block specific domains not on any blocklist
AdlistsGroup Management → AdlistsAdd community blocklist URLs to expand coverage
Settings → DNSSettings menuChange upstream DNS, enable DNSSEC, configure conditional forwarding

Step 7 — Add Extra Blocklists

The default StevenBlack blocklist is solid, but the community maintains many specialist lists. Add them in Group Management → Adlists in the admin dashboard, then update gravity:

pi@raspberrypi:~$ pihole -g
  [i] Pi-hole version is v5.18.3
  [i] Neutrino emissions detected...
  [✓] Pulling blocklist source list into range
  [✓] Preparing new gravity database
  [✓] Retrieving blocklist from: https://raw.githubusercontent.com/StevenBlack/hosts/...
  [✓] Storing downloaded list in temporary space
  [✓] Number of domains being pulled in by gravity: 131,818
  [✓] Gravity blocking is enabled

Popular additional lists:

ListURLFocus
StevenBlack Fakenewshttps://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hostsFake news sites
OISD (full)https://big.oisd.nlVery comprehensive; low false-positive rate
Developer Danhttps://www.github.developerdan.com/hosts/lists/ads-and-tracking-extended.txtAds & trackers extension
Energized Pornhttps://block.energized.pro/porn/formats/hosts.txtAdult content (optional parental filter)
Don't go overboard with blocklists. Very large combined lists can slow down DNS lookups and cause false positives that break websites. Start with one or two extras and add more only if needed.

Step 8 — Whitelisting and Blacklisting

Whitelisting (un-blocking a domain)

Sometimes Pi-hole blocks something it shouldn't — a streaming service CDN, a bank's security check, a game's update server. Whitelist from the command line or the admin dashboard:

pi@raspberrypi:~$ pihole -w domain.example.com
  [i] Adding domain.example.com to the whitelist...
  [✓] domain.example.com has been whitelisted

Blacklisting (blocking an extra domain)

pi@raspberrypi:~$ pihole --blacklist annoyingsite.example.com
  [i] Adding annoyingsite.example.com to the blacklist...
  [✓] annoyingsite.example.com has been blacklisted

Regex blacklisting

You can block entire patterns using regular expressions:

pi@raspberrypi:~$ pihole --regex '(.+\.)?ads\..*'
# blocks any domain matching this regex pattern

Step 9 — Keeping Pi-hole Updated

Pi-hole has its own update mechanism separate from apt:

pi@raspberrypi:~$ pihole -up
  [i] See a log of this update at: /var/log/pihole/pihole_updatecheck.log
  [✓] Pi-hole core files are up to date
  [✓] Pi-hole Web Interface files are up to date
  [✓] FTL binary is up to date

Also update your blocklists regularly to catch new ad domains:

pi@raspberrypi:~$ pihole -g     # update gravity (blocklists)

Automate blocklist updates with cron

pi@raspberrypi:~$ sudo crontab -e

Add this line to update gravity every Sunday at 03:00:

0 3 * * 0  pihole -g > /dev/null 2>&1

Optional: Enable DNSSEC

DNSSEC verifies that DNS responses haven't been tampered with in transit. Enable it in Settings → DNS → Advanced DNS settings → Use DNSSEC in the admin dashboard. Your chosen upstream DNS provider must also support DNSSEC (Cloudflare, Google, and Quad9 all do).

Optional: Enable Conditional Forwarding

By default, the Query Log shows device IP addresses (like 192.168.1.12) rather than device names (like Phillips-iPhone). Conditional forwarding tells Pi-hole to ask your router to resolve local IP addresses to hostnames.

Enable it in Settings → DNS → Advanced DNS settings → Use Conditional Forwarding and enter your router's IP and local domain (often local or home).

Troubleshooting Common Problems

⚠ Internet stops working after changing router DNS
Your Pi-hole is unreachable. Check: (1) the Pi is powered on and connected, (2) the IP address hasn't changed — this is why a static IP is essential, (3) Pi-hole's DNS service is running: pihole status. As a quick fix, revert your router DNS to its original value while you investigate.
⚠ A website or app stops working
Pi-hole is likely blocking a domain the site needs. Open Tools → Query Log in the admin dashboard and look for red (blocked) entries that appeared when you tried to use the site. Whitelist those domains: pihole -w the-blocked-domain.com. Common culprits: font CDNs, analytics endpoints used for licence checking, game anti-cheat systems.
⚠ Admin dashboard is unreachable (http://pi-ip/admin returns nothing)
The lighttpd web server may have stopped. Check and restart it: sudo systemctl status lighttpd then sudo systemctl restart lighttpd. Also verify Pi-hole itself is running: pihole status.
⚠ Blocking percentage seems very low (under 5%)
Some devices may not be using Pi-hole yet. Check Top Clients on the dashboard — are all your devices listed? Devices need to renew their DHCP lease to get the new DNS server. Force this by disconnecting and reconnecting from Wi-Fi, or running ipconfig /release && ipconfig /renew on Windows / sudo dhclient -r && sudo dhclient on Linux.
⚠ Pi-hole blocks ads on browsers but not in apps
Some apps (particularly Android apps and smart TVs) use hardcoded DNS servers (usually 8.8.8.8) and ignore your router's DNS setting. To force them through Pi-hole, add a firewall rule on your router that intercepts all UDP traffic on port 53 destined for anything other than your Pi and redirects it to your Pi. This is called "DNS hijacking" and the steps vary by router model.
⚠ Pi-hole is slow to respond / DNS lookups feel laggy
Check CPU and memory usage: htop. Also check if your blocklists have grown very large — a combined list over 2 million entries can slow down a Pi Zero. Try removing some of the larger adlists in Group Management → Adlists and re-running pihole -g. Also ensure the Pi has a reliable power supply — under-voltage causes throttling.
⚠ "Gravity database is locked" error when updating
Another Pi-hole process is already running an update. Wait a few minutes and try again. If it persists: sudo rm /etc/pihole/gravity.db-journal then re-run pihole -g.
⚠ Forgot the admin password
Reset it with: pihole -a -p — you will be prompted to enter a new password (or press Enter twice to set no password).

Quick Reference

TaskCommand
Check Pi-hole statuspihole status
Update Pi-hole softwarepihole -up
Update blocklists (gravity)pihole -g
Whitelist a domainpihole -w domain.com
Remove whitelist entrypihole -w -d domain.com
Blacklist a domainpihole --blacklist domain.com
Remove blacklist entrypihole --blacklist -d domain.com
Disable blocking (5 min)pihole disable 5m
Disable blocking (permanent)pihole disable
Re-enable blockingpihole enable
Reset admin passwordpihole -a -p
View recent queries (CLI)pihole -t (live tail)
View Pi-hole logssudo tail -f /var/log/pihole/pihole.log
Admin dashboard URLhttp://<pi-ip>/admin
Restart Pi-hole FTLsudo systemctl restart pihole-FTL
Restart web interfacesudo systemctl restart lighttpd