Running Your Own Recursive DNS Resolver on Raspberry Pi with Unbound: Full DNS Privacy Beyond Pi-hole
This site's Pi-hole guides cover network-wide ad blocking — Pi-hole intercepts DNS requests and blocks known ad/tracker domains, but it still forwards legitimate lookups upstream to a resolver like Google DNS or Cloudflare, meaning that upstream provider still sees every domain you visit. Running your own recursive resolver with Unbound does something different: instead of forwarding queries anywhere, your Raspberry Pi talks directly to the DNS root servers and walks the delegation chain itself for every lookup. No third party — not your ISP's DNS, not Google, not Cloudflare — sees your browsing pattern in aggregate. This guide covers setting up Unbound on a Raspberry Pi, and — the more common real-world setup — chaining it behind Pi-hole so you get ad-blocking and full recursive resolution together.
How Recursive Resolution Differs From a Forwarder
A typical DNS "resolver" you configure — 1.1.1.1, 8.8.8.8, your ISP's DNS — is a forwarding (caching) resolver: it takes your query and passes it to another resolver, which does the real work and hands back an answer, and every one of those upstream operators can log which domains you're resolving, even without seeing the actual page content over HTTPS. A recursive resolver skips that middleman: it starts at the 13 root server clusters, gets referred to the correct top-level-domain server (.com, .org, etc.), gets referred again to the domain's authoritative nameserver, and gets the final answer directly from the source. No single party in that chain sees your full browsing pattern — each server only sees one piece of a much larger picture, and the authoritative server for the exact domain you're visiting is generally already expecting that traffic.
What You Give Up
This isn't a strictly-better replacement for a public forwarder — it's a genuine trade-off, worth stating plainly before you commit an hour to setup:
- Slightly slower first-lookup times — walking the full delegation chain for an uncached domain takes longer than asking a resolver that already has it cached from millions of other users. Unbound's own caching mostly erases this after the first visit to any given site.
- No DNS-based content filtering from a third party — if you relied on your upstream provider's malware/phishing blocklist, you lose that unless you add it yourself (Pi-hole handles this layer instead, see below).
- You become responsible for keeping it running — a public resolver has no downtime you need to worry about; your Pi does.
Installing Unbound
sudo apt update sudo apt install unbound -yUnbound ships with a sensible default root hints file and works as a recursive resolver out of the box, but a few settings are worth setting explicitly in /etc/unbound/unbound.conf.d/pi-recursive.conf:
server: interface: 127.0.0.1 port: 5335 do-ip4: yes do-udp: yes do-tcp: yes prefetch: yes cache-min-ttl: 3600 cache-max-ttl: 86400 harden-glue: yes harden-dnssec-stripped: yes use-caps-for-id: yes edns-buffer-size: 1232 qname-minimisation: yesBinding to a non-standard port (5335 here) rather than the default 53 is deliberate — it leaves port 53 free for Pi-hole to bind to, which is the setup most people actually want (see below). qname-minimisation is a meaningful privacy improvement on its own: it sends only the minimum necessary portion of a domain name to each server in the delegation chain, rather than the full query, so intermediate servers see even less of what you're resolving.
Chaining Behind Pi-hole (the Setup Most People Want)
Running Unbound standalone gives you privacy but loses Pi-hole's ad/tracker blocking. Running them together gives you both: Pi-hole handles blocklist filtering and serves as your network's DNS server on port 53, then forwards anything not blocked to Unbound running locally on port 5335 for full recursive resolution — instead of forwarding to a public DNS provider.
- Install and configure Unbound as above, bound to 127.0.0.1:5335.
- Test it directly: dig @127.0.0.1 -p 5335 example.com should return a valid answer.
- In the Pi-hole admin interface, go to Settings → DNS, uncheck all the default upstream providers, and under "Custom DNS servers (IPv4)" enter 127.0.0.1#5335.
- Save, then run a lookup from a client on your network and confirm it resolves — Pi-hole's query log will show the request being filtered against blocklists and then resolved through Unbound.
Verifying DNSSEC and Confirming It's Actually Working
Unbound validates DNSSEC by default, which protects against a resolver being fed forged answers for a domain that publishes DNSSEC records. Confirm it's active:
dig @127.0.0.1 -p 5335 sigfail.verteiltesysteme.net dig @127.0.0.1 -p 5335 sigok.verteiltesysteme.netThe first (intentionally broken DNSSEC signature) should return SERVFAIL; the second (valid signature) should resolve normally. If the first one resolves instead of failing, DNSSEC validation isn't actually working and is worth troubleshooting before you trust the setup.
Performance and Monitoring
Unbound's cache means most repeat lookups are effectively free after the first resolution. On a Raspberry Pi 4 or 5, recursive resolution for an uncached domain typically adds well under a second versus a cached public forwarder response — noticeable on the very first visit to a brand-new domain, unnoticeable for nearly everything else in normal browsing. Check unbound-control stats for cache hit rate and query volume if you want to confirm it's keeping up with your household's DNS load; a Pi 4 or better handles typical home traffic without strain.
Pi-hole plus Unbound is a meaningfully different privacy posture than Pi-hole alone — it removes the single biggest remaining party (your upstream DNS provider) that could otherwise see every domain your network visits, at the cost of a small first-lookup delay and one more service to maintain on hardware you already have running.
Related Guides
- How to Install and Configure Pi-hole on Raspberry Pi
- Running Pi-hole on a Raspberry Pi Zero 2W
- Pi-hole Setup: Network-Wide Ad Blocking
- Backing Up Self-Hosted Services on Raspberry Pi with Restic and Borg
- Self-Hosting Syncthing on a Raspberry Pi: Real-Time File Sync Without the Cloud
- Self-Host Your Photos with Immich: A Local Google Photos Alternative
- Self-Hosting Jellyfin Media Server on a Raspberry Pi: Hardware Transcoding and Remote Access
- How to Install Klipper on Any 3D Printer: Complete Setup Guide