Pi-hole and Unbound Setup

These are mostly notes I made for myself while setting up Pi-hole and Unbound on a new Raspberry Pi, but I figured I may as well post them here in case it helps someone out or gets them wanting to try it out.

If you’re unaware, Pi-hole is a network-wide ad blocker that works by looking at DNS queries and Unbound is a recursive DNS resolver. There’s a few benefits of running both:

Install and configure Pi-hole

Pi-hole is pretty straightforward to get up and running so I won’t go into details here. I’ve linked the install docs below, but these commands are how to obtain and run the installer.

git clone --depth 1 Pi-hole
cd "Pi-hole/automated install/"
sudo bash

After Pi-hole is installed, run this command to set the admin password for the web interface.

pihole -a -p

Pi-hole Documentation: Installation

Install and configure Unbound

You should be able to install Unbound from your distro’s package repositories.

sudo apt install unbound

Unbound may fail to start due to a port conflict with Pi-hole. Don’t worry about this because you haven’t configured it yet.

Here’s my Unbound config, which for the most part is the same config that Pi-hole gives you in their documentation about Unbound but with a few additions to add more reliance on caching which should increase performance.

# /etc/unbound/unbound.conf.d/pi-hole.conf
    # If no logfile is specified, syslog is used
    # logfile: "/var/log/unbound/unbound.log"
    verbosity: 0

    port: 5335
    do-ip4: yes
    do-udp: yes
    do-tcp: yes

    # May be set to yes if you have IPv6 connectivity
    do-ip6: no

    # You want to leave this to no unless you have *native* IPv6. With 6to4 and
    # Terredo tunnels your web browser should favor IPv4 for the same reasons
    prefer-ip6: no

    # Use this only when you downloaded the list of primary root servers!
    # If you use the default dns-root-data package, unbound will find it automatically
    #root-hints: "/var/lib/unbound/root.hints"

    # Trust glue only if it is within the server's authority
    harden-glue: yes

    # Require DNSSEC data for trust-anchored zones, if such data is absent, the zone becomes BOGUS
    harden-dnssec-stripped: yes

    # Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes
    # see for further details
    use-caps-for-id: no

    # Reduce EDNS reassembly buffer size.
    # Suggested by the unbound man page to reduce fragmentation reassembly problems
    edns-buffer-size: 1472

    # Perform prefetching of close to expired message cache entries
    # This only applies to domains that have been frequently queried
    prefetch: yes

    # One thread should be sufficient, can be increased on beefy machines. In reality for most users running on small networks or on a single machine, it should be unnecessary to seek performance enhancement by increasing num-threads above 1.
    num-threads: 1

    # Ensure kernel buffer is large enough to not lose messages in traffic spikes
    so-rcvbuf: 1m

    # Ensure privacy of local IP ranges
    private-address: fd00::/8
    private-address: fe80::/10
	# This refreshes expiring cache entries if they have been accessed with
    # less than 10% of their TTL remaining
    prefetch: yes

    # This attempts to reduce latency by serving the outdated record before
    # updating it instead of the other way around. Alternative is to increase
    # cache-min-ttl to e.g. 3600.
    cache-min-ttl: 0
	serve-expired: yes

After the Unbound config has been created, go ahead and start it.

sudo systemctl start unbound

To make sure Unbound is working, run this dig command and see if you get a response.

dig @ -p 5335

If Unbound is working, you just need to setup Pi-hole to use it as its upstream DNS server. Go into Pi-hole’s DNS settings in the web interface and set the custom DNS server to “”. Disable any other upstream DNS servers.

Pi-hole Documentation: Unbound

Run a DNS performance test

There’s a handy DNS performance test bash script that you can run to test your DNS performance and see the effects of caching.

Run the following commands to get it.

sudo apt install bc dnsutils
git clone --depth=1

Running the bash script will run several DNS speed tests using your default DNS provider (which at this point is Pi-hole + Unbound) along with other DNS servers. The first run for your setup might be slow. For me it averaged about 200ms. But repeated runs should be near instant at about 1ms.