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