DEV Community

Cover image for Pi-hole with Unbound: Private Recursive DNS Explained
NXVL
NXVL

Posted on Originally published at nxvalue.com

Pi-hole with Unbound: Private Recursive DNS Explained

Most "private DNS" setups only move your trust around. You stop asking your ISP and start asking Google, Cloudflare, or Quad9 instead. Pi-hole with Unbound goes a step further: block unwanted domains first, then resolve everything else yourself, with no public resolver in the middle.

This guide explains how the two pieces fit together, how to build the setup on your own server, and what it does and does not protect.

The two pieces

Pi-hole is a DNS filter. Your devices ask it for a domain name, and it checks the request against your blocklists. If the domain is an ad network, tracker, or telemetry endpoint, Pi-hole answers with "nothing here" and the connection never starts. It also keeps a query log, so you can see which device asked for what.

Unbound is a recursive DNS resolver. A normal setup forwards your questions to a big public resolver that does the work for you. Unbound does the work itself: it starts at the DNS root servers, follows the chain to the .com servers, then to the domain's own authoritative servers, and caches the answer. It also validates DNSSEC signatures, so forged answers are rejected.

Put together, the flow looks like this:

Your device
   │  (DoT / DoH, encrypted)
   ▼
Pi-hole        → blocked? answer immediately, nothing leaves the server
   │  (allowed)
   ▼
Unbound        → recursive lookup + DNSSEC validation + cache
   │
   ▼
Root → TLD → authoritative servers
Enter fullscreen mode Exit fullscreen mode

Why not just forward to Cloudflare or Quad9?

Forwarding is fast and simple, and for many people it is a fine choice. The trade-off is that one company sees the full list of domains you look up, from every device, tied to your IP address.

With Unbound as the upstream:

  • No single resolver sees your whole history. Each authoritative server only sees the question it is responsible for, such as "what is the address of example.com?".
  • You do not depend on a third party's uptime or policy. Nobody can change filtering or logging rules underneath you.
  • DNSSEC is checked on your own server, not trusted from someone else's answer.

Option A: Build it yourself

These steps assume a small Debian or Ubuntu server with Pi-hole already installed.

1. Install Unbound

sudo apt update
sudo apt install unbound
Enter fullscreen mode Exit fullscreen mode

2. Configure it to listen only on localhost

Create /etc/unbound/unbound.conf.d/pi-hole.conf:

server:
    verbosity: 0

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

    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: no
    edns-buffer-size: 1232

    prefetch: yes
    num-threads: 1

    private-address: 192.168.0.0/16
    private-address: 172.16.0.0/12
    private-address: 10.0.0.0/8
Enter fullscreen mode Exit fullscreen mode

Port 5335 keeps Unbound out of Pi-hole's way on port 53. Binding to 127.0.0.1 means nothing outside the server can talk to it directly. The private-address lines stop Unbound from returning answers that point into your private network, which helps against DNS rebinding.

Restart it:

sudo systemctl restart unbound
Enter fullscreen mode Exit fullscreen mode

3. Test Unbound on its own

dig example.com @127.0.0.1 -p 5335
Enter fullscreen mode Exit fullscreen mode

You should get an answer with status: NOERROR. Now check that DNSSEC validation works:

dig sigfail.verteiltesysteme.net @127.0.0.1 -p 5335
dig sigok.verteiltesysteme.net @127.0.0.1 -p 5335
Enter fullscreen mode Exit fullscreen mode

The first must return SERVFAIL (a deliberately broken signature, correctly rejected). The second must return NOERROR.

4. Point Pi-hole at Unbound

In the Pi-hole web interface:

  1. Go to Settings → DNS.
  2. Untick every public upstream (Google, Cloudflare, and so on).
  3. Under Custom DNS servers, add 127.0.0.1#5335.
  4. Save.

From now on, anything Pi-hole allows is resolved by Unbound.

5. Encrypt the path from your devices

Plain DNS between your phone and your server is readable by anyone on the network path. To fix that, expose your Pi-hole over DoT (port 853) or DoH (port 443) using a TLS-terminating proxy in front of it, such as stunnel, nginx, or dnsdist, with a valid certificate for a hostname you own. Then use that hostname in Android's Private DNS setting or the equivalent on iOS and macOS.

Expect to spend most of your time on this step: certificates, renewals, firewall rules, and keeping the proxy updated.

Option B: Let a managed node do it

If you want the same architecture without the maintenance, NxValue Stack provisions a private Pi-hole + Unbound node for you. It is not a shared public resolver: it is your own isolated server running open-source Pi-hole and Unbound, configured for you alone.

  • Unbound runs as a DNSSEC-validating recursive resolver on your node.
  • DoH and DoT endpoints are generated for you, so you paste one hostname into Private DNS and you are done.
  • The dashboard shows live queries and blocked domains per device, and you can export or delete your data at any time.
  • Billing is hourly and you can cancel anytime. The BASE-N plan is $4/month.

You can try the demo node here.

Some limits to this setup

  • Encrypted DNS stops your ISP and local network from reading your DNS lookups, but they can still see the IP addresses you connect to

  • The first lookup of a domain can be slower.Recursion has to walk the chain of servers. Caching and prefetch hide most of this after a short warm-up.

  • Authoritative servers still see your server's IP. They just cannot see a complete profile of you the way a single big well-known forwarder like Google/CF would.

  • DNS blocking is not a full ad blocker. First-party ads, such as video ads on YouTube or Twitch, come from the same domains as the content and cannot be separated at the DNS level. Pair Pi-hole with a browser content blocker for full coverage.

Summary

  • Pi-hole decides what gets resolved. Unbound decides how, without a public resolver.
  • Self-hosting gives you full control, at the cost of setting up TLS, certificates, and maintenance.
  • A managed private node gives you the same stack with encrypted endpoints ready in about a minute.
  • Either way, the result is DNS that blocks trackers, validates DNSSEC, and does not funnel your history into one large resolver.

Pi-hole is a registered trademark of Pi-hole LLC. NxValue Stack is an independent service provider and is not affiliated with Pi-hole LLC.

Top comments (0)