Gluetun — One VPN Container to Route Them All

Gluetun logo and wordmark

If you run qBittorrent, Prowlarr, Sonarr and friends in Docker, the standard advice is to give each one its own VPN connection. That works, but it’s wasteful and hard to manage. Gluetun is a lightweight VPN client container that acts as a network gateway — every container that needs VPN protection just borrows its network stack instead of running its own tunnel.

One tunnel. One set of credentials. One place to check if something isn’t connecting.

VPN Provider
Mullvad / PIA / etc
WireGuard endpoint

WireGuard tunnel

gluetun
  • Interface: wg0
  • Kill-switch: iptables — ON
  • Ports exposed: 8080, 6881, 9696…

network_mode: container:gluetun

Docker network (vpn_net)
qBittorrent
Prowlarr
Sonarr
Radarr
SABnzbd
cross-seed

Port forwarding: VPN provider assigns an external port → Gluetun → qBittorrent


What you need before you start

  • A VPN subscription that supports WireGuard (Mullvad, PIA, ProtonVPN, AirVPN, and many others)
  • Your provider’s WireGuard private key — generated from your provider’s dashboard
  • The VPN endpoint address and port (e.g. 198.54.128.1:51820)
  • Your assigned internal VPN IP (e.g. 10.66.44.2/32)
  • The server’s public key

All of these come from your provider’s “Generate WireGuard config” page. Download a .conf file — everything you need is in it.

Mullvad tip: Go to Account → WireGuard configuration → Generate key → Download config. Pick a server that supports port forwarding if you want qBittorrent to accept incoming connections.


The Gluetun Docker Compose file

Create /mnt/tank/stacks/gluetun/docker-compose.yml:

services:
  gluetun:
    image: qmcgaw/gluetun:latest
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    ports:
      # qBittorrent web UI
      - 8080:8080
      # qBittorrent torrent port
      - 6881:6881
      - 6881:6881/udp
      # Prowlarr
      - 9696:9696
      # Add ports for any other containers sharing this network
    environment:
      - VPN_SERVICE_PROVIDER=mullvad        # change to your provider
      - VPN_TYPE=wireguard
      - WIREGUARD_PRIVATE_KEY=YOUR_PRIVATE_KEY_HERE
      - WIREGUARD_ADDRESSES=10.66.44.2/32   # your assigned VPN IP
      - SERVER_COUNTRIES=Netherlands         # or Sweden, Switzerland, etc.
      # Optional: lock to a specific city or hostname
      # - SERVER_CITIES=Amsterdam
      # - WIREGUARD_PUBLIC_KEY=SERVER_PUBLIC_KEY
      # - VPN_ENDPOINT_IP=198.54.128.1
      # - VPN_ENDPOINT_PORT=51820
      # Port forwarding (Mullvad / PIA)
      - VPN_PORT_FORWARDING=on
      - VPN_PORT_FORWARDING_PROVIDER=mullvad
    volumes:
      - /mnt/tank/configs/gluetun:/gluetun
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "/gluetun-entrypoint", "healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 3

Environment variables explained

Variable What it does
VPN_SERVICE_PROVIDER Your VPN provider slug (mullvad, pia, protonvpn, airvpn, etc.)
VPN_TYPE Use wireguard — faster and simpler than OpenVPN
WIREGUARD_PRIVATE_KEY Your WireGuard private key from the provider dashboard
WIREGUARD_ADDRESSES The internal IP assigned to you by the VPN (from the .conf file)
SERVER_COUNTRIES Which country to connect to. Gluetun picks the best server automatically
VPN_PORT_FORWARDING Enable port forwarding (needed for good torrent speeds on some providers)

Security note: Never commit WIREGUARD_PRIVATE_KEY to git. Store it in a .env file alongside the compose file and reference it as ${WIREGUARD_PRIVATE_KEY}.


Connecting other containers

This is the key part. Any container that should route through the VPN uses network_mode: "container:gluetun" instead of declaring its own ports. It piggybacks entirely on Gluetun’s network interface — same IP, same routing table, same kill-switch.

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    network_mode: "container:gluetun"   # <-- this is all you need
    environment:
      - PUID=568
      - PGID=568
      - WEBUI_PORT=8080
    volumes:
      - /mnt/tank/configs/qbittorrent:/config
      - /mnt/tank/downloads:/downloads
    restart: unless-stopped
    depends_on:
      gluetun:
        condition: service_healthy

  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    container_name: prowlarr
    network_mode: "container:gluetun"
    environment:
      - PUID=568
      - PGID=568
    volumes:
      - /mnt/tank/configs/prowlarr:/config
    restart: unless-stopped
    depends_on:
      gluetun:
        condition: service_healthy

A few things to note:

  • No ports: on the child containers — all port mappings go on the Gluetun service, since that’s the one with the actual network interface.
  • depends_on: condition: service_healthy — this makes the container wait until Gluetun has a working VPN connection before starting. Essential for the kill-switch to work on startup.
  • Containers can reach each other via localhost — because they share the same network namespace, qBittorrent and Prowlarr can talk to each other on 127.0.0.1.

The kill-switch

Gluetun uses iptables to block all traffic that doesn’t go through the VPN tunnel. If the WireGuard connection drops, the containers sharing its network simply lose internet access rather than falling back to your real IP. No leaks.

The CAP_NET_ADMIN capability and /dev/net/tun device are required for this — Gluetun needs to create the network interface and set the firewall rules.


Port forwarding

Some VPN providers (Mullvad, PIA, AirVPN) can assign you a port on their server that forwards through to your container. This is important for qBittorrent — without an open port you can connect to peers but they can’t initiate connections to you, which kills your ratio on private trackers.

With VPN_PORT_FORWARDING=on, Gluetun writes the forwarded port to /gluetun/forwarded_port. You can read this file with a small script and push the port into qBittorrent’s API automatically.

# Check your current forwarded port
cat /mnt/tank/configs/gluetun/forwarded_port

Verifying it works

# Check Gluetun is connected
docker logs gluetun | grep -i "ip|connected|port"

# Check qBittorrent is using the VPN IP (not your home IP)
docker exec qbittorrent curl -s ifconfig.me

# Should return your VPN provider's IP, not your home IP

If the IP matches your VPN provider, everything is working. If it returns your home IP, Gluetun isn’t connected or the container isn’t using network_mode: "container:gluetun" correctly.

Avatar photo

By admin

One thought on “Gluetun — One VPN Container to Route Them All”

Leave a Reply

Your email address will not be published. Required fields are marked *