How to Install Unbound with Pi-hole (Full DNS Privacy Guide)

Pi-hole Unbound DNS Privacy Home Lab

If you’re already running Pi-hole, adding Unbound is the next major upgrade.
Unbound turns your Raspberry Pi into a local recursive DNS resolver, which means:

  • No reliance on Google, Cloudflare, or other DNS providers
  • Stronger privacy
  • Faster DNS after caching
  • Complete control of your DNS pipeline

This guide explains exactly how to install Unbound, integrate it with Pi-hole, and verify everything is working.


1. What is Unbound (in simple words)?

Normally, Pi-hole forwards DNS requests to an upstream server:

  • 1.1.1.1 (Cloudflare)
  • 8.8.8.8 (Google)
  • Quad9
  • etc.

With Unbound, your Pi becomes the resolver.

Instead of asking another DNS provider, Unbound:

  1. Starts at the DNS root servers
  2. Resolves step by step
  3. Caches results locally
  4. Serves DNS privately inside your home

This makes your network faster and far more private.


2. Requirements

  • A Raspberry Pi with Pi-hole installed
  • Raspberry Pi OS Lite (recommended)
  • Terminal access (SSH)

Works perfectly with:

  • Pi-hole as DNS only
  • Bell Giga Hub handling DHCP
  • Any home-lab setup

3. Install Unbound

Update system

sudo apt update && sudo apt upgrade -y

Install Unbound

sudo apt install unbound -y

This installs the Unbound service and default config.


4. Create a custom Unbound config for Pi-hole

Create the file:

sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf

Paste this:

server:
    verbosity: 0
    interface: 127.0.0.1
    port: 5335
    do-ip4: yes
    do-ip6: no
    do-udp: yes
    do-tcp: yes

    do-not-query-localhost: no

    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: yes

    prefetch: yes
    num-threads: 1

    msg-cache-size: 50m
    rrset-cache-size: 100m

    root-hints: "/var/lib/unbound/root.hints"

    hide-identity: yes
    hide-version: yes

Save and exit.


5. Download root DNS hints

sudo wget https://www.internic.net/domain/named.root -O /var/lib/unbound/root.hints

Ensure directory exists:

sudo mkdir -p /var/lib/unbound

Run wget again if needed.


6. Restart Unbound

sudo systemctl restart unbound

Check:

sudo systemctl status unbound

7. Configure Pi-hole to use Unbound

Open:

http://<PI_IP_ADDRESS>/admin

Go to:

Settings → DNS

  • Uncheck all upstream servers
  • Add custom:
127.0.0.1#5335

Save.


8. Test Unbound

Run a basic resolution test:

dig google.com @127.0.0.1 -p 5335

You will get a verbose response. The key things to confirm:

  • status: NOERROR — Unbound resolved successfully
  • SERVER: 127.0.0.1#5335 — The query went through Unbound on the correct port

Your output will look similar to this:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
google.com.    300    IN    A    142.250.74.14
...
;; SERVER: 127.0.0.1#5335(127.0.0.1) (UDP)

DNSSEC validation test:

dig sigfail.verteiltesysteme.net @127.0.0.1 -p 5335

This domain has an intentionally broken DNSSEC signature. The expected result is:

status: SERVFAIL

SERVFAIL means Unbound detected the bad signature and correctly rejected it — this is the right behaviour. If you see NOERROR, DNSSEC validation is not active. If you get a timeout, Unbound cannot reach the internet (see Troubleshooting below).


9. Optional: Improve Unbound performance

Edit:

sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf

Add:

cache-max-ttl: 86400
neg-cache-size: 25m

Restart:

sudo systemctl restart unbound

10. Troubleshooting

Unbound not listening

sudo lsof -i :5335

No internet

sudo systemctl restart unbound

Logs:

sudo journalctl -u unbound --no-pager

DNSSEC test times out

This means Unbound cannot reach the authoritative DNS servers on the internet. Check whether outbound DNS queries are being blocked by your firewall:

dig . NS @198.41.0.4

If this also times out, the issue is outbound UDP/TCP port 53 being blocked on your Pi — not an Unbound config problem. Check your firewall rules.

Network stops working after pointing Pi-hole to Unbound

First, confirm both services are running:

systemctl status unbound
systemctl status pihole-FTL

Then check for a resolver loop:

cat /etc/resolv.conf

If it shows nameserver 127.0.0.1, DNS queries may be looping back to Pi-hole before reaching Unbound. Make sure do-not-query-localhost: no is present in your pi-hole.conf (included in Step 4 above) and restart Unbound:

sudo systemctl restart unbound

Also verify in Pi-hole Admin → Settings → DNS that all default upstream providers are unchecked and only 127.0.0.1#5335 is set.


11. Summary

You now have:

  • Pi-hole blocking ads + trackers
  • Unbound resolving DNS locally
  • Full DNS privacy
  • Faster queries over time
  • Complete control of your network

This is the best possible home DNS setup you can build with a Raspberry Pi.