Three Network Zones

Every container lives in exactly one zone. Download traffic is encrypted, management traffic stays private, and streaming gets direct hardware access.

Zone 1

VPN Tunnel

All download traffic encrypted through WireGuard. Kill switch with iptables DROP — if the tunnel drops, nothing leaks.

Gluetun VPN Gateway Transmission :9091 SABnzbd :8080
Zone 2

Docker Bridge

Private bridge network for all management and automation services. Containers discover each other by name — no exposed ports needed internally.

Radarr :7878 Sonarr :8989 Lidarr :8686 Prowlarr :9696 Bazarr :6767 Seerr :5055 QuestArr :5002 FlareSolverr :8191 LazyLib :5299 Kavita :5004 Audiobookshelf :13378
Zone 3

Host Network

Direct host network access for DLNA/UPnP discovery and hardware transcoding (VA-API, NVENC). No network isolation — full LAN visibility.

Jellyfin :8096

VPN Kill Switch

Gluetun enforces a strict kill switch using iptables. If the WireGuard tunnel drops, all outbound traffic from download clients is blocked — zero leaks, zero exceptions.

1
Tunnel drops WireGuard connection lost
2
Client tries to send Transmission/SABnzbd attempts outbound
3
BLOCKED by iptables Default policy: DROP all non-tunnel traffic
4
Zero unencrypted traffic No packets bypass the tunnel
5
Tunnel re-establishes Gluetun reconnects automatically
6
Downloads resume Traffic flows through tunnel again
How iptables enforces this

Gluetun sets the default OUTPUT chain policy to DROP, then adds explicit ACCEPT rules only for traffic going through the tun0 interface (the WireGuard tunnel). If tun0 goes down, no rules match — everything is dropped. This is a whitelist approach: only tunnel traffic is allowed, everything else is denied by default.

Search vs Download Traffic

Not all traffic needs VPN protection. Search queries are harmless metadata lookups — it's the actual file downloads that need encryption.

Search Traffic

Direct (no VPN)
Arr apps Indexer sites

Radarr, Sonarr, Lidarr, and Prowlarr query indexers over HTTPS. These are simple API calls — "does this release exist?" — and reveal nothing about what you actually download.

Download Traffic

VPN Encrypted
Transmission / SABnzbd WireGuard tunnel

Actual file transfers go through Gluetun's WireGuard tunnel. Torrent and Usenet traffic involves direct connections to external servers — encrypting this protects your privacy.

Why search doesn't need VPN

Searching an indexer is like checking a catalog — it returns metadata, not content. The HTTPS connection already encrypts the query. VPN-routing search traffic would add latency and reduce reliability for no benefit. Downloads are different: you're transferring actual files and making direct connections to external servers, so VPN encryption provides meaningful privacy protection.

DNS Routing

Each zone resolves DNS differently. VPN traffic uses tunnel DNS, bridge services use Docker's resolver, and the host uses your router.

VPN Zone
Transmission & SABnzbd Gluetun DNS Cloudflare 1.1.1.1

DNS queries route through the VPN tunnel to prevent DNS leaks and ensure consistent name resolution.

Bridge Zone
Arr apps Docker DNS 127.0.0.11 1.1.1.1 / 8.8.8.8

Docker's built-in DNS resolver handles container name resolution, then forwards external queries to Cloudflare and Google.

Host Zone
Jellyfin Router DNS 192.168.1.254

Running on the host network, Jellyfin uses your router's DNS — same as any other device on your LAN.

Cross-Zone Connections

Services in different zones still need to talk to each other. Docker's bridge network and shared network namespaces make this possible.

Bridge ↔ VPN

Arr apps (Zone 2) send downloads to Transmission and SABnzbd (Zone 1) through Gluetun's shared network namespace. Radarr talks to gluetun:9091 — Gluetun proxies the connection to Transmission inside the tunnel.

Bridge ↔ Host

Bridge containers reach Jellyfin (Zone 3) via the Docker host gateway. Jellyfin accesses arr APIs using the host's IP on their mapped ports.

Service Discovery

Within the Docker bridge, containers resolve each other by name — radarr, sonarr, prowlarr — thanks to Docker's embedded DNS at 127.0.0.11. No hardcoded IPs needed.