Why I tried routing DNS through a VPN—and why I gave up
As part of my ongoing quest to improve privacy and resilience across my self-hosted stack, I recently attempted to route all DNS traffic from my Unbound DNS resolver through Gluetun—a VPN container that acts as a gateway for other Docker containers.
The goal was simple: add another layer of privacy by ensuring DNS requests left my network encrypted and tunneled, away from prying eyes like my ISP or local network monitors.
🔎 Spoiler alert: I gave up.
🎯 The Goal
My setup includes various Docker containers, with Unbound acting as a local DNS resolver/cache and AdGuard Home handling DNS rewrites and filtering. The plan was to push Unbound’s upstream traffic through Gluetun, making sure every DNS query to the wider internet passed through a VPN tunnel.
What I wanted:
- 🔒 Encrypted DNS resolution (via DoH/DoT or VPN)
- 🚫 No DNS leaks
- 🧾 Local visibility and query logging
- ⚙️ Minimal overhead and clean container isolation
⚠️ The Problem
Gluetun is excellent at forcing traffic through a VPN tunnel, but it's also opinionated—especially when it comes to DNS. It works hard to prevent DNS leaks, but that’s exactly what made it problematic when combined with Unbound.
What I ran into:
- ❌ Unbound became unreachable inside the Gluetun container unless I exposed ports in ways that defeated Gluetun’s isolation model.
- 💣 DNS leaks were ironically hard to avoid—because patching Unbound’s connectivity meant loosening the very controls meant to protect it.
- 🧱 Gluetun’s network stack is strict—Unbound needs recursive resolution and access to root servers on port 53, which Gluetun actively tries to block.
- 🛠️ Firewall and routing tweaks only added complexity and fragility.
It started to feel like I was trying to force two tools together that just weren’t designed to cooperate.
🧵 The Workaround I Didn't Want
I considered a few compromises:
- Running Unbound outside of Gluetun, and having other containers send DNS queries through it while still routing their traffic via Gluetun.
- Using Gluetun’s built-in DoH features, bypassing Unbound completely.
But each workaround came with trade-offs:
- 🧩 Leak risk remained, unless I locked down host-level DNS completely.
- 👁️🗨️ Visibility was reduced—I’d lose local logging and control.
- 🤯 The whole setup became fragile, with too many moving parts.
🛑 Why I Gave Up
Sometimes in homelab life, the juice just isn’t worth the squeeze—and this was one of those moments.
🧠 I stepped back and asked:
"Is slightly more upstream privacy worth this complexity?"
The answer? Not for me.
✅ What I Do Instead
I pivoted to something far more sustainable:
- 🛠️ Unbound and AdGuard Home run together on the host
- 🔐 Upstream DNS is encrypted via DoT/DoH to trusted, no-log providers
- 🚷 Firewall rules restrict outbound DNS on port 53 to only Unbound
- 📊 All DNS traffic is logged and visible locally
It's not “perfect” privacy—but it’s private enough, and most importantly, reliable.
💡 Final Thoughts
Gluetun is a brilliant tool—if you're routing traffic from a torrent client, browser, or containerized app that needs VPN protection.
Unbound, on the other hand, shines best when it can operate independently, without network interference.
🔄 Trying to force them to work together turned into a constant battle between privacy, performance, and maintainability.
🧠 Lesson learned: Just because two tools are great doesn’t mean they’re meant to be used together.
If you’re building a privacy-first DNS stack:
- Let Gluetun handle VPN traffic for apps.
- Let Unbound handle DNS on the host.
- And use firewalls to keep it all tight and leak-free.
📝 Like this post?
Read more real-world DevOps and self-hosting stories at:
👉 blog.opensourceitsolutions.co.uk
#DNSPrivacy #Gluetun #Unbound #SelfHosting #Homelab #Docker #DevOps #Networking #OpenSource