Pi-hole plus DoH for a home network in 2026
How to run Pi-hole with dnscrypt-proxy for encrypted upstream DNS, and why most old cloudflared proxy-dns guides are stale after February 2, 2026.
Most Pi-hole DoH guides are stale now.
That is the first thing worth knowing in 2026, and it is more important than the usual "what is DNS over HTTPS?" preamble.
The stale part is not the concept. Encrypted upstream DNS is still useful. The stale part is the architecture in a lot of old tutorials, especially the ones that treat cloudflared proxy-dns as the obvious forever answer.
Cloudflare announced that the undocumented cloudflared proxy-dns command would be removed from new releases starting February 2, 2026. See the official Cloudflare changelog.
That means the practical question in April 2026 is no longer "should I add encrypted upstream DNS to Pi-hole?" It is "what is the boring, supportable way to do it now?"
The answer is: Pi-hole plus dnscrypt-proxy.
Split responsibilities cleanly
The sane architecture is simple:
- clients on your LAN use Pi-hole as their DNS server
- Pi-hole filters and caches
- a localhost stub encrypts the upstream hop to the recursive resolver
That split matters because it keeps each component honest.
Pi-hole is good at being your LAN-facing filter and cache. It does not need to become an everything-engine. The encrypted stub is good at talking securely upstream. It does not need to become your whole local resolver worldview.
This also keeps the stack easier to debug than a giant chain of cleverness.
And just as important, it clarifies what encrypted upstream DNS does not solve: it does not make the upstream resolver automatically trustworthy, and it does not erase browser-side DNS policy mistakes. That is why this topic pairs with /blog/doh-vs-dot-leak-comparison and /blog/network-opsec-checklist.
This resolver-trust point is where people often get sloppy. Encrypting the hop between your Pi-hole box and the upstream resolver prevents passive observation on that segment. It does not stop the upstream resolver from seeing the names you ask it to resolve. That means the real trust decision becomes narrower and clearer: which upstream operator do you want learning your queries, and how much do you care about local-hop exposure versus resolver exposure? The protocol only answers the first half of that.
Why dnscrypt-proxy is the sane default now
Pi-hole's own current guide is clear: if you want DoH and related encrypted upstream protocols, use dnscrypt-proxy.
That recommendation matters because it is both current and boring.
The guide also notes something operationally helpful: Debian 13 and Ubuntu 25 and later ship official dnscrypt-proxy packages through APT. That lowers the maintenance burden a lot compared with hand-assembled sidecar experiments.
This is what a good home setup should feel like:
- package-supported
- localhost-bound
- easy to restart
- easy to verify
Not "ingenious shell one-liner from a forum post."
That supportability matters more in home networks than people admit. The whole point of Pi-hole is often that other people in the house depend on it without wanting to hear a lecture about your DNS architecture. If the box reboots after an update, the design should come back up boringly. That is a better success criterion than whether the setup looked advanced on the day you installed it.
Keep port 53 for Pi-hole
The cleanest wiring choice is to let Pi-hole keep its ordinary DNS listener on port 53, then bind the encrypted stub to localhost on a different port such as 127.0.0.1:5053.
Pi-hole's guide uses a systemd socket override for exactly this reason:
[Socket]
ListenStream=
ListenDatagram=
ListenStream=127.0.0.1:5053
ListenDatagram=127.0.0.1:5053
That solves the most common self-inflicted wound in these setups: two services trying to own the same port and then producing a debugging session that should never have existed.
A minimal direction for dnscrypt-proxy
You do not need a giant resolver-shopping manifesto to get started.
A minimal direction looks like:
listen_addresses = []
server_names = ['cloudflare-security']
The details of resolver choice depend on your preferences and threat model, and the dnscrypt public server list exists if you want to compare options. But do not turn resolver shopping into the main event.
For most home networks, the valuable outcome is:
- your clients keep using one local DNS server
- Pi-hole keeps doing filtering and cache duties
- the upstream hop from Pi-hole to the recursive resolver is encrypted
That is already a solid upgrade.
Point Pi-hole at the local stub
Once dnscrypt-proxy is listening on 127.0.0.1:5053, Pi-hole should use that local stub as its upstream:
sudo pihole-FTL --config dns.upstreams '["127.0.0.1#5053"]'
sudo systemctl restart dnscrypt-proxy.socket
sudo systemctl restart dnscrypt-proxy.service
sudo systemctl restart pihole-FTL.service
That is the architecture you want:
- clients -> Pi-hole on
:53 - Pi-hole -> localhost encrypted stub on
:5053 - stub -> upstream resolver over encrypted transport
Small, understandable, supportable.
Why old cloudflared walkthroughs should go in the trash
This is not about dunking on Cloudflare. It is about freshness.
Cloudflare's changelog explicitly says the proxy-dns command is being removed from new releases starting February 2, 2026 and recommends migration to supported solutions before then.
That means tutorials still leading with "install cloudflared and run proxy-dns forever" are stale by construction.
Even if you can pin old versions, that is not the same thing as having a good long-term home-network design. It means you are building around a removed, undocumented behavior because a tutorial search result had good SEO.
That is not a plan.
If cloudflared is still installed on the box, Pi-hole's own guide says you may uninstall it if dnscrypt-proxy replaces that role, or at minimum ensure the two services use separate ports.
Again, the theme is boring correctness, not tool brand loyalty.
Verify the behavior you actually care about
Do not trust the dashboard alone. Verify each layer.
Start with simple local queries:
dig @127.0.0.1 -p 53 example.com
dig @127.0.0.1 -p 5053 example.com
You want to prove two different things:
- Pi-hole is serving clients on
:53 - the encrypted stub is alive on
:5053
Then confirm Pi-hole's upstream is really the local stub and not some forgotten direct resolver path.
It is also worth checking what the stub is bound to. Localhost binding is not just tidiness. It is the difference between "this helper process serves the local resolver stack" and "I accidentally exposed another DNS listener on the LAN." The smaller the listening surface, the fewer surprises you inherit later.
This is also where /blog/ipv6-leak-prevention becomes relevant. DNS hardening is not finished if part of your network quietly escapes over an address family or resolver path you forgot to account for.
And remember the trust model: encrypted upstream DNS hides the local hop from passive observers on the LAN or access network. It does not make the upstream resolver blind. It does not turn DoH into anonymity.
That is an improvement worth having. It is just not magic.
When this is worth doing
RouteHarden's view is simple: if you already run Pi-hole, adding a small localhost stub is worth it. Replacing your whole DNS stack because a transport acronym is fashionable usually is not.
This is especially true on home networks where the main goals are:
- local filtering
- predictable client behavior
- less plaintext DNS on the access network
- easy maintenance when the box reboots six months from now
That is why this architecture pairs well with /blog/openwrt-privacy-router. The local resolver role and the upstream encryption role should stay separate enough that you can reason about both.
The boring correct answer
In 2026, the sane Pi-hole encrypted-DNS setup is:
- Pi-hole on LAN port
53 dnscrypt-proxyon127.0.0.1:5053- Pi-hole forwarding upstream to the local stub
- easy verification with
dig
The more old tutorials you read, the more attractive that boringness should become.
Use the exact date in your own notes too: February 2, 2026 is when the old cloudflared proxy-dns assumption stopped being a safe default for new releases.
That is enough reason to stop copying stale walkthroughs and move to the supportable design now.