← All articles
NETWORKING Gluetun: Route Docker Containers Through a VPN 2026-02-09 · gluetun · vpn · docker

Gluetun: Route Docker Containers Through a VPN

Networking 2026-02-09 gluetun vpn docker privacy

Gluetun is a VPN client container that other Docker containers can route their traffic through. Instead of running a VPN on your entire server (which breaks self-hosted services that need direct connections), Gluetun lets you selectively route only the containers that need VPN access.

The typical use case: route your torrent client and *arr stack through a VPN while keeping Nextcloud, Jellyfin, and everything else on your regular connection.

Why Gluetun?

You could configure VPN connections inside individual containers, but Gluetun centralizes it:

The alternative — running OpenVPN or WireGuard inside each container — means managing multiple VPN connections, multiple configurations, and multiple potential leak points.

Installation

Basic Setup with Mullvad (WireGuard)

# docker-compose.yml
services:
  gluetun:
    image: qmcgaw/gluetun
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    ports:
      # Ports for containers using gluetun's network
      - "8080:8080"   # qBittorrent web UI
      - "6881:6881"   # qBittorrent incoming connections
    environment:
      - VPN_SERVICE_PROVIDER=mullvad
      - VPN_TYPE=wireguard
      - WIREGUARD_PRIVATE_KEY=your-private-key
      - WIREGUARD_ADDRESSES=10.x.x.x/32
      - SERVER_COUNTRIES=Switzerland
    restart: unless-stopped

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    network_mode: "service:gluetun"  # Route through Gluetun
    depends_on:
      gluetun:
        condition: service_healthy
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/Los_Angeles
    volumes:
      - qbit_config:/config
      - /data/downloads:/downloads
    restart: unless-stopped

volumes:
  qbit_config:

The key line is network_mode: "service:gluetun" — this makes qBittorrent use Gluetun's network stack. All of qBittorrent's traffic goes through the VPN tunnel.

Note that port mappings for containers using Gluetun's network go on the Gluetun container, not on the service container.

With ProtonVPN (OpenVPN)

services:
  gluetun:
    image: qmcgaw/gluetun
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    ports:
      - "8080:8080"
    environment:
      - VPN_SERVICE_PROVIDER=protonvpn
      - VPN_TYPE=openvpn
      - OPENVPN_USER=your-openvpn-user
      - OPENVPN_PASSWORD=your-openvpn-password
      - SERVER_COUNTRIES=Netherlands
    restart: unless-stopped

With a Custom WireGuard Configuration

If your provider isn't directly supported:

environment:
  - VPN_SERVICE_PROVIDER=custom
  - VPN_TYPE=wireguard
  - VPN_ENDPOINT_IP=1.2.3.4
  - VPN_ENDPOINT_PORT=51820
  - WIREGUARD_PUBLIC_KEY=server-public-key
  - WIREGUARD_PRIVATE_KEY=your-private-key
  - WIREGUARD_ADDRESSES=10.x.x.x/32

Routing Multiple Containers

Add more containers to the VPN by setting their network mode:

services:
  gluetun:
    image: qmcgaw/gluetun
    ports:
      - "8080:8080"   # qBittorrent
      - "8989:8989"   # Sonarr
      - "7878:7878"   # Radarr
      - "9696:9696"   # Prowlarr
    # ... VPN config

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    network_mode: "service:gluetun"
    depends_on:
      gluetun:
        condition: service_healthy
    # ...

  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    network_mode: "service:gluetun"
    depends_on:
      gluetun:
        condition: service_healthy
    # ...

  radarr:
    image: lscr.io/linuxserver/radarr:latest
    network_mode: "service:gluetun"
    depends_on:
      gluetun:
        condition: service_healthy
    # ...

All four containers share the single VPN connection and appear with the same public IP.

Port Forwarding

Some VPN providers (Mullvad, ProtonVPN, AirVPN) support port forwarding through the VPN. This is important for torrent clients — without an incoming port, you can only connect to peers who are connectable, reducing speeds.

environment:
  - VPN_PORT_FORWARDING=on
  - VPN_PORT_FORWARDING_PROVIDER=protonvpn

Gluetun exposes the forwarded port via its API:

curl http://localhost:8000/v1/openvpn/portforwarded

You can configure your torrent client to use this port automatically.

Verifying the VPN

Check Your External IP

From inside a container using Gluetun's network:

docker exec qbittorrent curl -s ifconfig.me

This should show the VPN server's IP, not your real IP.

Check Gluetun's Status

Gluetun has a built-in HTTP control server:

# Check public IP
curl http://localhost:8000/v1/publicip/ip

# Check VPN status
curl http://localhost:8000/v1/openvpn/status

Health Check

Gluetun includes a health check that Docker can use:

docker inspect --format='{{.State.Health.Status}}' gluetun

The depends_on condition service_healthy in our compose file ensures containers only start after the VPN is connected.

The Kill Switch

Gluetun's firewall is a kill switch by default. If the VPN connection drops:

  1. All traffic from containers using Gluetun's network is blocked
  2. Gluetun attempts to reconnect
  3. Traffic resumes only after the VPN is back up

This prevents IP leaks — your real IP is never exposed through the containers, even during VPN reconnection.

Troubleshooting

Container Can't Reach Local Network

Containers using network_mode: "service:gluetun" can't access your local network by default (all traffic goes through the VPN). To allow local access:

environment:
  - FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24

This is needed when Sonarr/Radarr need to reach Jellyfin or other services on your local network.

DNS Resolution Issues

Gluetun handles DNS through the VPN by default. If you have DNS issues:

environment:
  - DOT=off
  - DNS_ADDRESS=1.1.1.1

Slow Speeds

Gluetun vs Host-Level VPN vs Per-Container VPN

Approach Scope Complexity Leak Risk
Gluetun Selected containers Low Very low
Host VPN Entire server Medium Medium (split tunnel needed)
Per-container Individual containers High Varies

Host-Level VPN Problems

Running a VPN on the host means all traffic routes through it. This breaks:

You'd need split tunneling, which is complex and error-prone.

Gluetun's Advantage

Only containers you explicitly route through Gluetun use the VPN. Everything else is untouched. Clean separation, minimal configuration.

Verdict

Gluetun solves the "I need a VPN for some things but not everything" problem cleanly. One container, one VPN connection, and any container that needs VPN access just sets network_mode: "service:gluetun". The built-in kill switch and health checks mean you can trust it to not leak your IP.

If you're running a torrent client, *arr stack, or any other services that benefit from VPN routing, Gluetun is the standard way to do it in Docker. It's one of those tools that the self-hosting community has broadly settled on as the right solution.