QSticky
🔄 Automated port forwarding manager that keeps qBittorrent in sync with Gluetun VPN's forwarded ports. Monitors port changes in real-time and updates qBittorrent automatically.
Install / Use
/learn @monstermuffin/QStickyREADME
qSticky
qSticky is an automated port forwarding manager for Gluetun and qBittorrent. It automatically updates qBittorrent's listening port whenever Gluetun receives a new forwarded port.

[!IMPORTANT]
Gluetun v3.40.1+ API Change: qSticky now uses Gluetun's new API endpoints (/v1/portforward,/v1/vpn/status). If you're upgrading from an older version or experiencing 401 errors, you'll need to update yourconfig.tomlauthentication file. See the Authentication Setup section below for the updated configuration.
How it Works
qSticky monitors Gluetun's port forwarding through its control server API and updates qBittorrent's connection settings as needed.
Port Monitoring
- Queries Gluetun's control server API endpoint at
/v1/portforward(Gluetun v3.39.0+) - Supports both Basic Auth and API Key authentication methods
- Polls the API at configurable intervals (default: 30 seconds)
Port Management When a new port is detected, qSticky retrieves the port number from Gluetun's API, connects to qBittorrent's WebUI API, updates qBittorrent's listening port, and verifies the change was successful.
Health Monitoring qSticky maintains a health status file, checks qBittorrent connectivity regularly, tracks port changes and any errors, and provides Docker health checks.
Recovery The application automatically retries on connection failures, maintains session with qBittorrent, handles network interruptions gracefully, and logs important events and errors.
Flow
graph TD;
A[Gluetun Control Server] -->|API Poll| B[qSticky];
B -->|Port Update| C[qBittorrent];
B -->|Status Write| D[Health Monitor];
Quick Start
[!IMPORTANT]
qSticky only supports VPN providers with native port forwarding integration in Gluetun. Currently supported providers: Private Internet Access (PIA), ProtonVPN, Perfect Privacy, and PrivateVPN. I recommend using ProtonVPN and my shill link is here.
Authentication Setup
[!IMPORTANT] 401 Error in qSticky logs? You need to update your Gluetun
config.tomlfile to include the new API endpoints. Follow the configuration examples below to fix authentication issues with Gluetun v3.39.0+.
qSticky requires access to Gluetun's control server API to monitor port forwarding. You need to configure this one of two ways:
[!NOTE]
Authentication is required for qSticky to function. No unauthenticated access is supported, as Gluetun is deprecating unauthenticated endpoints.
Create Authentication Config
Create a config.toml file somewhere to be mapped into gluetun:
[[roles]]
name = "qSticky"
routes = [
"GET /v1/portforward",
"GET /v1/vpn/status"
]
auth = "apikey"
apikey = "your_api_key_here"
Or if you prefer basic auth:
[[roles]]
name = "qSticky"
routes = [
"GET /v1/portforward",
"GET /v1/vpn/status"
]
auth = "basic"
username = "myusername"
password = "mypassword"
[!NOTE]
/v1/portforwardis required for dynamic port mapping, and/v1/vpn/statusis required for Gluetun's health status checks.
Volume mount
Mount the config in your docker-compose.yml:
services:
gluetun:
# ... other gluetun config ...
volumes:
- ./gluetun/config.toml:/gluetun/auth/config.toml # Mount auth config
qSticky Configuration
Configure qSticky to use the same authentication method:
services:
qSticky:
# ... other qSticky config ...
environment:
# For API Key auth:
GLUETUN_AUTH_TYPE: apikey
GLUETUN_APIKEY: your_api_key_here
# Or for Basic auth:
# GLUETUN_AUTH_TYPE: basic
# GLUETUN_USERNAME: myusername
# GLUETUN_PASSWORD: mypassword
For complete details on Gluetun's control server authentication, check out the official Gluetun documentation.
Gluetun Setup
Gluetun setup is straightforward. If you're already using it you may just need to add some environment variables:
To set up port forwarding:
- Enable port forwarding in Gluetun by setting
VPN_PORT_FORWARDING=on - Enable Gluetun's control server with
GLUETUN_HTTP_CONTROL_SERVER_ENABLE=on - Configure authentication (API key or Basic Auth)
- Ensure qSticky has network access to Gluetun's control server
A working Gluetun configuration might look like:
services:
gluetun:
image: qmcgaw/gluetun:latest
container_name: gluetun
environment:
VPN_SERVICE_PROVIDER: protonvpn
VPN_TYPE: wireguard
VPN_PORT_FORWARDING: on
GLUETUN_HTTP_CONTROL_SERVER_ENABLE: on
WIREGUARD_PRIVATE_KEY: 'YOURKEY'
SERVER_COUNTRIES: Netherlands
volumes:
- ./gluetun/config.toml:/gluetun/auth/config.toml
[!NOTE]
Since we are using docker compose networking, port8000does not need to be explicitly mapped in docker. If you wish to use the API outside of the docker network, you should map the port.
qSticky Setup
[!TIP] A full list of environment variables are listed and explained below.
To deploy qSticky, add the service to your compose file as so, changing settings as required:
services:
qsticky:
image: ghcr.io/monstermuffin/qsticky:latest
container_name: qsticky
environment:
# qbittorrent settings
QBITTORRENT_HOST: gluetun
QBITTORRENT_HTTPS: false
QBITTORRENT_PORT: 8080
QBITTORRENT_USER: admin
QBITTORRENT_PASS: adminadmin
# gluetun settings
GLUETUN_HOST: gluetun
GLUETUN_AUTH_TYPE: apikey
GLUETUN_APIKEY: your_api_key_here
# qSticky settings
LOG_LEVEL: INFO
healthcheck:
test: ["CMD", "python3", "-c", "import json; exit(0 if json.load(open('/app/health/status.json'))['healthy'] else 1)"]
interval: 30s
timeout: 10s
retries: 3
restart: always
[!NOTE]
Put qSticky in the same network as gluetun and your host for both gluetun and qBittorrent will begluetun. It is adviced to do this ascontainer:gluetunwill break the network stack on gluetun restarts.
[!NOTE]
HTTPS and SSL Certificates: When usingQBITTORRENT_HTTPS: true, qSticky defaults to accepting self-signed certificates (QBITTORRENT_VERIFY_SSL: false). SetQBITTORRENT_VERIFY_SSL: trueif you want strict SSL certificate verification.
qBittorrent Setup
qBittorrent can be deployed like the following example:
services:
qbittorrent:
container_name: qbittorrent
image: linuxserver/qbittorrent:latest
network_mode: container:gluetun
environment:
PUID: 1000
PGID: 1000
TZ: UTC
WEBUI_PORT: 8080
volumes:
- ./qbittorrent/config:/config
- ./downloads:/downloads
restart: always
healthcheck:
test: ["CMD-SHELL", "curl -sf https://api.ipify.org || exit 1"]
interval: 30s
timeout: 10s
retries: 3
depends_on:
- gluetun
[!NOTE] I use the above
healthcheckto ensure qbittorrent is working. If that check fails, it means qbittorrent can't get out of gluetun's network and marks the container as unhealthy.
Full Stack Example
Here is a complete example stack for deploying Gluetun, qBittorrent and qSticky:
services:
gluetun:
container_name: gluetun
image: qmcgaw/gluetun:latest
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
VPN_SERVICE_PROVIDER: protonvpn
VPN_TYPE: wireguard
VPN_PORT_FORWARDING: on
WIREGUARD_PRIVATE_KEY: 'YOURKEY'
WIREGUARD_ADDRESSES: 'IP'
SERVER_COUNTRIES: Netherlands
GLUETUN_HTTP_CONTROL_SERVER_ENABLE: on
volumes:
- ./gluetun/config.toml:/gluetun/auth/config.toml
ports:
- 8080:8080 # qBittorrent WebUI
restart: always
qbittorrent:
container_name: qbittorrent
image: linuxserver/qbittorrent:latest
network_mode: container:gluetun
environment:
PUID: 1000
PGID: 1000
TZ: UTC
WEBUI_PORT: 8080
volumes:
- ./qbittorrent/config:/config
- ./downloads:/downloads
healthcheck:
test: ["CMD-SHELL", "curl -sf https://api.ipify.org || exit 1"]
interval: 30s
timeout: 10s
retries: 3
restart: always
depends_on:
- gluetun
qsticky:
image: ghcr.io/monstermuffin/qsticky:latest
container_name: qsticky
environment:
# qbittorrent settings
QBITTORRENT_HOST: gluetun
QBITTORRENT_HTTPS: false
QBITTORRENT_PORT: 8080
QBITTORRENT_USER: admin
QBITTORRENT_PASS: 'YOURPASS'
# gluetun settings
GLUETUN_HOST: gluetun
GLUETUN_AUTH_TYPE: apikey
GLUETUN_APIKEY: 'YOURAPIKEY'
# qSticky settings
LOG_LEVEL: INFO
healthcheck:
test: ["CMD", "python3", "-c", "import json; exit(0 if json.load(open('/app/health/status.json'))['healthy'] else 1)"]
interval: 30s
timeout: 10s
retries: 3
restart: always
Configuration
All configuration is done through environment variables:
| Environment Variable | Description | Default | |---------------------|-------------|---------| | QBITTORRENT_HOST | qBittorrent server hostname | gluetun | | QBITTORRENT_PORT | qBittorrent server port | 8080 | | QBITTORRENT_USER | qBittorrent username | admin | | QBITTORRENT_PASS | qBittorrent password | adminadmin | | QBITTORRENT_HTTPS | Use HTTPS for qBittorrent connection | false | | QBITTORRENT_VERIFY_SSL | Verify SSL certificates for HTTPS connections | false | | CHECK_INTERVAL | API check interval in seconds | 30 | | LOG_LEVEL | Logging level (DEBUG, INFO, ERROR, WARNING) |
Related Skills
node-connect
351.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
prose
351.8kOpenProse VM skill pack. Activate on any `prose` command, .prose files, or OpenProse mentions; orchestrates multi-agent workflows.
frontend-design
110.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
351.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
