Pidiylab Logo

Pidiylab Title

Private Recursive DNS with Unbound & Pi-hole on Raspberry Pi

Published:

Updated:

Author:

Private recursive dns with unbound & pi hole on raspberry pi

Disclaimer

As an affiliate, we may earn a commission from qualifying purchases. We get commissions for purchases made through links on this website from Amazon and other third parties.

Introduction

Ever get the feeling your internet knows a little too much about you? Yeah, same here. Every time you load a webpage, your device throws out a request like it’s shouting, “Hey, where’s google.com live?” And guess who’s listening? Your ISP, third-party DNS providers, maybe even that free coffee shop Wi-Fi you regretted using last week.

Now, imagine rerouting those nosey queries to your own private recursive DNS resolver running on a Raspberry Pi. That’s where Unbound steps in. Pair it with Pi-hole acting as an upstream filter, and you’ve got a setup that blocks ads, skips trackers, and never sends DNS logs to someone else’s servers. It’s your network traffic, your rules. Plus, it’s surprisingly light on resources—even that dusty Pi Zero in your drawer can handle it.

Key Takeaways

  • Unbound provides private, recursive DNS with full DNSSEC validation
  • Pi-hole filters ads and telemetry, works as Unbound’s front-end
  • Use root hints instead of forwarders for total independence
  • Binding to 127.0.0.1 keeps queries local and safe
  • Regular updates and log checks prevent surprises

Choosing the Right Hardware and OS

Look, not all Raspberry Pis are created equal. You might think any old board will do, but if you’re planning to run Unbound with Pi-hole, there’s a sweet spot between power, heat, and “wait, why is nothing resolving?”

Raspberry Pi 4B is the crowd favorite. It’s got enough RAM to handle DNS cache, run Unbound without choking, and still give Pi-hole its share. Got a Pi Zero 2 W lying around? That’ll work too, just don’t expect blazing speeds with a hundred devices hammering it.

For OS, stick with Raspberry Pi OS Lite if you want something reliable and low on fluff. DietPi is even lighter if you’re feeling adventurous, and Ubuntu Server 22.04 is rock solid if you’re into that LTS life.

Here’s a quick table to compare:

ModelRAMUse CaseNotes
Raspberry Pi 4B2–8GBMain serverGreat balance of power/efficiency
Pi Zero 2 W512MBLight usage, backup resolverNeeds passive cooling
Pi 3B+1GBMedium load, basic home useGets warm under stress
Pi 4004GBDesktop + DNS comboBuilt-in keyboard, stays cool

Spoiler alert: If you’re still using a Pi 1, stop reading and go fix your life.

Installing Unbound on Raspberry Pi

All right, let’s get Unbound actually doing something. You’ve got your Raspberry Pi booted up, SSH’d in, and probably already wondering if this is going to brick your internet. (It won’t—probably.)

Start by updating your packages. Depending on your OS, it’ll look something like this:

sudo apt update && sudo apt install unbound

Now, Unbound needs a list of root DNS servers to get going. This isn’t optional—without it, it’s like asking for directions without a map.

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

Make sure Unbound is using this hints file by referencing it in /etc/unbound/unbound.conf. You’ll need to open it up and actually write the config. Here’s the minimal bit to make it behave:

server:
    verbosity: 0
    interface: 127.0.0.1
    port: 5335
    do-ip4: yes
    do-udp: yes
    do-tcp: yes
    root-hints: "/var/lib/unbound/root.hints"

Notice that port 5335? That’s because Pi-hole likes to hog port 53, so we give Unbound its own little corner.

Now check the service:

sudo systemctl enable unbound
sudo systemctl start unbound

And see if it’s alive:

dig @127.0.0.1 -p 5335 google.com

If it returns an IP? Congrats. You’re resolving like a grown-up.

Configuring Unbound for Recursive Resolution

Okay, so Unbound’s installed—but now it needs to act like a proper recursive resolver, not some clueless middleman. That means answering DNS queries by walking the whole DNS chain itself, not just phoning a friend (aka upstream forwarders).

Pop open the unbound.conf file again:

sudo nano /etc/unbound/unbound.conf

And update it with more advanced goodies:

server:
    verbosity: 0
    interface: 127.0.0.1
    port: 5335
    do-ip4: yes
    do-udp: yes
    do-tcp: yes
    root-hints: "/var/lib/unbound/root.hints"
    hide-identity: yes
    hide-version: yes
    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: yes
    qname-minimisation: yes
    cache-min-ttl: 3600
    cache-max-ttl: 86400
    prefetch: yes
    prefetch-key: yes
    val-clean-additional: yes
    aggressive-nsec: yes
    val-permissive-mode: no
    rrset-roundrobin: yes
    serve-expired: yes
    serve-expired-ttl: 86400
    do-not-query-localhost: no

    auto-trust-anchor-file: "/var/lib/unbound/root.key"

Then initialize DNSSEC (the digital signature checking system that keeps spoofers out of your DNS business):

sudo unbound-anchor -a /var/lib/unbound/root.key

Restart Unbound to let it soak all that in:

sudo systemctl restart unbound

What you’ve got now is a recursive DNS resolver that does its own dirty work, follows the root servers, and won’t ask Google or Cloudflare what 1.1.1.1 actually means.

Also: it’s not logging queries unless you tell it to, and it’s validating DNSSEC signatures, which means it knows when something smells phishy.

Setting Up Pi-hole to Use Unbound

Now that Unbound is strutting around like a DNS boss, it’s time to let Pi-hole know who’s in charge. And spoiler alert—it ain’t your ISP’s DNS anymore.

Fire up the Pi-hole Admin Web Interface, head to Settings > DNS, and in the Custom section at the bottom, enter this:

127.0.0.1#5335

That #5335 tells Pi-hole to send DNS queries to Unbound’s port, not the usual 53. They don’t share well, so we keep ’em separated like roommates with bad history.

Make sure to uncheck all other upstream DNS providers (Google, Cloudflare, etc.) if you want true recursive DNS without outside help. Otherwise, you’re just adding another middleman.

Now scroll down and hit Save. Give it a test:

dig pi-hole.net

Watch the results flow through Unbound via Pi-hole. If you see something like Query time: 50 msec, congrats—your local recursive DNS resolver is doing its job.

Extra settings to double-check:

  • DNSSEC: Enable it in the Pi-hole GUI to show validated lookups.
  • Conditional Forwarding: Turn it OFF unless you like leaking internal domain traffic back to your router.
  • Logs: Optional, but if you’re nosey like me, keep logging enabled just to peek at what’s resolving.

Now both systems are talking like old friends: Unbound handles the legwork, and Pi-hole slaps down ads and trackers with a smirk.

Performance Optimization

Let’s be honest—nobody likes slow DNS. Especially when you’re the one who set it up. Thankfully, Unbound isn’t just secure—it’s snappy, if you tell it how to behave.

Start with these cache-related settings in your unbound.conf:

    cache-min-ttl: 3600
    cache-max-ttl: 86400
    prefetch: yes
    serve-expired: yes
    serve-expired-ttl: 86400
  • cache-min-ttl keeps answers for at least an hour
  • cache-max-ttl stretches out those good results for a full day
  • prefetch grabs popular queries before they expire
  • serve-expired makes Unbound answer from cache even if the record is a little stale (better than a timeout)

Next, pump up the storage a bit:

    rrset-cache-size: 256m
    msg-cache-size: 128m

These bump the memory allocated to DNS results. If you’ve got a Raspberry Pi with more than 1GB RAM, use it. Your future self will thank you when 30 devices start asking about cdn.facebook.net at the same time.

You can also control verbosity:

    log-queries: no
    verbosity: 0

Unless you enjoy watching your logs fill with 10,000 queries for TikTok, turn this off. It keeps the Pi-hole logs clean too, since Pi-hole only shows what Unbound passes back.

Want to go full paranoid? Add:

    minimal-responses: yes
    hide-identity: yes
    hide-version: yes

These tell Unbound to mind its own business and not tell outsiders what version you’re running or who you are.

Securing the Resolver

You’ve built a DNS setup that works—but does it work for everyone on the internet? It shouldn’t. Unless you want to become the world’s slowest public DNS, it’s time to lock things down.

Limit Unbound to Localhost

This part’s already done if you used the default config:

    interface: 127.0.0.1

This makes sure only Pi-hole on the same device can talk to Unbound. Nobody else on your network (or the internet) should be able to query it.

Access Control Lists

Want to be extra sure? Add an explicit rule:

    access-control: 127.0.0.0/8 allow
    access-control: ::1 allow
    access-control: 0.0.0.0/0 refuse
    access-control: ::0/0 refuse

This says, “Local IPs? Fine. Everything else? Get lost.”

Rate Limiting

If someone does find your DNS port, slow them down:

    ratelimit: 1000
    ip-ratelimit: 200

That’ll make Unbound throttle abuse instead of melting under load.

Run as Unprivileged User

By default, Unbound should drop root privileges:

    username: "unbound"

Don’t skip this. If Unbound ever gets compromised (unlikely, but still), it can’t trash your whole system.

Systemd Hardening

You can make it even tighter by editing the service unit:

sudo systemctl edit unbound

Add:

[Service]
ProtectSystem=full
ProtectHome=yes
PrivateTmp=yes
NoNewPrivileges=true

This limits Unbound’s access to parts of the filesystem it doesn’t need.

Monitoring and Logs

You’ve got a slick DNS setup—so now what? You watch it like a hawk, obviously. DNS breaks quietly, so you need to know what’s happening before your spouse says, “Why isn’t the internet working again?”

Check Logs the Old-Fashioned Way

journalctl -u unbound
tail -f /var/log/pihole.log
tail -f /var/log/pihole-FTL.log

Use Pi-hole’s Dashboard

The web UI under Query Log and Long-term Data shows:

  • Who requested what
  • Which domains got blocked
  • Whether queries came from Unbound or another upstream

Third-Party Tools That Play Nice

  • Netdata – Lightweight dashboard with DNS stats
  • Grafana + Prometheus – Custom dashboards
  • vnStat, iftop, nload – Bandwidth tracking

Don’t Forget Rotation

Log files get big fast. Use logrotate to keep things clean and avoid SD card death.

Troubleshooting Tips

All right, so things went sideways. DNS won’t resolve, your spouse is glaring at you, and even the dog looks disappointed. Here’s how to fix your Frankenstein setup without rage-quitting back to Google DNS.

  • Check service status: sudo systemctl status unbound
  • Test Unbound directly: dig @127.0.0.1 -p 5335 google.com
  • Test DNSSEC:
  dig sigfail.verteiltesysteme.net @127.0.0.1 -p 5335
  dig sigok.verteiltesysteme.net @127.0.0.1 -p 5335
  • Fix DNSSEC with:
  sudo unbound-anchor -a /var/lib/unbound/root.key
  • Flush cache:
  sudo unbound-control flush_zone .
  • Restart Unbound:
  sudo systemctl restart unbound

Home Network Configuration

You’ve got Unbound resolving DNS and Pi-hole filtering like a champ—but none of that matters if your devices are still asking the router for directions.

  • Change router’s DHCP DNS to your Pi-hole IP
  • Or disable router DHCP and enable Pi-hole’s DHCP server
  • Set a static IP in /etc/dhcpcd.conf
  • Add local DNS records in Pi-hole web UI
  • Use Gravity Sync or Teleporter for redundancy

Maintenance and Community Help

Let’s be real—this setup’s not exactly “set it and forget it.”

Stay Updated

sudo apt update && sudo apt upgrade unbound
pihole -up

Backup with Teleporter from Pi-hole GUI to save:

  • Blocklists
  • Whitelists
  • Local DNS records
  • DHCP settings

Join the Nerd Herd

Don’t Sleep on Logs

journalctl -u unbound --since "7 days ago"

Check regularly to catch issues early.

Frequently Asked Questions (FAQ)

Q: Can I use Unbound without Pi-hole?
Yes, but you’ll lose ad-blocking and filtering.

Q: Do I need DNSSEC in both Unbound and Pi-hole?
Only Unbound handles validation. Pi-hole just displays the status.

Q: What happens if Unbound fails?
Pi-hole won’t resolve domains. Restart or use a temporary fallback DNS.

Q: Is this setup faster than using 1.1.1.1 or 8.8.8.8?
Yes, once caching kicks in. First query might be slower.

Q: Can I run this setup with other services on the same Pi?
Yes, as long as resources aren’t maxed out.

References

Was this helpful?

Yes
No
Thanks for your feedback!

About the author

Latest Posts

Pi DIY Lab