Skip to content

Instantly share code, notes, and snippets.

@danilopopeye
Last active February 8, 2026 16:01
Show Gist options
  • Select an option

  • Save danilopopeye/73861547781dbfe4bef5b29cbbc66f89 to your computer and use it in GitHub Desktop.

Select an option

Save danilopopeye/73861547781dbfe4bef5b29cbbc66f89 to your computer and use it in GitHub Desktop.
---
services:
gluetun:
# https://github.com/qdm12/gluetun
image: ghcr.io/qdm12/gluetun:v3.40.1
container_name: gluetun
restart: unless-stopped
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- .../gluetun:/gluetun
- ./gluetun-control-server.toml:/gluetun/auth/config.toml:ro
env_file: ./.env
environment:
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/others.md
- TZ=Etc/UTC
- PUID=568
- PGID=568
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/control-server.md
- HTTP_CONTROL_SERVER_LOG=off
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/http-proxy.md
- HTTPPROXY=on
- HTTPPROXY_LOG=off
- HTTPPROXY_STEALTH=on
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/port-forwarding.md
- VPN_PORT_FORWARDING=on
# TODO: should we use this instead of the `update-forwarded-port.sh`
# - VPN_PORT_FORWARDING_UP_COMMAND=
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/updater.md
- UPDATER_PERIOD=24h
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/firewall.md
- FIREWALL_OUTBOUND_SUBNETS=192.168.0.0/24,192.168.144.0/24
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/dns.md
- DOT_PROVIDERS=quad9,cloudflare,google
- BLOCK_SURVEILLANCE=on
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/vpn.md
- VPN_SERVICE_PROVIDER=protonvpn
- VPN_TYPE=wireguard
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/providers/protonvpn.md
- SERVER_COUNTRIES=Brazil
- PORT_FORWARD_ONLY=on
ports:
- 3128:8888/tcp # HTTP proxy
- 18080:18080/tcp # qBittorrent
deploy:
resources:
limits:
cpus: "2"
memory: 512M
qbittorrent:
# https://docs.linuxserver.io/images/docker-qbittorrent
image: lscr.io/linuxserver/qbittorrent:5.1.2-r4-ls425
container_name: qbittorrent
restart: unless-stopped
volumes:
- ./update-forwarded-port.sh:/custom-services.d/update-forwarded-port.sh:ro
- .../config:/config
- .../downloads:/downloads
environment:
- PUID=568
- PGID=568
- TZ=Etc/UTC
- WEBUI_PORT=18080
- DOCKER_MODS=ghcr.io/vuetorrent/vuetorrent-lsio-mod:latest
network_mode: service:gluetun
depends_on:
gluetun:
condition: service_healthy
deploy:
resources:
limits:
cpus: "4"
memory: 2048M
[[roles]]
name = "qbittorrent"
# Define a list of routes with the syntax "HTTP-Method /path"
routes = ["GET /v1/openvpn/portforwarded"]
# Define an authentication method with its parameters
auth = "apikey"
apikey = "super-secret-apikey"
# auth = "basic"
# username = "myusername"
# password = "mypassword"
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/wireguard.md
WIREGUARD_PRIVATE_KEY=...
WIREGUARD_PERSISTENT_KEEPALIVE_INTERVAL=77s
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/updater.md
UPDATER_PROTONVPN_USERNAME=...
UPDATER_PROTONVPN_PASSWORD=...
# https://github.com/qdm12/gluetun-wiki/blob/v3.40.0/setup/options/http-proxy.md
# HTTPPROXY_USER=username
# HTTPPROXY_PASSWORD=password
#!/usr/bin/with-contenv bash
set -euo pipefail
# Change me
API_KEY=super-secret-apikey
# every minute
DEFAULT_SLEEP=60
QBT_BASEURL=http://localhost:18080/api/v2
GLUETUN_BASEURL=http://localhost:8000/v1
while true; do
SLEEP=$DEFAULT_SLEEP
PORT=$(curl --silent --request GET --url "$QBT_BASEURL/app/preferences" | jq --raw-output .listen_port)
NEW_PORT=$(curl --silent --header "X-API-Key: $API_KEY" "$GLUETUN_BASEURL/openvpn/portforwarded" | jq --raw-output .port)
if [ -z "$NEW_PORT" ]; then
echo "No forwarded port found?"
SLEEP=10
elif [ -z "$PORT" ]; then
echo "qBittorrent API did not respond?"
SLEEP=10
elif [ "$PORT" != "$NEW_PORT" ]; then
echo "Ports changed: old: $PORT, new: $NEW_PORT"
echo "Trying to update port via API"
curl \
--silent \
--request POST \
--url "$QBT_BASEURL/app/setPreferences" \
--data "json={\"listen_port\": $NEW_PORT}"
# shellcheck disable=SC2181
if [ $? -eq 0 ]; then
echo "Port updated successfully"
PORT=$NEW_PORT
else
echo "Error updating port"
fi
fi
sleep $SLEEP
done

Torrent Stack

Torrent stack with VPN using Gluetun and qBittorrent.

Services

Service Description
gluetun VPN client (ProtonVPN/WireGuard) with port forwarding and HTTP proxy
qbittorrent Torrent client with VueTorrent, routed through the VPN

Ports

Port Service
3128 HTTP proxy (Gluetun)
18080 qBittorrent WebUI

Configuration Files

File Description
compose.yaml Docker containers definition
gluetun-control-server.toml Gluetun control server configuration (auth)
update-forwarded-port.sh Script that syncs the forwarded port with qBittorrent
.env VPN environment variables (not versioned)

Requirements

  • Gluetun files at .../gluetun
  • qBittorrent files at .../qbittorrent/
  • Downloads at .../downloads/
  • .env file with VPN credentials (ProtonVPN)

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment