Prerequisites

Before you start, you should have qBittorrent up and running using this guide.

Implementation

If you’ve used the guide linked above, the qBittorrent container is already running. There are two configuration files that we’ll need to edit: .env and docker-compose.yml.

.env

Make sure the LAN_NETWORK variable is set properly. If you haven’t modified it after the initial setup, it should be set to 192.168.x.0/24. Update it so that your Synology’s LAN IP is within the address range. Example: since my Synology’s LAN IP address is 192.168.1.110, I’ve replaced x with 1: 192.168.1.0/24.

Set VPN_ENABLED to true

Set VPN_PROVIDER to pia

Hotio’s qBittorrent image also supports Proton VPN out of the box. You should be able to use it with any provider that supports the WireGuard protocol.

If you’re using PIA or Proton, set PORT_FORWARD to true.

Add the following variables:

VPN_PIA_USER=YOUR_PIA_USERNAME
VPN_PIA_PASS=YOUR_PIA_PASSWORD
VPN_PIA_PREFERRED_REGION=belgium # optional

Since port forwarding is disabled in some of the regions supported by PIA VPN, you might want to also set VPN_PIA_PREFERRED_REGION. You can see all available regions in docker/appdata/qbittorrent/wireguard/pia-regions.json. This file will be created the first time you run the container after setting your PIA username and password.

docker-compose.yml

Uncomment the devices section in qbittorrent:

devices:
  - /dev/net/tun:/dev/net/tun

Add the following variables to the environment section:

VPN_PIA_USER=${VPN_PIA_USER}
VPN_PIA_PASS=${VPN_PIA_PASS}
VPN_PIA_PREFERRED_REGION=${VPN_PIA_PREFERRED_REGION}

Here’s how your qBittorrent container definition should look:

qbittorrent:
  container_name: qbittorrent
  image: hotio/qbittorrent:latest
  restart: unless-stopped
  logging:
    driver: json-file
    options:
      max-file: ${DOCKERLOGGING_MAXFILE}
      max-size: ${DOCKERLOGGING_MAXSIZE}
  labels:
    - org.hotio.pullio.update=${PULLIO_UPDATE}
    - org.hotio.pullio.notify=${PULLIO_NOTIFY}
    - org.hotio.pullio.discord.webhook=${PULLIO_DISCORD_WEBHOOK}
  ports:
    - ${QBITTORRENT_WEBUI_PORT}:${QBITTORRENT_WEBUI_PORT}
    - ${QBITTORRENT_PRIVOXY_PORT}:${QBITTORRENT_PRIVOXY_PORT}
  cap_add:
    - NET_ADMIN
  devices:                              
    - /dev/net/tun:/dev/net/tun         
  sysctls:
    - net.ipv4.conf.all.src_valid_mark=1
    - net.ipv6.conf.all.disable_ipv6=1  
  environment:
    - PUID=${PUID}
    - PGID=${PGID}
    - TZ=${TZ}
    - UMASK=002
    - VPN_ENABLED=${VPN_ENABLED}
    - VPN_FIREWALL_TYPE=legacy
    - VPN_PROVIDER=${VPN_PROVIDER}
    - VPN_LAN_NETWORK=${LAN_NETWORK}
    - VPN_CONF=wg0-fix
    - VPN_AUTO_PORT_FORWARD=${PORT_FORWARD}
    - VPN_PIA_USER=${VPN_PIA_USER}
    - VPN_PIA_PASS=${VPN_PIA_PASS}
    - VPN_PIA_PREFERRED_REGION=${VPN_PIA_PREFERRED_REGION}
    - VPN_HEALTHCHECK_ENABLED=false
    - PRIVOXY_ENABLED=${QBITTORRENT_ENABLE_PRIVOXY}
    - WEBUI_PORTS=${QBITTORRENT_WEBUI_PORT}/tcp,${QBITTORRENT_WEBUI_PORT}/udp 
  dns:
    - 1.1.1.1
    - 8.8.8.8
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - ${DOCKERCONFDIR}/qbittorrent:/config:rw
    - ${DOCKERSTORAGEDIR}/torrents:/data/torrents:rw

Setting up tun service

/dev/net/tun is a kernel module that provides a network tunnel interface. On Synology NAS systems, it’s used by VPN applications and other networking tools like qBittorrent with VPN functionality.

Installing the Tun Service for Synology and VPN

Testing Changes

With everything done, you need to try running the container with the latest changes: sudo docker-compose up --force-recreate qbittorrent

Here’s a sample output from a successful startup:

qbittorrent  | s6-rc: info: service init-wireguard successfully started
qbittorrent  | s6-rc: info: service service-qbittorrent: starting
qbittorrent  | s6-rc: info: service service-pia: starting
qbittorrent  | s6-rc: info: service service-forwarder: starting
qbittorrent  | s6-rc: info: service service-qbittorrent successfully started
qbittorrent  | s6-rc: info: service service-pia successfully started
qbittorrent  | s6-rc: info: service service-forwarder successfully started
qbittorrent  | s6-rc: info: service legacy-services: starting
qbittorrent  | [INF] [2025-04-12 20:23:44] [PIA] Fetching new forwarded port...
qbittorrent  | s6-rc: info: service legacy-services successfully started
qbittorrent  | [INF] [2025-04-12 20:23:44] [PIA] Forwarded port will expire at [2025-06-14T06:23:44.166007524Z].
qbittorrent  | 
qbittorrent  | *** Legal Notice ***
qbittorrent  | qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.
qbittorrent  | 
qbittorrent  | If you have read the legal notice, you can use command line option `--confirm-legal-notice` to suppress this message.
qbittorrent  | 
qbittorrent  | WebUI will be started shortly after internal preparations. Please wait...
qbittorrent  | 
qbittorrent  | [INF] [2025-04-12 20:23:54] [VPN] Forwarded port is [REDACTED].
qbittorrent  | 
qbittorrent  | ******** Information ********
qbittorrent  | To control qBittorrent, access the WebUI at: http://localhost:8080
qbittorrent  | 
qbittorrent  | [INF] [2025-04-12 20:24:04] [QBITTORRENT] Updated forwarded port to [REDACTED].

Troubleshooting

The only issue I’ve encountered was with the /dev/net/tun module. It had overly restrictive permission settings:

ls -al /dev/net/tun
# Overly restrictive; should return `crw-rw---- root root`
crw------- 1 root root 10, 200 Feb 13 02:14 /dev/net/tun

The qBittorrent container needs at least 660 permission. You can fix that by executing:

sudo chmod 660 /dev/net/tun  # Allow root group access

Verifying VPN Works

To verify that the qBittorrent container is hidden behind a VPN, you can use IP/DNS Detect (Torrent Address detection).

Resources