90 lines
3.3 KiB
Markdown
90 lines
3.3 KiB
Markdown
# 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
|
||
|
||
1. Keep Web UI authentication ON (LAN bypass not needed — the arr apps
|
||
authenticate with the API) and give them a permanent password.
|
||
2. 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.
|
||
3. 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):
|
||
|
||
```python
|
||
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
|
||
|
||
```yaml
|
||
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 `curl` needs a `Referer: http://<host>:<port>/` header
|
||
(CSRF protection) or POSTs get rejected even with a valid SID.
|
||
- Ensure umask is set to `022` so downloaded files are readable by arr apps.
|
||
- Monitor bandwidth limits to avoid saturating the network.
|
||
|
||
## See Also
|
||
|
||
- [[ARR-Stack]] — full *arr stack documentation
|