qBittorrent Nox
Deploy qBittorrent Nox (headless) torrent client.
Ansible hosts group: qbittorrent_nox
Variables
| Option | Type | Description | Default |
|---|---|---|---|
cs_qbittorrent_nox_docker_tag | string | qBittorrent Nox docker tag | 5.2.4-lt2-1 |
cs_qbittorrent_nox_docker_image | string | qBittorrent Nox docker image | {{ cs_vm_artifact_registry_containers_home }}/qbittorrent-nox |
cs_qbittorrent_nox_container_name | string | Container name | qbittorrent-nox |
cs_qbittorrent_nox_group | string | Dedicated group | qbittorrent-nox |
cs_qbittorrent_nox_user | string | Dedicated user (no home, no login) | qbittorrent-nox |
cs_qbittorrent_nox_user_gid | int | GID for the qBittorrent Nox group | 1984 |
cs_qbittorrent_nox_user_uid | int | UID for the qBittorrent Nox user | 1985 |
cs_qbittorrent_nox_server_dns | list | DNS servers | The cluster's DNS servers (from Vault) |
cs_qbittorrent_nox_download_dir | string | Download directory | /app/qbittorrent-nox-downloads |
cs_qbittorrent_nox_container_root | string | Container root directory | /app/qbittorrent-nox-container-root |
cs_qbittorrent_nox_container_media_mounts | list | List of media mounts | [] |
cs_qbittorrent_nox_cluster | string | Cluster name | {{ cs_cluster_name }} |
cs_qbittorrent_nox_public_uri | list | Public URLs served through the reverse proxy | [https://qbittorrent-nox-{{ inventory_hostname }}.<cluster domain>] |
cs_qbittorrent_nox_trusted_proxies | list | CIDRs trusted to set X-Forwarded-For | The cluster CIDR and VPN CIDR (from Vault) |
cs_qbittorrent_nox_restic_cluster_name | string | Restic cluster name | {{ cs_qbittorrent_nox_cluster }} |
cs_qbittorrent_nox_restic_node_name | string | Restic backup node name | {{ inventory_hostname }} |
cs_qbittorrent_nox_restic_repo_name | string | Restic repository name | qbittorrentnox |
Vault configurations
- key:
{{ cs_project_code }}/application-deployer/clusters/{{ cs_qbittorrent_nox_cluster }}/hosts/{{ inventory_hostname }}/apps/qbittorrent-nox/config
{
"qbittorrent_username": "admin",
"qbittorrent_password": "password",
"https_port": "Web server UI Port",
"listen_port": "torrent listen port"
}
Reverse proxy and direct access
The WebUI is reachable both directly on the LAN (https://<host-ip>:<https_port>) and through the
reverse proxy at any of the cs_qbittorrent_nox_public_uri entries. Both paths are validated
against WebUI\HostHeaderValidation, which qBittorrent enforces even for the WebUI's own root
page. The container publishes its port through Docker's bridge NAT, so qBittorrent's built-in
"matches the local bind address" shortcut never applies here: WebUI\ServerDomains explicitly
lists every address a client might legitimately connect through: the host's own IPv4 addresses,
hostname/fqdn (direct LAN access), and each cs_qbittorrent_nox_public_uri entry's hostname
(qBittorrent supports more than one, including reverse proxy aliases), matching the domains
configured for the qbittorrent-nox-public reverse proxy backend.
WebUI\ServerDomains and WebUI\TrustedReverseProxiesList are semicolon-joined lists, and both
are written wrapped in literal double quotes (like WebUI\Password_PBKDF2): left unquoted,
qBittorrent's config parser silently truncates the value to everything before the first ; the
next time it saves its settings back to disk (e.g. on container restart), leaving only the first
entry in effect.
WebUI\ReverseProxy\Enabled is set alongside WebUI\ReverseProxySupportEnabled: qBittorrent 5.2.3
writes this newer key itself once it saves its settings, so it's set explicitly here too rather
than relying on that migration happening on a fresh deploy.
WebUI\ReverseProxySupportEnabled only takes effect once WebUI\TrustedReverseProxiesList is
non-empty, so cs_qbittorrent_nox_trusted_proxies (the cluster and VPN CIDRs) is written there.
This means X-Forwarded-For is trusted only when it arrives from inside those ranges: requests
proxied by the reverse proxy resolve to the real client IP for banning/whitelisting purposes,
while a direct LAN connection cannot spoof its own IP through that header.
Backup
Restic backs up only cs_qbittorrent_nox_container_root (qBittorrent Nox's own config). cs_qbittorrent_nox_download_dir
and any cs_qbittorrent_nox_container_media_mounts entries sit outside that root and are excluded on purpose: they
hold downloaded torrent content, which can be re-fetched from its original source and isn't data qBittorrent Nox
needs protected the way its own config/state is.
The {{ cs_qbittorrent_nox_container_name }} container is stopped for the duration of the backup and started
again afterwards, even if the backup itself fails.
Cleanup (dangerously_cleanup_qbittorrent_nox)
Destructive. Only runs when this exact tag is passed explicitly (it is intentionally excluded from the
plain qbittorrent_nox tag) and permanently deletes qBittorrent Nox's own data on the host:
- Removes the
{{ cs_qbittorrent_nox_container_name }}Docker container. - Deletes the UFW allow rules opened for the listen port (TCP and UDP) and the HTTPS port.
- Deletes
cs_qbittorrent_nox_container_root.cs_qbittorrent_nox_download_dirand anycs_qbittorrent_nox_container_media_mountsentries are left untouched, since they hold downloaded torrent content, not data qBittorrent Nox needs protected the way its own config/state is. - Deletes the
{{ cs_qbittorrent_nox_user }}user, its home directory, and the{{ cs_qbittorrent_nox_group }}group.
Tags
qbittorrent_nox: Deploy qBittorrent Nox.qbittorrent_nox_install: Install qBittorrent Nox.qbittorrent_nox_restic_backup: Run Restic backup for qBittorrent Nox.qbittorrent_nox_restic_restore: Restore qBittorrent Nox's data from the latest Restic snapshot.dangerously_cleanup_qbittorrent_nox: Destructive. Removes the qBittorrent Nox Docker container, closes its UFW ports, and deletescs_qbittorrent_nox_container_root. Never included by the plainqbittorrent_noxtag.
Deployment
uv sync --all-extras --all-packages --no-progress
uv --offline run --no-sync --no-progress ansible-galaxy install -r requirements.yml
uv --offline run --no-sync --no-progress ansible-playbook playbook.yml --tags qbittorrent_nox