01Why Route Containers Through VPN?
Some self-hosted services benefit from VPN routing:
**Use cases:**
• **Torrenting**: Hide your IP from peers and trackers
• **Geo-unblocking**: Access region-restricted content
• **Privacy**: Prevent services from leaking your IP
• **Split tunneling**: Only route specific containers
**Gluetun** is the go-to solution—a lightweight container that connects to 60+ VPN providers and routes traffic for other containers through it.
Gluetun supports WireGuard and OpenVPN, with WireGuard being faster and more efficient.
02Basic Gluetun Setup
Gluetun connects to your VPN provider and exposes a network that other containers can use. Configuration varies by provider—check the Gluetun wiki for your specific provider.
**Supported providers include:**
Mullvad, NordVPN, Surfshark, ProtonVPN, PIA, Windscribe, and 60+ more.
Here's a setup for Mullvad (WireGuard):
1services: 2 gluetun: 3 image: qmcgaw/gluetun:latest4 container_name: gluetun5 cap_add: 6 - NET_ADMIN7 devices: 8 - /dev/net/tun:/dev/net/tun9 environment: 10 - VPN_SERVICE_PROVIDER=mullvad11 - VPN_TYPE=wireguard12 - WIREGUARD_PRIVATE_KEY=${MULLVAD_PRIVATE_KEY}13 - WIREGUARD_ADDRESSES=10.x.x.x/3214 - SERVER_COUNTRIES=Sweden15 volumes: 16 - ./gluetun:/gluetun17 ports: 18 # Ports for containers using this VPN19 - 8080:8080 # qBittorrent20 - 6881:6881 # Torrent port21 restart: unless-stoppedThe NET_ADMIN capability is required for VPN functionality. This gives the container elevated network privileges.
03Routing Containers Through the VPN
To route a container's traffic through Gluetun, use `network_mode: service:gluetun`. This makes the container share Gluetun's network stack—all its traffic goes through the VPN.
**Important:** When using network_mode, ports must be exposed on the Gluetun container, not the service itself.
1services: 2 gluetun: 3 image: qmcgaw/gluetun:latest4 cap_add: 5 - NET_ADMIN6 devices: 7 - /dev/net/tun:/dev/net/tun8 environment: 9 - VPN_SERVICE_PROVIDER=mullvad10 - VPN_TYPE=wireguard11 - WIREGUARD_PRIVATE_KEY=${MULLVAD_PRIVATE_KEY}12 - WIREGUARD_ADDRESSES=10.x.x.x/3213 - SERVER_COUNTRIES=Sweden14 ports: 15 - 8080:8080 # qBittorrent WebUI16 - 9696:9696 # Prowlarr17 restart: unless-stopped1819 qbittorrent: 20 image: linuxserver/qbittorrent:latest21 container_name: qbittorrent22 network_mode: service:gluetun23 depends_on: 24 gluetun: 25 condition: service_healthy26 environment: 27 - PUID=100028 - PGID=100029 volumes: 30 - ./qbittorrent:/config31 - /downloads:/downloads32 # NO ports here - they go on gluetun!33 restart: unless-stopped3435 prowlarr: 36 image: linuxserver/prowlarr:latest37 network_mode: service:gluetun38 depends_on: 39 - gluetun40 volumes: 41 - ./prowlarr:/config42 restart: unless-stoppedUse depends_on with condition: service_healthy to ensure the VPN is connected before starting dependent containers.
04Kill Switch and Leak Prevention
Gluetun has a built-in kill switch—if the VPN disconnects, all traffic is blocked. This prevents IP leaks. You can also configure allowed IPs for local network access.
**Kill switch behavior:**
• Blocks all traffic if VPN disconnects
• Prevents DNS leaks (uses VPN's DNS)
• Can whitelist local network ranges
**Verify your setup:**
1. Check your public IP from inside the container
2. Disconnect VPN and verify traffic is blocked
3. Test DNS to ensure no leaks
1# Check your IP from inside a VPN-routed container2docker exec qbittorrent curl -s https://ipinfo.io/ip34# Compare to your real IP5curl -s https://ipinfo.io/ip67# Check DNS (should show VPN provider's DNS)8docker exec qbittorrent cat /etc/resolv.conf910# Test kill switch: stop gluetun and try to connect11docker stop gluetun12docker exec qbittorrent curl -s https://ipinfo.io/ip13# Should fail/timeout05Split Tunneling: Selective VPN Routing
Not all services need VPN routing. Use split tunneling to route only specific containers through the VPN while others use your regular connection.
**Architecture:**
• Services needing privacy → network_mode: service:gluetun
• Regular services → Normal Docker networking
• Services talking to VPN'd containers → Shared network
The key is understanding that VPN-routed containers can only communicate with containers in their same network stack.
1services: 2 gluetun: 3 image: qmcgaw/gluetun:latest4 cap_add: 5 - NET_ADMIN6 devices: 7 - /dev/net/tun:/dev/net/tun8 environment: 9 - VPN_SERVICE_PROVIDER=mullvad10 - VPN_TYPE=wireguard11 - WIREGUARD_PRIVATE_KEY=${MULLVAD_PRIVATE_KEY}12 - WIREGUARD_ADDRESSES=10.x.x.x/3213 # Allow local network access14 - FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/2415 ports: 16 - 8080:808017 networks: 18 - vpn_network19 restart: unless-stopped2021 # Through VPN22 qbittorrent: 23 image: linuxserver/qbittorrent:latest24 network_mode: service:gluetun25 depends_on: 26 - gluetun27 volumes: 28 - ./qbittorrent:/config29 - /downloads:/downloads3031 # NOT through VPN - normal networking32 jellyfin: 33 image: jellyfin/jellyfin:latest34 ports: 35 - 8096:809636 volumes: 37 - ./jellyfin:/config38 - /media:/media:ro39 networks: 40 - vpn_network # Can access gluetun services4142networks: 43 vpn_network: Use FIREWALL_OUTBOUND_SUBNETS to allow VPN-routed containers to access your local network (like for NAS access).
06VPN Port Forwarding for Better Speeds
Some VPN providers support port forwarding, which improves torrent speeds by allowing incoming connections. Gluetun can automatically configure this.
**Providers with port forwarding:**
• ProtonVPN (paid plans)
• Private Internet Access
• Mullvad (limited)
• AirVPN
When enabled, Gluetun requests a forwarded port and writes it to a file or updates container environment variables.
1services: 2 gluetun: 3 image: qmcgaw/gluetun:latest4 cap_add: 5 - NET_ADMIN6 devices: 7 - /dev/net/tun:/dev/net/tun8 environment: 9 - VPN_SERVICE_PROVIDER=private internet access10 - VPN_TYPE=openvpn11 - OPENVPN_USER=${PIA_USER}12 - OPENVPN_PASSWORD=${PIA_PASS}13 - SERVER_REGIONS=Netherlands14 # Enable port forwarding15 - VPN_PORT_FORWARDING=on16 - VPN_PORT_FORWARDING_PROVIDER=protonvpn17 volumes: 18 - ./gluetun:/gluetun19 ports: 20 - 8080:808021 restart: unless-stopped2223# The forwarded port is available at:24# /gluetun/forwarded_port25# Or via the control server: http://localhost:8000/v1/openvpn/portforwarded07Troubleshooting VPN Containers
Common issues and solutions when running containers through VPN:
**Container can't connect to internet:**
• Check Gluetun logs for VPN connection errors
• Verify credentials and server settings
• Ensure /dev/net/tun device exists
**Can't access container WebUI:**
• Ports must be on Gluetun, not the service
• Check firewall rules in Gluetun
**Slow speeds:**
• Try a different server/country
• Use WireGuard instead of OpenVPN
• Enable port forwarding if available
**Container starts before VPN:**
• Use depends_on with health check condition
1# Check Gluetun status2docker logs gluetun34# Check if VPN is connected5docker exec gluetun curl -s https://ipinfo.io67# Test connectivity from a routed container8docker exec qbittorrent ping -c 3 google.com910# Check Gluetun health11curl http://localhost:8000/v1/vpn/status1213# Restart with fresh connection14docker compose restart gluetunIf Gluetun fails to connect, dependent containers will have no network access. Always use health checks and monitoring.