
How to Block Ads Across Your Whole Network with Pi-hole DNS?
Browser ad blockers work well on a laptop, but they do nothing for the smart TV that shows banner ads in its menus, the phone game that loads trackers between levels, or the tablet a guest brings over. Pi-hole takes a different approach: instead of filtering inside each browser, it sits on your network as the DNS server and refuses to resolve domains known to serve ads and tracking. Every device that uses it is covered automatically, with no software to install on any of them. It is a hands-on, home-network version of the DNS filtering that companies use to block malware.
This guide explains how Pi-hole blocks ads at the DNS level, how to install it on a Raspberry Pi, a Linux box, or in Docker, how to point your network at it, how to stop devices from bypassing it, how to add an upstream recursive resolver, and how to fix the occasional site it breaks.
How Pi-hole Blocks Ads with DNS
Before any device can load an ad from ads.example-network.com, it has to resolve that hostname to an IP address. Pi-hole acts as your network's DNS server and checks every query against a set of blocklists (collectively called gravity).
- If the domain is on a blocklist, Pi-hole answers immediately with an unroutable address — by default
0.0.0.0for IPv4 and::for IPv6. The device tries to connect to nowhere, fails instantly, and the ad slot stays empty. - If the domain is allowed, Pi-hole forwards the query to an upstream resolver, caches the answer, and returns it as normal.
This technique is called a DNS sinkhole. Because it works on hostnames, it blocks ads and trackers in apps, smart TVs, and IoT devices just as well as in browsers. The trade-off is that it cannot block an ad served from the same domain as the content you want, because blocking that domain would block the content too.
What You Need
- A device that is always on: a Raspberry Pi (any model from the Pi 3 onward is plenty), a small Linux server, a virtual machine, or any machine that can run Docker.
- A static IP address on your LAN for that device, for example
192.168.1.2. Every client will be told to use this address for DNS, so it must not change. Set it with a DHCP reservation on your router or a static configuration on the device. - Access to your router's admin panel to change the DNS server it hands to clients.
Pi-hole is lightweight. It handles the DNS traffic of a busy household on a fraction of a Raspberry Pi's CPU and memory.
Step 1: Install Pi-hole
You can install Pi-hole directly on the operating system or run it as a container. Pick whichever fits the machine you have.
Option 1: Install with the Official Script
On Raspberry Pi OS, Debian, Ubuntu, or Fedora, the official installer sets up everything:
curl -sSL https://install.pi-hole.net | bash
The installer asks which network interface to use, which upstream DNS provider to forward to, and whether to install the web interface. If you prefer to read a script before running it, download it first:
curl -sSL https://install.pi-hole.net -o basic-install.sh
less basic-install.sh
sudo bash basic-install.sh
At the end, the installer shows the admin URL and a generated password. Set your own password with:
sudo pihole setpassword
That command applies to Pi-hole v6, the current major version, which consolidated its configuration into /etc/pihole/pihole.toml and ships its own built-in web server. Older v5 installs used pihole -a -p for the same task.
Option 2: Run Pi-hole in Docker
If the machine already runs other services, Docker keeps Pi-hole isolated. Create a docker-compose.yml:
services:
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "8080:80/tcp"
environment:
TZ: "Europe/London"
FTLCONF_webserver_api_password: "change-me-to-something-long"
FTLCONF_dns_listeningMode: "all"
volumes:
- "./etc-pihole:/etc/pihole"
restart: unless-stopped
Start it with docker compose up -d. This publishes DNS on port 53 over both UDP and TCP, exposes the web interface on port 8080 of the host, and stores configuration and blocklists in ./etc-pihole so they survive container upgrades. The FTLCONF_ variables map directly onto settings in pihole.toml; dns.listeningMode set to all is needed because, inside Docker's network, queries do not appear to come from the local subnet.
On Ubuntu, the host's systemd-resolved stub listener may already occupy port 53. If docker compose up fails with "address already in use", disable the stub by setting DNSStubListener=no in /etc/systemd/resolved.conf and running sudo systemctl restart systemd-resolved.
Step 2: Test Pi-hole Before Pointing Your Network at It
Query Pi-hole directly from another machine before changing anything on the router:
# A normal domain should resolve
dig @192.168.1.2 example.com A +short
# A well-known ad domain should be sinkholed
dig @192.168.1.2 doubleclick.net A +short
# 0.0.0.0
If the first returns an IP and the second returns 0.0.0.0, Pi-hole is filtering correctly. You can also check from the Pi itself whether a domain is on any list:
pihole -q doubleclick.net
This searches your blocklists and allow and deny lists and shows which list matched. Using dig for DNS lookups covers more query options if you need to troubleshoot.
Step 3: Point Your Network at Pi-hole
There are two ways to make every device use Pi-hole.
Method A: Change the DNS Server Your Router Hands Out
In your router's DHCP or LAN settings, set the DNS server given to clients to 192.168.1.2. Devices pick up the change when they renew their DHCP lease, or immediately if you reconnect them to Wi-Fi.
Two details matter:
- Do not add a public resolver as a secondary DNS. Clients do not treat a "secondary" as a fallback; many use both interchangeably, so ads will leak through whenever the public server answers first.
- Prefer the LAN DHCP setting over the WAN DNS setting. If you only change the router's own upstream DNS, every query reaches Pi-hole from the router's IP and you lose per-device statistics.
Router interfaces vary a lot; the guide on changing DNS servers on your router walks through the options, including routers that do not allow you to change the DHCP DNS setting at all.
Method B: Let Pi-hole Run DHCP
If your router will not let you change the DNS server it advertises, disable DHCP on the router and enable Pi-hole's built-in DHCP server in its web interface (Settings, then DHCP). Pi-hole will then hand out addresses and advertise itself as the DNS server. Set the gateway to your router's IP and choose an address range that does not overlap with any static devices.
If you only want to cover a single device rather than the whole network, you can set its DNS manually instead; see how to change DNS settings on Windows, Mac, iPhone, and Android.
Step 4: Choose and Manage Blocklists
Pi-hole ships with a default blocklist that covers common ad and tracking domains. You can add more lists in the web interface under Lists (Adlists in v5) by pasting the list URL, then rebuild gravity:
pihole -g
pihole -g downloads every configured list, deduplicates the domains, and loads them into the database. It runs automatically once a week.
More lists are not always better. Huge aggregated lists block more trackers but also break more legitimate sites. A sensible approach is to start with the default list, add one or two well-maintained lists, and expand only if you still see ads you care about.
Step 5: Fix What Gets Broken
Every DNS-level blocker eventually blocks something you need: a shopping link that routes through a tracking domain, a streaming app that refuses to start, or a login flow that depends on an analytics endpoint. To find the culprit:
- Open the Query Log in the web interface and filter by the affected device's IP.
- Reproduce the problem and look for blocked domains (shown in red) at that moment.
- Allow the domain that is clearly related to the broken feature.
You can allow or block domains from the command line as well:
pihole allow tracking.example-shop.com
pihole deny telemetry.example-tv.com
These are the v6 commands; on v5 the equivalents are pihole -w and pihole -b. For temporary troubleshooting, pihole disable 5m turns blocking off for five minutes and pihole enable turns it back on.
Stopping Devices from Bypassing Pi-hole
Some devices ignore the DNS server your network provides.
- Hardcoded DNS. Some streaming sticks, smart TVs, and apps send queries directly to a public resolver such as
8.8.8.8. On routers that support it (OpenWrt, pfSense, OPNsense), add a firewall rule that redirects all outbound port 53 traffic not coming from Pi-hole back to Pi-hole, or simply blocks it. - Browser DNS over HTTPS. Browsers with DNS over HTTPS enabled send queries over port 443 to their own resolver, skipping Pi-hole entirely. Pi-hole answers Mozilla's canary domain
use-application-dns.netwith NXDOMAIN by default, which stops Firefox from enabling DoH automatically, but a user who turns DoH on manually will still bypass it. Chrome only upgrades to DoH when the system's resolver is a known DoH-capable provider, which a Pi-hole on a private IP is not. - IPv6. If your router advertises its own IPv6 DNS server through router advertisements, clients may send queries there instead. Either configure the router to advertise Pi-hole's IPv6 address or let Pi-hole handle it.
- VPNs and private relays. VPN apps and services like iCloud Private Relay use their own DNS by design. That is expected and not something to fight.
Optional: Use Unbound as a Private Recursive Upstream
By default, Pi-hole forwards allowed queries to a public resolver of your choice. If you would rather not send your browsing history to any single third party, run Unbound on the same machine as a full recursive resolver that talks directly to the root, TLD, and authoritative servers.
sudo apt install unbound
Create /etc/unbound/unbound.conf.d/pi-hole.conf:
server:
interface: 127.0.0.1
port: 5335
do-ip4: yes
do-udp: yes
do-tcp: yes
do-ip6: no
harden-glue: yes
harden-dnssec-stripped: yes
use-caps-for-id: no
edns-buffer-size: 1232
prefetch: yes
num-threads: 1
Restart Unbound and test it:
sudo systemctl restart unbound
dig @127.0.0.1 -p 5335 example.com A +short
Then, in Pi-hole's DNS settings, clear the public upstream servers and set a custom upstream of 127.0.0.1#5335. Unbound listens only on localhost, validates DNSSEC, and caches answers, so after the first lookup of a domain responses are as fast as any public resolver. The Pi-hole documentation's Unbound guide has the full recommended configuration.
Keeping Pi-hole Healthy
- Update regularly. Run
pihole -upon bare-metal installs, or pull the new image and recreate the container in Docker. - Back up your configuration. Use Teleporter in the web interface to export settings, lists, and allow and deny entries.
- Plan for downtime. If Pi-hole goes offline, every device loses DNS. Some households run a second Pi-hole and advertise both addresses, keeping them in sync with a tool such as nebula-sync.
- Check the dashboard. A blocked percentage between 10 and 30 is typical for a home network. A sudden spike from one device can indicate a misbehaving app or malware.
Pi-hole FAQ
Generally no. YouTube serves most video ads from the same domains as the videos themselves, so blocking them at the DNS level would block the videos too. Browser-based blockers handle YouTube better.
Usually not. Pi-hole caches answers locally and blocked domains return instantly, so pages often load faster because ad and tracker requests never happen. The first lookup of a new domain takes as long as your upstream resolver.
No. Pi-hole runs on most Debian, Ubuntu, and Fedora systems, in a virtual machine, or in Docker on any host. A Raspberry Pi is popular simply because it is cheap, quiet, and low power.
The ads are either served from the same domain as the content, the device is bypassing Pi-hole with hardcoded DNS or DNS over HTTPS, or the ad domain is not on your blocklists. Check the Query Log to see whether the device is querying Pi-hole at all.
Not a public one. Clients use secondary servers interchangeably, so ads will leak through. If you want redundancy, run a second Pi-hole and advertise both.
Devices that only use Pi-hole for DNS will be unable to resolve names, so the internet will appear down. Running a second instance or keeping a quick way to switch the router back to another DNS server avoids this.
Yes, if you add blocklists that include malicious domains. It is not a full security product, but it adds a useful layer that works for every device on the network.
Yes. Pi-hole answers over IPv6 and returns :: for blocked AAAA queries. Make sure your router advertises Pi-hole's IPv6 address, or clients may send IPv6 DNS queries elsewhere.
Conclusion
Pi-hole turns a cheap, always-on device into a network-wide ad and tracker blocker by doing one thing well: answering DNS queries for unwanted domains with an address that goes nowhere. Install it with the official script or Docker, give it a static IP, test it with dig, and then make it the only DNS server your router hands to clients. From that point, every phone, TV, console, and laptop on your network benefits without any per-device setup.
The ongoing work is small but real. Tune your blocklists rather than piling them on, allow the occasional domain a site legitimately needs, close the bypass routes such as hardcoded DNS and IPv6 router advertisements, and keep Pi-hole updated and backed up. Add Unbound if you want to stop relying on a third-party resolver entirely, and you end up with a faster, quieter, and more private network.
Here are some useful references for going deeper on Pi-hole:
- Pi-hole Documentation: Pi-hole docs — official installation, configuration, and troubleshooting guides.
- Pi-hole Documentation: Unbound as a recursive resolver — the recommended Unbound configuration for use with Pi-hole.
- GitHub: pi-hole/docker-pi-hole — the official Docker image with environment variable reference.
- Mozilla Support: Canary domain use-application-dns.net — how networks can signal Firefox not to enable DNS over HTTPS automatically.
- Unbound Documentation: unbound.conf reference — every option used in the Unbound configuration above.


