How to Install Unbound with Pi-hole (Full DNS Privacy Guide)
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:
- Starts at the DNS root servers
- Resolves step by step
- Caches results locally
- 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.