gluetun + qBittorrent
Use these steps to run gluetun (VPN client) with qBittorrent routed through it using Docker Compose.
gluetun handles the VPN connection (WireGuard in this guide), and qBittorrent runs in gluetun's network namespace so all its traffic goes through the VPN tunnel.
Create the Compose File
Create a docker-compose.yml file with both services:
services:
gluetun:
image: qmcgaw/gluetun:latest
container_name: gluetun
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
ports:
- "8080:8080/tcp"
- "9304:9304/tcp"
- "9304:9304/udp"
volumes:
- ./gluetun:/gluetun
env_file:
- .env
restart: unless-stopped
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
network_mode: "service:gluetun"
env_file:
- .env
volumes:
- ./qbittorrent/config:/config
- ./data:/data
restart: unless-stopped
depends_on:
- gluetun
Create the Environment File
Create a .env file in the same directory as docker-compose.yml:
TZ=Etc/UTC
PUID=1000
PGID=1000
VPN_SERVICE_PROVIDER=
VPN_TYPE=wireguard
WIREGUARD_PRIVATE_KEY=
WIREGUARD_PRESHARED_KEY=
WIREGUARD_ADDRESSES=
SERVER_COUNTRIES=
SERVER_CITIES=
FIREWALL_VPN_INPUT_PORTS=
WIREGUARD_MTU=1320
Required WireGuard Variables
| Variable | Description |
|---|---|
VPN_SERVICE_PROVIDER | Your VPN provider name (e.g., mullvad, protonvpn, ivpn, surfshark). See gluetun providers for the full list. |
WIREGUARD_PRIVATE_KEY | Your WireGuard private key from your VPN provider. |
WIREGUARD_ADDRESSES | WireGuard interface address(es) from your provider (e.g., 10.0.0.2/32). |
SERVER_COUNTRIES | Country code for the VPN server (e.g., US, NL, CH). |
SERVER_CITIES | Optional: specific city (e.g., New York, Amsterdam). |
Optional Variables
| Variable | Description |
|---|---|
WIREGUARD_PRESHARED_KEY | Preshared key if your provider uses one. |
FIREWALL_VPN_INPUT_PORTS | Ports to allow inbound through the VPN (e.g., 9304 for gluetun's shadowsocks). |
WIREGUARD_MTU | MTU for WireGuard interface (default 1320 works for most providers). |
qBittorrent Variables
| Variable | Description |
|---|---|
TZ | Timezone (e.g., Etc/UTC, America/New_York). |
PUID / PGID | User/group ID for file permissions (default 1000). |
Start Services
Run Docker Compose from the directory containing both files:
docker compose up -d
Access the Web UIs
Both services share port 8080 on the host:
- gluetun control server:
http://localhost:8080— shows VPN connection status, public IP, and shadowsocks/trojan config - qBittorrent Web UI:
http://localhost:8080— same port, served by qBittorrent (gluetun proxies it)
Default qBittorrent login: admin with a randomly generated password. Find it in the container logs:
docker logs qbittorrent
Change the password immediately in qBittorrent settings after first login.
Verify VPN Connection
- Open the gluetun control server at
http://localhost:8080 - Confirm "Public IP" shows your VPN provider's IP, not your home IP
- In qBittorrent, go to Tools → Options → Connection and verify the "Network Interface" shows the VPN tunnel (typically
tun0)
Notes
- Port 9304 is the gluetun port-forward listening port (used for inbound connections through the VPN). Remove if not needed.
- gluetun data persists in
./gluetun(contains VPN configs, certificates). - qBittorrent config persists in
./qbittorrent/config; downloads go to./data. - If the VPN disconnects, qBittorrent loses network access (kill switch behavior).
- For other VPN protocols (OpenVPN), change
VPN_TYPEand adjust variables accordingly.