All apps · 0 apps
pia-qbittorrent
Docker app from GeorgeK's Repository
Overview
Readme
View on GitHubA Docker container combining qBittorrent with Private Internet Access (PIA) VPN, supporting both WireGuard and OpenVPN. Built on Alpine Linux for a minimal footprint.
Fork of j4ym0/pia-qbittorrent with bug fixes and additional features.
Quick Links
Companion App
Looking for a native Windows desktop experience? Check out the companion Electron app that wraps the qBittorrent Web UI:
qBittorrent Desktop for Windows 11 — native window, system tray, magnet link support, .torrent file association, and the running container version shown in the title bar.
The title-bar version comes from an X-Docker-Version response header this image adds to the Web UI (set from the image version on every start), so the app always shows which build is running.
Features
- Your real IP stays hidden - if the VPN drops, the container loses its internet instead of quietly falling back to your normal connection
- It fixes itself - it notices when the VPN has stopped working - including when it still looks connected - and repairs it without you doing anything
- A dead VPN server is not your problem - it moves to another server nearby, and your forwarded port moves with it
- It keeps up with PIA - the list of PIA servers is refreshed every time the container starts, so it still works when PIA moves a region onto new machines
- Faster seeding - PIA port forwarding is set up for you, wherever your region supports it
- Downloads survive updates - it saves your progress on shutdown, so nothing re-checks after a restart
- Files land with the right owner - so they are readable on Unraid and other NAS systems without fixing permissions afterwards
- Your PIA login can stay out of the container settings - keep it in a protected file instead
- Runs on a Raspberry Pi - as well as a normal PC or server
Technical details
- WireGuard and OpenVPN support
- PIA port forwarding for seeding
- PIA server list refreshed at every container start, falling back to the bundled copy if PIA is unreachable
- Kill switch — all IPv4 and IPv6 traffic blocked if the VPN drops
- Docker healthcheck catches a tunnel that is up but dead, not just a missing interface — it reports
unhealthyrather than looking fine while torrents hang - Auto-healing VPN — detects a dead/dropped tunnel and reconnects in place (WireGuard re-registers its key, OpenVPN restarts the client and re-authenticates), escalating to a full container restart if the in-place reconnect can't recover it
- qBittorrent is relaunched after a successful reconnect, so it binds the new tunnel address. Resume data is saved first
- Automatic server failover — if the VPN server you're on goes down, reconnect tries the other servers in your region instead of retrying a dead one, and port forwarding follows it to the new server rather than silently pointing at the old one
- Port forwarding that cannot be set up at startup is retried every 10 minutes while the VPN is up, and qBittorrent is switched to the port once it works — no restart needed
- Multi-arch images —
amd64andarm64 - VPN network interface auto-detected and locked (WireGuard
pia/ OpenVPNtun0) - Configurable UID/GID for correct file ownership on Unraid and NAS systems
- Configurable UMASK; download folder permissions preserved across restarts
- Automatic
.torrentfile export to/downloads/torrents - Graceful shutdown — saves resume data so torrents resume instead of re-checking after an update
- Secure credential storage via
auth.conf - DNS leak protection with custom DNS servers
- Hook script support after the VPN connects —
/config/post-vpn-connect.shruns as the container user; bake a hook into the image at/app/post-vpn-connect.shif it genuinely needs root - Web UI accessible on your local network
Components
| Component | Stable (latest) |
Beta (beta) |
|---|---|---|
| Alpine Linux | 3.24 | same |
| qBittorrent | 5.2.4 | 5.3.0rc1 |
| libtorrent | 2.0.15 | 2.1.2 |
| Boost | 1.92.0 | same |
| OpenVPN | 2.7.7 | same |
| WireGuard | 1.0.20260223 | same |
| IPTables | 1.8.13 | same |
| Python 3 | Alpine 3.24 default (required by qBittorrent search plugins) | same |
Quick Start
Requires an active PIA subscription. Get one here — that is a referral link, which supports this project at no extra cost to you.
docker run -d --init --name=pia-qbittorrent --restart unless-stopped \
--cap-add=NET_ADMIN \
-v /your/downloads:/downloads \
-v /your/config:/config \
-p 8888:8888 \
-e PIA_USERNAME=your_username \
-e PIA_PASSWORD=your_password \
-e PIA_REGION=ca_montreal \
-e VPN_CLIENT=wireguard \
-e UID=99 \
-e GID=100 \
-e UMASK=000 \
gjergjk/pia-qbittorrent:latest
Then open the Web UI on port 8888. --cap-add=NET_ADMIN is required (the VPN and kill switch need it) and --restart unless-stopped is strongly recommended so the container can restart itself to recover from an expired VPN token. UID=99/GID=100/UMASK=000 suit Unraid; see Environment Variables for other systems.
Environment Variables
| Variable | Default | Description |
|---|---|---|
PIA_USERNAME |
PIA account username | |
PIA_PASSWORD |
PIA account password | |
PIA_REGION |
netherlands |
VPN region — see PIA Servers |
VPN_CLIENT |
openvpn |
VPN client: openvpn or wireguard |
PORT_FORWARDING |
true |
Enable PIA port forwarding for seeding. Skipped automatically in regions that do not support it, and retried in the background if PIA cannot provide a port at startup |
UID |
700 |
User ID for qBittorrent process. Use 99 for Unraid |
GID |
700 |
Group ID for qBittorrent process. Use 100 for Unraid |
UMASK |
022 |
Umask for downloads. 000 = fully open, 002 = group-writable |
WEBUI_PORT |
8888 |
qBittorrent Web UI port |
WEBUI_INTERFACES |
Network interfaces for Web UI access e.g. eth0,eth1 |
|
ALLOW_LOCAL_SUBNET_TRAFFIC |
false |
Allow LAN devices to connect directly to the container |
EXTRA_SUBNETS |
Comma-separated extra subnets to allow through the kill switch (e.g. for reverse proxies or *arr apps on a different Docker network) | |
OPEN_ADDITIONAL_LOCAL_PORTS |
Comma-separated extra LAN ports to open, e.g. 8989,7878. For containers sharing this container's network (network_mode: container:...) whose web UIs would otherwise be blocked by the kill switch |
|
DNS_SERVERS |
9.9.9.9,149.112.112.112 |
Comma-separated DNS servers |
LEGACY_IPTABLES |
false |
Use legacy iptables instead of nftables |
VPN_LOG_DIR |
/logs |
Where the VPN client writes its log. Must be root-owned — a path under /config, or any world-writable directory, is ignored with a warning and /logs used instead |
TZ |
Timezone e.g. America/New_York |
|
HOSTHEADERVALIDATION |
Set to false if having trouble accessing the WebUI. Has no practical effect unless you also set WebUI\ServerDomains to your own hostname — CSRF protection is what guards the Web UI |
|
CSRFPROTECTION |
Set to false if having trouble accessing the WebUI |
Volumes
| Path | Description |
|---|---|
/downloads |
Download directory |
/config |
qBittorrent config and profiles |
Unraid Setup
Available in Community Applications: search for pia-qbittorrent.
| Variable | Value |
|---|---|
UID |
99 |
GID |
100 |
UMASK |
000 (or 002) |
This maps qBittorrent to Unraid's nobody:users so downloaded files are accessible from SMB shares.
- Storage: map
/downloadsto your share (e.g./mnt/user/downloads/) and/configto appdata (e.g./mnt/user/appdata/pia-qbittorrent/). - Network: Bridge and custom bridge networks both work; the VPN tunnel runs inside the container either way. Avoid Host networking: the container would then share the Unraid server's own network stack, so the kill switch's firewall rules, routes and IPv6 settings would be applied to the server — including flushing the iptables rules Docker itself relies on, which breaks networking for other containers.
- Extra Parameters: keep
--cap-add=NET_ADMIN --restart unless-stopped. - Other containers (Sonarr, Radarr, etc.): if they are on a different Docker network and cannot reach the Web UI, add their subnet to
EXTRA_SUBNETS, e.g.172.18.0.0/16.
VPN Client
WireGuard
- Lower CPU usage and faster speeds due to less overhead
- Needs WireGuard support in the host kernel (built in since Linux 5.6; Unraid has it)
- Best for most home setups
OpenVPN
- Works where WireGuard cannot, e.g. an older kernel without WireGuard
- Can be steadier on unusual networks or high-latency links
Port forwarding, reconnects and server failover work the same on both.
Note: Port forwarding is available in most PIA regions, but not all. See the PIA Regions section for the full list of regions that support it.
PIA Regions
Set PIA_REGION to the region you want. Matching is flexible — you can use the region name or its PIA ID, and it's case-insensitive (underscores, hyphens, and spaces are treated the same). So ca_montreal, CA Montreal, and ca all resolve to the same region.
Common regions with port forwarding:
PIA_REGION |
Location |
|---|---|
ca_montreal |
CA Montreal |
ca_toronto |
CA Toronto |
ca_ontario |
CA Ontario |
uk |
UK London |
netherlands |
Netherlands |
de_frankfurt |
DE Frankfurt |
france |
France |
switzerland |
Switzerland |
sweden |
SE Stockholm |
spain |
ES Madrid |
italy |
IT Milano |
romania |
Romania |
singapore |
Singapore |
japan |
JP Tokyo |
aus |
AU Sydney |
ℹ️ 135 of 190 regions support port forwarding; no US region does. The table below says which. Ignore the
-pfin a region id — 32 ids end in-pfwithout supporting it.
All PIA regions
Either column works as PIA_REGION, as does any unique fragment — massachusetts finds us_massachusetts-pf. Short fragments can be ambiguous, so prefer the full name or id if in doubt.
🌍 Click to view all 190 PIA regions
| Location | PIA ID | Port forwarding |
|---|---|---|
| AR Streaming Optimized | ar-so |
Yes |
| AT Streaming Optimized | at-so |
Yes |
| AU Adelaide | au_adelaide-pf |
Yes |
| AU Brisbane | au_brisbane-pf |
Yes |
| AU Melbourne | aus_melbourne |
Yes |
| AU Perth | aus_perth |
Yes |
| AU Sydney | aus |
Yes |
| Albania | al |
Yes |
| Algeria (geo) | dz |
Yes |
| Andorra (geo) | ad |
Yes |
| Argentina | ar |
Yes |
| Armenia (geo) | yerevan |
Yes |
| Australia Streaming Optimized | au_australia-so |
Yes |
| Austria | austria |
Yes |
| BE Streaming Optimized | be-so |
Yes |
| BR Streaming Optimized | br-so |
Yes |
| Bahamas | bahamas |
Yes |
| Bangladesh (geo) | bangladesh |
Yes |
| Belgium | belgium |
Yes |
| Bolivia | bo_bolivia-pf |
Yes |
| Bosnia and Herzegovina (geo) | ba |
Yes |
| Brazil | br |
Yes |
| Bulgaria | sofia |
Yes |
| CA Montreal | ca |
Yes |
| CA Ontario | ca_ontario |
Yes |
| CA Ontario Streaming Optimized | ca_ontario-so |
Yes |
| CA Toronto | ca_toronto |
Yes |
| CA Vancouver | ca_vancouver |
Yes |
| CH Streaming Optimized | ch-so |
Yes |
| CL Streaming Optimized | cl-so |
Yes |
| Cambodia (geo) | cambodia |
Yes |
| Chile | santiago |
Yes |
| China (geo) | china |
Yes |
| Colombia | bogota |
Yes |
| Costa Rica | sanjose |
Yes |
| Croatia | zagreb |
Yes |
| Cyprus (geo) | cyprus |
Yes |
| Czech Republic | czech |
Yes |
| DE Berlin | de_berlin |
Yes |
| DE Frankfurt | de-frankfurt |
Yes |
| DE Germany Streaming Optimized | de_germany-so |
Yes |
| DK Streaming Optimized | denmark_2 |
Yes |
| Denmark | denmark |
Yes |
| ES Madrid | spain |
Yes |
| ES Streaming Optimized | es-so |
Yes |
| ES Valencia | es-valencia |
Yes |
| Ecuador | ec_ecuador-pf |
Yes |
| Egypt (geo) | egypt |
Yes |
| Estonia | ee |
Yes |
| FI Helsinki | fi |
Yes |
| FI Streaming Optimized | fi_2 |
Yes |
| FR Streaming Optimized | fr-so |
Yes |
| France | france |
Yes |
| Georgia (geo) | georgia |
Yes |
| Greece | gr |
Yes |
| Greenland | greenland |
Yes |
| Guatemala | gt_guatemala-pf |
Yes |
| HU Streaming Optimized | hu-so |
Yes |
| Hong Kong (geo) | hk |
Yes |
| Hungary | hungary |
Yes |
| IL Israel 2 | il_israel_2-pf |
Yes |
| IL Streaming Optimized | il-so |
Yes |
| IT Milano | italy |
Yes |
| IT Streaming Optimized (geo) | italy_2 |
Yes |
| Iceland | is |
Yes |
| India | in |
Yes |
| Indonesia (geo) | jakarta |
Yes |
| Ireland | ireland |
Yes |
| Isle of Man (geo) | man |
Yes |
| Israel | israel |
Yes |
| JP Streaming Optimized | japan_2 |
Yes |
| JP Tokyo | japan |
Yes |
| KR Streaming Optimized | kr-so |
Yes |
| Kazakhstan | kazakhstan |
Yes |
| LT Streaming Optimized | lt-so |
Yes |
| LU Streaming Optimized | lu-so |
Yes |
| Latvia | lv |
Yes |
| Liechtenstein (geo) | liechtenstein |
Yes |
| Lithuania | lt |
Yes |
| Luxembourg | lu |
Yes |
| MX Streaming Optimized | mx-so |
Yes |
| Macao (geo) | macau |
Yes |
| Malaysia | kualalumpur |
Yes |
| Malta (geo) | malta |
Yes |
| Mexico | mexico |
Yes |
| Moldova | md |
Yes |
| Monaco (geo) | monaco |
Yes |
| Mongolia (geo) | mongolia |
Yes |
| Montenegro (geo) | montenegro |
Yes |
| Morocco (geo) | morocco |
Yes |
| NL Netherlands Streaming Optimized | nl_netherlands-so |
Yes |
| NZ Streaming Optimized | nz-so |
Yes |
| Nepal (geo) | np_nepal-pf |
Yes |
| Netherlands | nl_amsterdam |
Yes |
| New Zealand | nz |
Yes |
| Nigeria (geo) | nigeria |
Yes |
| North Macedonia | mk |
Yes |
| Norway | no |
Yes |
| PL Streaming Optimized | pl-so |
Yes |
| PT Streaming Optimized | pt-so |
Yes |
| Panama | panama |
Yes |
| Peru | pe_peru-pf |
Yes |
| Philippines | philippines |
Yes |
| Poland | poland |
Yes |
| Portugal | pt |
Yes |
| Qatar (geo) | qatar |
Yes |
| RO Streaming Optimized | ro-so |
Yes |
| RS Streaming Optimized | rs-so |
Yes |
| Romania | ro |
Yes |
| SE Stockholm | sweden |
Yes |
| SE Streaming Optimized | sweden_2 |
Yes |
| SG Streaming Optimized | sg-so |
Yes |
| SK Streaming Optimized | sk-so |
Yes |
| Saudi Arabia (geo) | saudiarabia |
Yes |
| Serbia | rs |
Yes |
| Singapore | sg |
Yes |
| Slovakia | sk |
Yes |
| Slovenia | slovenia |
Yes |
| South Africa | za |
Yes |
| South Korea | kr_south_korea-pf |
Yes |
| Sri Lanka (geo) | srilanka |
Yes |
| Switzerland | swiss |
Yes |
| TW Streaming Optimized | tw-so |
Yes |
| Taiwan | taiwan |
Yes |
| Turkey (geo) | tr |
Yes |
| UK London | uk |
Yes |
| UK Manchester | uk_manchester |
Yes |
| UK Southampton | uk_southampton |
Yes |
| UK Streaming Optimized | uk_2 |
Yes |
| US Alabama (geo) | us_alabama-pf |
No |
| US Alaska (geo) | us_alaska-pf |
No |
| US Arkansas (geo) | us_arkansas-pf |
No |
| US Atlanta | us_atlanta |
No |
| US Baltimore (geo) | us-baltimore |
No |
| US California | us_california |
No |
| US Chicago | us_chicago |
No |
| US Connecticut (geo) | us_connecticut-pf |
No |
| US Denver | us_denver |
No |
| US East | us-newjersey |
No |
| US East Streaming Optimized | us-streaming |
No |
| US Florida | us_florida |
No |
| US Honolulu (geo) | us-honolulu |
No |
| US Houston | us_houston |
No |
| US Idaho (geo) | us_idaho-pf |
No |
| US Indiana (geo) | us-indiana |
No |
| US Iowa (geo) | us_iowa-pf |
No |
| US Kansas (geo) | us_kansas-pf |
No |
| US Kentucky (geo) | us-kentucky |
No |
| US Las Vegas | us_las_vegas |
No |
| US Louisiana (geo) | us_louisiana-pf |
No |
| US Maine (geo) | us_maine-pf |
No |
| US Massachusetts | us_massachusetts-pf |
No |
| US Michigan (geo) | us_michigan-pf |
No |
| US Minnesota (geo) | us_minnesota-pf |
No |
| US Mississippi (geo) | us_mississippi-pf |
No |
| US Missouri (geo) | us_missouri-pf |
No |
| US Montana (geo) | us_montana-pf |
No |
| US Nebraska (geo) | us_nebraska-pf |
No |
| US New Hampshire (geo) | us_new_hampshire-pf |
No |
| US New Mexico | us_new_mexico-pf |
No |
| US New York | us_new_york_city |
No |
| US North Carolina (geo) | us_north_carolina-pf |
No |
| US North Dakota (geo) | us_north_dakota-pf |
No |
| US Ohio (geo) | us_ohio-pf |
No |
| US Oklahoma (geo) | us_oklahoma-pf |
No |
| US Oregon (geo) | us_oregon-pf |
No |
| US Pennsylvania (geo) | us_pennsylvania-pf |
No |
| US Rhode Island (geo) | us_rhode_island-pf |
No |
| US Salt Lake City | us-salt-lake-city |
No |
| US Seattle | us_seattle |
No |
| US Silicon Valley | us_silicon_valley |
No |
| US South Carolina (geo) | us_south_carolina-pf |
No |
| US South Dakota | us_south_dakota-pf |
No |
| US Tennessee (geo) | us-tennessee |
No |
| US Texas | us_south_west |
No |
| US Vermont (geo) | us_vermont-pf |
No |
| US Virginia (geo) | us_virginia-pf |
No |
| US Washington DC | us_washington_dc |
No |
| US West | us3 |
No |
| US West Streaming Optimized | us-streaming-2 |
No |
| US West Virginia (geo) | us_west_virginia-pf |
No |
| US Wilmington (geo) | us-wilmington |
No |
| US Wisconsin (geo) | us_wisconsin-pf |
No |
| US Wyoming | us_wyoming-pf |
No |
| Ukraine | ua |
Yes |
| United Arab Emirates | ae |
Yes |
| Uruguay | uy_uruguay-pf |
Yes |
| Venezuela | venezuela |
Yes |
| Vietnam (geo) | vietnam |
Yes |
| ZA Streaming Optimized | za-so |
Yes |
The container refreshes this list from PIA on every start, so it is never limited to the table below. To regenerate the table yourself:
curl -s https://serverlist.piaservers.net/vpninfo/servers/v6 | head -1 | \
jq -r '.regions[] | "\(.name) — \(.id) — pf=\(.port_forward)"' | sort
Port Forwarding
Enabled by default (PORT_FORWARDING=true). On startup a port is requested from PIA, opened in the firewall, and set in qBittorrent automatically.
- Port is assigned randomly by PIA — you cannot specify one
- Port is valid for up to 2 months
- Container refreshes the port binding every 10 minutes to keep it alive
- If PIA cannot provide a port at startup, the container runs without one and retries every 10 minutes while the VPN is up; once it works, the port is opened and qBittorrent is switched to it automatically. The log shows PIA's reason.
- If your region doesn't support port forwarding (e.g. all US regions), the container logs it and keeps running without it. Pick a supported region to use it.
- PIA limits how often an account can sign in. Restarting the container many times in a short period can hit that limit — see Known Issues
Web UI
Access at http://YOUR_SERVER_IP:8888
Default username: admin
Default password: shown in container logs (docker logs pia-qbittorrent)
Change the password after first login — it changes every restart until you set a permanent one.
Saving .torrent Files
By default, added .torrent files are automatically saved to /downloads/torrents so you always keep a copy. The folder is created automatically when you add your first torrent.
Magnet links are saved too — just a few seconds later. A magnet has no metadata when added, so qBittorrent writes the .torrent once it fetches the metadata from the swarm. (If a magnet never finds peers, no file is written — but it wouldn't download anyway.)
Existing installs: this default is only written on a fresh config, so if you upgraded from an earlier version it won't appear automatically. To enable it manually, go to Options → Downloads → Saving Management, tick "Copy .torrent files to:", enter
/downloads/torrents, and Save.
auth.conf File
Store credentials securely by mounting an auth file instead of using environment variables:
/your/auth.conf:
line 1: your_pia_username
line 2: your_pia_password
docker run ... -v /your/auth.conf:/auth.conf ...
When /auth.conf is present, PIA_USERNAME and PIA_PASSWORD are ignored.
Hooks
Create /config/post-vpn-connect.sh to run custom code after the VPN connects but before qBittorrent starts.
It runs as qbtUser, not root. A hook that needs root must be baked into the image at /app/post-vpn-connect.sh, which the container user cannot write.
Available variables:
| Variable | Description |
|---|---|
PF_PORT |
The PIA forwarded port (empty if port forwarding is off or unsupported) |
WEBUI_PORT |
The Web UI port |
VPN_DEVICE |
The VPN interface name (pia or tun0) |
PIA_REGION |
The region as you configured it |
VPN_CLIENT |
wireguard or openvpn |
PUID |
The user ID qBittorrent runs as |
PGID |
The group ID qBittorrent runs as |
Example:
MY_IP=$(wget -qO- ifconfig.me/ip)
printf " My external IP is $MY_IP\n"
printf " My forwarding port is $PF_PORT\n"
DNS Servers
| Server | Provider |
|---|---|
9.9.9.9, 149.112.112.112 |
Quad9 |
1.1.1.1, 1.0.0.1 |
Cloudflare |
8.8.8.8, 8.8.4.4 |
|
84.200.69.80, 84.200.70.40 |
DNS.WATCH |
Once connected to PIA you can also use PIA's own private DNS. These are reachable only through the tunnel, so they cannot be used before the VPN is up:
| Server | Provides |
|---|---|
10.0.0.242 |
DNS |
10.0.0.243 |
DNS + Streaming |
10.0.0.244 |
DNS + MACE (blocks ads and trackers) |
10.0.0.241 |
DNS + Streaming + MACE |
Build from Source
git clone https://github.com/GeorgeAL78/pia-qbittorrent-docker.git
cd pia-qbittorrent-docker
docker build -t gjergjk/pia-qbittorrent .
Reading the startup log
The first line reports whether the PIA server list could be refreshed:
| Line | Meaning |
|---|---|
DOWNLOADED 190 regions from PIA |
Got PIA's current list |
PIA UNREACHABLE - using the 190 regions baked into this image |
Using the bundled copy |
FAILED to write the file - using the 190 regions baked into this image |
Using the bundled copy |
All three are normal — the container works either way.
Port forwarding, if it could not be set up straight away:
| Line | Meaning |
|---|---|
Port forwarding could not be set up ... - PIA refused: <reason> |
PIA answered but refused; the reason is PIA's own message |
... - no usable response (curl exit N) |
PIA's port-forwarding service did not answer |
Port forwarding still pending - ... retrying next cycle |
Still retrying, every 10 minutes; the VPN is unaffected |
Port forwarding established on retry - port N |
Recovered; qBittorrent is relaunched on the new port |
Known Issues
Banned client error on some trackers
- Some private trackers may not have whitelisted the current qBittorrent version yet
- Check the tracker's forum for supported client versions
PIA sign-in limit after many restarts
- PIA limits how often an account can sign in, and every container start signs in. After many restarts in a short period PIA refuses with
Try again later., and port forwarding cannot be set up - Fix: stop restarting and wait — in testing the limit cleared within 30 minutes. A running container retries port forwarding on its own, so no further restart is needed
- PIA limits how often an account can sign in, and every container start signs in. After many restarts in a short period PIA refuses with
Special characters in password
- If your password contains special characters use the
/auth.conffile instead of environment variables
- If your password contains special characters use the
Unauthorized when using proxy for WebUI
- Fix: Set
CSRFPROTECTION=false
- Fix: Set
Cannot block IPv6: ip6tables is unavailable
- The kill switch blocks IPv6 with
ip6tables. On a host that has no IPv6 support in its kernel or iptables build, the container refuses to start rather than run with IPv6 unprotected - The container cannot fall back to
sysctlat runtime: Docker mounts/proc/sysread-only, so the write silently has no effect - Fix: set them when creating the container -
--sysctl net.ipv6.conf.all.disable_ipv6=1 --sysctl net.ipv6.conf.default.disable_ipv6=1, or the equivalent commented-outsysctls:block indocker-compose.yml
- The kill switch blocks IPv6 with
nft: Protocol not supported
- Occurs on older kernels or Synology NAS
- Fix: Set
LEGACY_IPTABLES=true
Files moved to .trash instead of deleted
- qBittorrent 5.x defaults to moving files to trash
- Fix: Tools → Options → Advanced → set "Torrent content removing mode" to "Delete files permanently"
Exit Codes
The container exits with these codes. Codes 5 and 7 expect a restart policy
(--restart unless-stopped); without one the container stays stopped. Existing
containers can be updated in place with docker update --restart unless-stopped <name>.
| Code | Meaning | Needs a restart policy |
|---|---|---|
0 |
Normal shutdown | - |
1 |
Invalid configuration (bad WEBUI_PORT, unresolvable PIA_REGION, IPv6 cannot be blocked) |
No - fix the setting |
3 |
PIA credentials missing or rejected while fetching a token, or the OpenVPN server name could not be resolved | No - fix /auth.conf or check DNS |
5 |
Deliberate restart to recover something that cannot be fixed in place: about an hour of failed in-place reconnects (for example an expired PIA token), no WireGuard server in the region accepting the key at startup, or a changed forwarded port that a running qBittorrent cannot be moved to | Yes |
6 |
OpenVPN reported a fatal error in its log | No |
7 |
VPN authentication failed | No - check credentials |
Before exiting with 5 the container stops qBittorrent gracefully so resume data is
saved and torrents do not re-check on the next start.
Changelog
Every release and its notes are on GitHub Releases. A summary of recent changes is on Docker Hub.
License
GNU General Public License v3.0
This project is a fork of j4ym0/pia-qbittorrent-docker, originally MIT licensed. The original MIT notice is preserved in the NOTICE file.
Disclaimer
This is an unofficial, community-maintained project. It is not affiliated with, endorsed by, or sponsored by Private Internet Access or qBittorrent. "Private Internet Access", "PIA", and "qBittorrent" are trademarks of their respective owners and are used here only to describe compatibility.
Categories
Download Statistics
Related apps
Explore more like this
Explore allDetails
gjergjk/pia-qbittorrentRuntime arguments
- Web UI
http://[IP]:[PORT:8888]/- Network
bridge- Shell
sh- Privileged
- false
- Extra Params
--cap-add=NET_ADMIN --restart unless-stopped
Template configuration
qBittorrent Web UI port
- Target
- 8888
- Default
- 8888
- Value
- 8888
Download directory
- Target
- /downloads
- Default
- /mnt/user/downloads/
- Value
- /mnt/user/downloads/
qBittorrent config and profiles
- Target
- /config
- Default
- /mnt/user/appdata/pia-qbittorrent/
- Value
- /mnt/user/appdata/pia-qbittorrent/
Your PIA account username
- Target
- PIA_USERNAME
Your PIA account password
- Target
- PIA_PASSWORD
VPN region e.g. ca_montreal, us_new_york
- Target
- PIA_REGION
- Default
- netherlands
- Value
- netherlands
VPN client: wireguard or openvpn
- Target
- VPN_CLIENT
- Default
- wireguard|openvpn
- Value
- wireguard
Enable PIA port forwarding for better seeding. Falls back gracefully if your region does not support it (e.g. US)
- Target
- PORT_FORWARDING
- Default
- true|false
- Value
- true
User ID for qBittorrent process. Use 99 for Unraid nobody
- Default
- 99
- Value
- 99
Group ID for qBittorrent process. Use 100 for Unraid users
- Default
- 100
- Value
- 100
Umask for downloads. 000=fully open (recommended for Unraid), 002=group-writable, 022=owner only
- Default
- 000
- Value
- 000
Must match the port mapping above
- Target
- WEBUI_PORT
- Default
- 8888
- Value
- 8888
Comma-separated network interfaces for Web UI access e.g. eth0,eth1 (defaults to the VPN's physical interface)
- Target
- WEBUI_INTERFACES
Set to false if having trouble accessing the WebUI (e.g. behind a reverse proxy)
- Target
- HOSTHEADERVALIDATION
- Default
- true|false
- Value
- true
Set to false if having trouble accessing the WebUI (e.g. behind a reverse proxy)
- Target
- CSRFPROTECTION
- Default
- true|false
- Value
- true
Comma-separated DNS servers
- Target
- DNS_SERVERS
- Default
- 9.9.9.9,149.112.112.112
- Value
- 9.9.9.9,149.112.112.112
Use legacy iptables instead of nftables
- Target
- LEGACY_IPTABLES
- Default
- false|true
- Value
- false
Timezone e.g. America/New_York
- Target
- TZ
Comma-separated extra subnets allowed through the kill switch. Use this if your *arr apps or reverse proxy are on a different Docker network and cannot reach qBittorrent e.g. 172.18.0.0/16
- Target
- EXTRA_SUBNETS
Comma-separated extra LAN ports to open e.g. 8989,7878. Use this for containers routed through this one (network_mode: container:...) whose web UI would otherwise be blocked by the kill switch
- Target
- OPEN_ADDITIONAL_LOCAL_PORTS
Set to true to allow LAN devices to connect directly to the container
- Target
- ALLOW_LOCAL_SUBNET_TRAFFIC
- Default
- false|true
- Value
- false