Cover image for The Ultimate ad-blocker: Configuring Pi-Hole with Unbound DNS

The Ultimate ad-blocker: Configuring Pi-Hole with Unbound DNS

jldohmann profile image Jesse ・6 min read

Ads: hate 'em

If you're like me, you hate ads disrupting your internet experience and slowing down your machine. This is especially true with news sources and other traffic-heavy sites.

Like many, I have an adblocker installed on all browsers to help reduce visual clutter, but there are a few inconveniences with it:

  1. Sites know when you have an adblocker enabled for a couple reasons, one of which is because a lot of the time they hide images behind the advertisements, so when the ad is removed the image is now unhidden, which tells the site the user has an adblocker.
  2. Adblockers are cosmetic and do not prevent ads from entering the network, so it still slows down browsing, sometimes considerably in my experience.
  3. Adblockers are single-machine only! I want to protect all my devices simultaneously with the same whitelists/blacklists.

Enter: Pi-hole to the rescue!

Pi-hole: what's that?

From the GitHub project README, Pi-hole is a DNS sinkhole that protects your devices from unwanted content, without installing any client-side software.

PiHole Architecture

It works at the network-level to prevent advertisements coming in to any device that is connected to that network.

I like to think of it in terms of a bait and switch: ad sites are baited by the request made from the DNS but a switch in IP addresses has been made between the IP address of the ad site, and the one that your computer ends up seeing when you receive the response.

So what ends up happening is that your computer just sees a blank page, and the advertisement is sent to some proverbial sinkhole!

I mostly followed the normal installation process, with a few caveats:

  1. I manually downloaded the installer before running
  2. I used Unbound DNS instead of Google, Cloudflare, or the other options you can select during setup (and made some specific configuration changes)
  3. I used an existing Nginx webserver instead of Lighttpd

You don't have to do these things, but if you're interested how/why I did them, keep reading!

Setting up Pi-hole

PiHole Install Art

I won't go into how to set up a Raspberry Pi and get a static IP address here, but there many helpful articles that can guide you thru it! I am using a RPi 3 Model A+ that just sits on my desk, but you can use any Linux machine.

Raspberry Pi 3 on my desk

Like I said, I didn't do much the first time around when I set up Pi-hole, other than manually downloading the installer:

wget -O basic-install.sh https://install.pi-hole.net

Then running it in my home directory:

sudo bash basic-install.sh

This will take you thru the setup. I selected to have the web interface and server (admin portal) on, running in anonymous mode (to get aggregated anonymous statistics), and initially selected Google as the upstream DNS server.

This last selection will be changed after Unbound is installed and configured.

Once Pi-hole is set up, mosey over to /etc/pihole and create a whitelist.txt file. Initially, I just pasted this list of domains into the file, and saved it. (If you're using a RPi, you may need to sudo write to the file.)

I did a similar thing for the blocklist, using this aggregated list from Reddit.

The blocklist is updated at 5:00am CST by changing the Pi-hole cron job located in /etc/cron.d/pihole, and the whitelist is updated at 5:05am CST, setup in the system crontab located in /etc/crontab. The blocklist is provided for you, I just changed the times it pulls the new ad sources. The whitelist is what is added manually by you; those sources are pulled from here.

Lastly, I edited /etc/pihole/pihole-FTL.conf to disable long term data storage in SQLite by setting:


So all stats are wiped every morning.

Choosing the DNS

Quickly: what is DNS

I did not know much about network programming before deep-diving into setting this up with a housemate; I didn't even know what a DNS really was.

All I knew is that I use HTTP to access websites, which have a domain name (like www.google.com). I also knew that my own computer had a unique identifier in the form of an IP address that gave the green light to these websites so I could access content.

DNS stands for Domain Name System, and what I was missing was that websites have their own IP addresses, and DNS is the process of translating the domain names into those IP addresses. The way a red light turns to green, so to speak.

The DNS servers used on your computer are probably specified by your ISP (internet service provider), but you don't have to use them. How you can change them, and why you'd want to, are good questions to ask, but I won't detail them here!

Anyway, there are two types: recursive DNS servers and authoritative DNS servers. Briefly, authoritative servers can satisfy queries from their own data without needing to query another source. Google Cloud DNS is an example of this. DNS Recursive servers are like a middleman: on behalf of the client, they resolve any query by traversing the path of the domain across the Internet to deliver the answer to the question. They can cache the results to make it faster the next time around.

How DNS Works


Unbound has a really nice about page that goes in-depth about the product. Concisely, Unbound is a recursive DNS that focuses on security and privacy.

You can configure Unbound using this short guide, and then you can re-run your Pi-hole installation script to re-select the upstream DNS provider.

The last thing I did was update the configuration file located in /etc/unbound/unbound.conf.d/pi-hole.conf to do a couple of things:

  • Only let Unbound query authoritative servers (not other recursive servers). This is to prevent leaking queries to a middle man. To do this, remove these lines:
  name: "."

There are other optimizations that can be made, but they are dependent on your network environment. These are things like number of threads, message cache size, and a few others.

Using Nginx

I had already created a webserver to use as a testing ground for my webpages, so I wanted to use the same server, just a different port.

To do this, I had to install php-fpm and then alter the Nginx configuration file at /etc/nginx/site-enabled/default to parse PHP:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html index.php;

    server_name _;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404
        try_files $uri $uri/ =404;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.3-fpm.sock;

    location ~ /\.ht {
        deny all;


Pi-hole is a great out of the box piece of software to take control of your browsing experience, but it is a bit fickle to configure everything to satisfy your particular tastes.

Unfortunately, Pi-hole does block some normal websites. There is no way around it from what I can tell: there are always going to be some false positives. You'll need to keep manually updating the whitelist to deal with these as they come.

Some browsers respond better to Pi-hole than others: Chrome seems to only partially use Pi-hole, because it is given an inconsistent response time. Firefox and Safari are roughly consistent. If you use Chrome, its best to have a backup server of Cloudflare or Google, in addition to Unbound.

This setup has had me jump down more rabbit holes than I anticipated, and I learned a lot because of it. If you take the time to do the same, I believe you can learn something about network programming too! Hopefully I'll also be able to see your writeups when you're finished 😎

Posted on Mar 1 by:

jldohmann profile



Internal tools developer by day βŒ¨οΈβš™οΈ, web developer and admin by night πŸ–₯🌎. Renowned kitchen wizard πŸ‘¨β€πŸ³.


markdown guide

Isn't it that Pi-hole uses dnsmasq (a recursive DNS resolver) itself that you can point to any DNS server you want? Why the need to use another DNS resolver? Did I miss something? Maybe better would be to setup a DoH (DNS over HTTPs) to enhance the privacy?


Isn't it that Pi-hole uses dnsmasq (a recursive DNS resolver) itself

dnsmasq is a DNS forwarder that can cache results. Unbound is a recursive resolver that can also cache results. If dnsmasq doesn't have the answer, it will pass the query to the upstream DNS, which can be anything you want, including Unbound.

Maybe better would be to setup a DoH (DNS over HTTPs) to enhance the privacy?

I don't know enough to say. I think with recursion, it makes sense to minimize middle men who get the query. With DoH I think that would introduce a middle man. So my setup would go from:

client -> unbound -> authoritative DNS


client -> DoH -> Google -> authoritative DNS

So there is nothing preventing Google from storing the query, which is not something I want πŸ˜…

The GitHub issue I linked to has another link to a longer discussion for the caching optimization (which requires disabling dnsmasq caching), and may have more specifics


These are awesome! Thanks for sharing. Definitely gonna use this dark theme πŸ™‚