qBittorrent (standalone)
Separate qBittorrent instance with tracker-specific rules
| Host | ShiNAS |
| Category | Media |
| Status | ⏸️ on demand (started only when I need it) |
| Exposed? | Web UI LAN only (not published through the tunnel) |
| Version | 5.2.4_v2.0.15-ls479 (pinned) |
Compose file: stacks/qbittorrent-mam/
Why I run it
One private tracker I use for audiobooks doesn't allow VPN connections, so it can't share the VPN-routed client in my *arr stack. Rather than weaken the VPN setup for everything else, this tracker gets its own small, separate qBittorrent.
Architecture
flowchart LR
me([Me, on the LAN]) -- Web UI :8089 --> qb[qBittorrent<br/>standalone]
qb -- torrent traffic --> net((Internet<br/>no VPN))
qb --> dl[(./downloads)]
vpnqb[arr-stack qBittorrent] -- through ProtonVPN --> vpn{{VPN}}
Two clients, two rules: everything general goes through the VPN-protected stack, and only this one tracker uses the direct connection it requires.
Security decisions
| Decision | Why |
|---|---|
| Separate container, separate folders | The no-VPN exception is contained to one client and one tracker |
| Web UI LAN only | Not published through the tunnel |
| On demand | Only running when I'm using it |
| Pinned image | Same version as the arr stack's qBittorrent |
Setup notes
docker compose up -d, openhttp://<LAN_IP>:8089, change the default login- Add only that tracker's torrents here
- Point the downloads folder at where Audiobookshelf can pick them up, or move them by hand
Troubleshooting log
| Date | Problem | Root cause | Fix |
|---|---|---|---|
| — | Port mappings were wrong at first | The published ports didn't line up with what qBittorrent was set to use | Corrected the mappings during setup |
What I'd harden next
- [ ] Check the torrent port: the compose sets
TORRENTING_PORT=6882but publishes51820. Confirm which port qBittorrent actually listens on (Settings → Connection) and make the two match. - [ ] Use the lab's usual
PGID=100and local time zone, like the other stacks
What I learned
- Rules shape architecture: one tracker's policy is why there are two download clients, and that's better than a single compromise
- Inside vs outside ports: what the app listens on and what Docker publishes have to line up, or connections silently fail