3.3 KiB
qBittorrent
qBittorrent is the torrent download client for the *arr stack on Dankserver. It receives download requests from Sonarr, Radarr, Lidarr, and Readarr via category tagging.
Host: Dankserver — Hostname: qbittorrent.dankserver.local — Docs: https://www.qbittorrent.org
Facts
| Item | Value |
|---|---|
| Image | lscr.io/linuxserver/qbittorrent:latest |
| Port | 8080 (host) → 8080 (container) |
| Min RAM | 512 MB |
| Auth | Web UI username/password; LAN mode available |
Configuration
- Keep Web UI authentication ON (LAN bypass not needed — the arr apps authenticate with the API) and give them a permanent password.
- Create download categories per app (
radarr,sonarr,lidarr,readarr): the arr download clients route category-per-app, and Prowlarr feeds hand grabs to each app's own client. - Set max active downloads: Settings → Downloads (recommended: 5 global, 3 per category).
Persistent WebUI credentials (verified 2026-08-30)
qBittorrent 5 mints a new temporary password at every start unless a
password is stored in qBittorrent.conf. That rotation silently breaks every
arr download client after each reboot. The Web-API has no password endpoint
any more (/api/v2/app/setPassword was removed), and the linuxserver image
has no WEBUI_AUTH handling — so persistence must be written to the conf
directly, in qb's own salt:hash format (src/base/utils/password.cpp:
PBKDF2-HMAC-SHA512, 100 000 iterations, 16-byte salt = 4×uint32, then
base64(salt) + ":" + base64(hash) as the raw value):
import base64, hashlib, os
salt = os.urandom(16)
h = hashlib.pbkdf2_hmac("sha512", password.encode(), salt, 100000, 64)
val = (base64.b64encode(salt) + b":" + base64.b64encode(h)).decode()
# with the container STOPPED, in [Preferences]:
# WebUI\Username=admin
# WebUI\Password_PBKDF2=<val>
Then podman start qbittorrent and confirm login survives a
podman restart — the temp-password rotation stops the moment stored
credentials verify. The chosen value lives host-local in
/home/dank/.qbpass (mode 600, owner dank) — never in git; every arr
download client and prowlarr.md reference it. (The classic
@ByteArray(salt+hash) form is WRONG for qb5: login 401s on it; verify()
base64-decodes the two halves separately.)
Docker Compose
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- UMASK_SET=022
volumes:
- /opt/qbittorrent/config:/config
- /mnt/media/downloads:/downloads
- /mnt/media/downloads/incomplete:/downloads/incomplete
ports:
- "8080:8080"
networks: [appnet]
Gotchas (verified live)
- Temporary-password rotation on every boot is the default state of an untouched qb5 — see the persistence recipe above; without it, all arr download clients silently fail queue adds ("Couldn't add release … to download queue" in the arr logs) after any restart.
- API login from
curlneeds aReferer: http://<host>:<port>/header (CSRF protection) or POSTs get rejected even with a valid SID. - Ensure umask is set to
022so downloaded files are readable by arr apps. - Monitor bandwidth limits to avoid saturating the network.
See Also
- ARR-Stack — full *arr stack documentation