Docker: Mullvad (WireGuard) & qBitTorrent
Sample Docker Compose configuration for running qBitTorrent as a container routed through another Mullvad container.
Port forwarding
For port forwarding to work via Mullvad, you have to set the "Listening port" (Settings -> Connection -> Listening port) in qBitTorrent to the correct forwarded port from Mullvad.
I also recommend forcing qBitTorrent to use the Mullvad network interface (Advanced -> Network interface), though I'm not sure if it matters much
docker-compose.yml
file
version: '3.5'
services:
vpn:
container_name: wireguard
image: jordanpotter/wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
net.ipv4.conf.all.src_valid_mark: 1
net.ipv6.conf.all.disable_ipv6: 0
volumes:
# Generate a file here: https://mullvad.net/en/account/#/wireguard-config/
# and put it in the same folder as `docker-compose.yml`
# Make sure to name it `mullvad.conf` exactly.
- ./mullvad.conf:/etc/wireguard/mullvad.conf
ports:
# I run NGINX on the host server for a reverse proxy.
# The secondary `8888` matches the `WEBUI_PORT` on the qBitTorrent container.
- "127.0.0.1:8080:8888"
restart: unless-stopped
qbittorrent:
container_name: qbit-wg
image: ghcr.io/linuxserver/qbittorrent
depends_on:
- vpn
network_mode: "service:vpn"
restart: unless-stopped
volumes:
# For persisting qBitTorrent configuration files
- ./config:/config
# Hard drives with more storage space, for download directories.
# - /data/media:/data/media
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Oslo
- WEBUI_PORT=8888
NGINX configuration file
# This is loosely based on the following:
# qBitTorrent GitHub wiki: https://github.com/qbittorrent/qBittorrent/wiki/NGINX-Reverse-Proxy-for-Web-UI
# My personal NGINX bootstrapping script: https://gist.github.com/Decicus/2f09db5d30f4f24e39de3792bba75b72
# Someone's reddit comment while I was researching, I wish I could find it again...
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name qbittorrent.example.com;
root /var/www/html;
ssl_certificate /srv/ssl/qbittorrent/fullchain.pem;
ssl_certificate_key /srv/ssl/qbittorrent/key.pem;
server_tokens off;
# These files are included as part of my NGINX bootstrapping script: https://gist.github.com/Decicus/2f09db5d30f4f24e39de3792bba75b72
# So normally I'd just put `include ssl_params.conf` and call it a day.
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# dhparams will have to be created here
# See this script file: https://gist.github.com/Decicus/2f09db5d30f4f24e39de3792bba75b72#file-generate-dhparams-sh
ssl_dhparam /etc/nginx/dhparams.pem;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
# CSP that whitelists a userstyle I use in my browser, for the qBitTorrent web UI: https://docs.theme-park.dev/themes/qbittorrent/
# Might wanna tweak it to your own liking if you don't use it.
# Commented by default, because it generally causes more headaches than it helps...
# add_header Content-Security-Policy "default-src https://use.fontawesome.com https: moz-extension: 'self' 'unsafe-inline'; style-src https://gilbn.github.io https://theme-park.dev https://qbittorrent.example.com https://raw.githubusercontent.com https://use.fontawesome.com 'unsafe-inline'; img-src https:";
index index.nginx-debian.html index.html index.htm;
charset utf-8;
location / {
# IP-based whitelisting. I whitelist my home IP, but you can choose to use something like HTTP auth if you want.
# Some might also be fine with exposing qBitTorrent's login page directly.
# allow 127.0.0.1;
# allow 192.168.0.0/24;
# deny all;
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
http2_push_preload on; # Enable http2 push
# The `8888` port here has to match the one in the `WEBUI_PORT` in docker-compose.yml
# Or else you will have issues...
proxy_set_header Host 127.0.0.1:8888;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_hide_header Content-Security-Policy;
# optionally, you can adjust the POST request size limit, to allow adding a lot of torrents at once:
#client_max_body_size 100M;
# since v4.2.2, is possible to configure qBittorrent
# to set the "Secure" flag for the session cookie automatically.
# However, that option does nothing unless using qBittorrent's built-in HTTPS functionality.
# For this use case, where qBittorrent itself is using plain HTTP
# (and regardless of whether or not the external website uses HTTPS),
# the flag must be set here, in the proxy configuration itself:
proxy_cookie_path / "/; Secure";
}
location /.well-known {
auth_basic "off";
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log /var/log/nginx/qbittorrent-access.log combined;
error_log /var/log/nginx/qbittorrent-error.log error;
location ~ /\.ht {
deny all;
}
}