9.9 KiB
122 — arriman
Docker host running the *arr stack via ezarr compose. Replaced the old yunohost-based LXC 100 on 2026-04-21.
At a glance
- Hostname:
arriman - IP:
192.168.8.132 - Privilege: privileged
- Resources: 4 cores / 8 GiB RAM / 24 GiB rootfs
- Mounts:
/mnt/library↔/mnt/library - Public hostnames:
jellyseerr/qbit/sab(see below)
Compose
/home/arr/ezarr/docker-compose.yml. Network ezarr_default 172.18.0.0/16. Service users all run with primary GID 10000 (host media group) inside their containers — see media permissions. Per-app /config/<app>-config/ dirs bind to /config inside.
.env contents:
DOWNLOADS_DIR=/mnt/library/downloads/MEDIA_DIR=/mnt/library/MEDIACENTER_GID=10000← must be 10000, not 13000. s6-setuidgid only honors the primary PGID;group_add:doesn't propagate. Without this, qBit errors every torrent with "Permission denied".SONARR_UID=13001,RADARR_UID=13002,LIDARR_UID=13003,PROWLARR_UID=13006,JELLYSEERR_UID=13012,BAZARR_UID=13013,QBITTORRENT_UID,SABNZBD_UID
Service / port map
All services route through gluetun's network namespace. Ports are exposed via the gluetun container:
| Service | Host:Container | Public hostname |
|---|---|---|
| gluetun (VPN) | — | — |
| sonarr | 8989:8989 |
direct only (via gluetun) |
| radarr | 7878:7878 |
direct only (via gluetun) |
| lidarr | 8686:8686 |
direct only (via gluetun) |
| prowlarr | 9696:9696 |
direct only (via gluetun) |
| bazarr | 6767:6767 |
direct only (via gluetun) |
| jellyseerr | 5056:5055 |
jellyseerr.hubris.network |
| qbittorrent | 8080:8080 |
qbit.hubris.network |
| sabnzbd | 8082:8082 HTTP, 9090:9090 HTTPS |
sab.hubris.network |
| flaresolverr | 8191:8191 |
internal only |
| homarr | 7575:7575 |
internal only |
Internal *arr ↔ *arr / *arr ↔ qBit/SAB/flaresolverr comms run on localhost:<port>
(services share gluetun's shared network namespace). External services reach them
via gluetun:<port> (e.g. Sonarr → qBittorrent at localhost:8080 or
gluetun:8080).
Categories (qBit + SAB + *arr)
| Category | qBit savePath | SAB dir | Consumer |
|---|---|---|---|
| tv | /data/torrents/tv |
tv | Sonarr |
| movies | /data/torrents/movies |
movies | Radarr |
| music | /data/torrents/music |
music | Lidarr |
| anime | /data/torrents/anime |
anime | Sonarr (2nd download client, root /data/media/anime) |
| books / audiobooks / comics / podcasts | /data/torrents/<cat> |
<cat> |
(reserved, none in use yet) |
Path mapping: host /mnt/library/<cat> ↔ container /data/media/<cat>. Downloads: host /mnt/library/downloads/<torrents|usenet>/<cat> ↔ container /data/torrents/<cat> and /data/usenet/<cat>.
Auth (reverse-proxy + Authentik forward-auth)
qBit
Auto-login behind forward-auth via IP whitelist. qBittorrent.conf lines:
WebUI\\AuthSubnetWhitelist=172.18.0.0/16, 172.17.0.0/16, 192.168.8.175/32WebUI\\ReverseProxySupportEnabled=trueWebUI\\TrustedReverseProxiesList=192.168.8.175, 172.18.0.0/16
Stop the container before editing
qBittorrent.conf. qBit writes its in-memory config on graceful shutdown and clobbers any live edits. Recipe:docker stop qbittorrent && sed -i ... && docker start qbittorrent.
Mobile/desktop clients keep working via /api/v2/* path bypass on Caddy.
SABnzbd
Gated with Authentik forward-auth (applied 2026-06-13). Caddy sab.hubris.network block uses import authentik inside a handle block. SABnzbd's own web auth is disabled:
html_login = 0→ no HTML login formusername/passwordcleared → CherryPy Basic Auth not activatedlocal_ranges = 172.18.0.0/16, 192.168.8.0/24, 127.0.0.0/8→ proxied requests from Caddy (192.168.8.x) and Docker-proxy (172.18.x) pass without auth
API key (67ef5a45e4e04157994e977005a33878) still works for internal service-to-service calls (Sonarr/Radarr/Lidarr via Docker internal networking — they talk to SAB at localhost:8082, not through Caddy).
host_whitelist: sabnzbd, localhost, 127.0.0.1, 192.168.8.132, sab.hubris.network — extend before accessing SAB from a new host.
Credentials
Backups of all migration-time secrets at /mnt/library/backup/arr-migration-2026-04-21/state/:
lxc100-apikey-{sonarr,radarr,prowlarr,lidarr}.txtqbit-creds.txt,sab-creds.txtlxc100-jellyseerr-settings.json
*arr API keys were preserved from the yunohost DB — don't rotate unless needed.
qBittorrent: admin / CDyjxMKvjfGupCKzXFkjsKw4nRrXMRL.
Migration gotchas (apply if ever re-importing)
- Imported *arr
config.xml: must have<BindAddress>*</BindAddress>,<Port>{ezarr-port}</Port>,<UrlBase></UrlBase>. Otherwise app listens only on 127.0.0.1, wrong port, wrong path. - Imported DB paths must be rewritten
/mnt/library/→/data/media/(RootFolders / Series / Movies / Artists tables). Without this, scans and imports fail silently. - Bazarr
config/config.yaml(yaml, not ini) —ip: 0.0.0.0,port: 6767, empty top-levelbase_url; sonarr/radarr connection sections normalized to docker service names. - Staging dir for migrations:
/mnt/library/backup/stage/<app>/(visible to both old LXC 100 and arriman because both bind-mount the same host path).
Permissions
Member of media GID 10000. The LXC has www-data, audiobookshelf, radarr, sonarr, lidarr, prowlarr, qbittorrent, bazarr, jellyseerr, mylar, jackett, overseerr, plex, arr in the media group. Each docker container also receives GID 10000 as its primary group via MEDIACENTER_GID=10000.
Rollback material (kept until 2026-04-28+)
/mnt/library/backup/arr-migration-2026-04-21/:
tars/— per-subtree tars of yunohost app data (granular restore)snapshots/— vzdumps of LXC 100 (pre-migration) and LXC 122 (pre-import), plus post-stop vzdumps of LXC 100 + 106stage/<app>-preimport.tar.gz— original empty ezarr/config/<app>-config/dirsstate/— service dumps, listening ports, API keys, jellyseerr settings at migration timeDESTROY_AFTER_2026-04-28.md— destroy checklist + post-destroy restore commands
Related
- Caddy (121)
- Authentik (124) — forward-auth wiring + per-app
/api/*bypass - DNS
- Media permissions
- Hubris host
Changelog
2026-06-13 — SABnzbd gated with Authentik forward-auth
SABnzbd now uses Authentik forward-auth (same import authentik Caddy pattern as qBit). SABnzbd's own web auth disabled: html_login=0, credentials cleared, local_ranges extended to cover Docker bridge + homelab LAN. API key still works for internal *arr service calls. See Auth section above.
2026-06-04 — all arr services moved behind gluetun VPN; SAB port conflict fixed
- All services (sonarr, radarr, lidarr, bazarr, prowlarr, jellyseerr, homarr,
flaresolverr) now use
network_mode: service:gluetun— whole stack routes through the VPN - Port mappings moved from individual services to gluetun container
- Fixed SABnzbd port conflict: was crashing in a restart loop because
qBittorrent held port 8080 inside the shared gluetun namespace. Changed
SAB internal port to 8082 (config at
/config/sabnzbd-config/sabnzbd.ini) - Caddy
sab.hubris.networkupdated to point to:8082 - Jellyseerr's
extra_hosts(auth.hubris.network) moved to gluetun sinceextra_hostsconflicts withnetwork_mode
2026-06-02 — ProtonVPN added (gluetun); LXC IP set static
- Added
gluetuncontainer to compose as a WireGuard VPN sidecar (ProtonVPN, server AL#57, located in Tirana, Albania) - qbittorrent and sabnzbd now use
network_mode: service:gluetun— all traffic routes through the VPN - Ports 8080 (qBit WebUI), 6881 tcp/udp (qBit BT), 8081 (SAB WebUI) exposed through gluetun
- gluetun config at
gluetun-config/wireguard/wg0.conf(read-only mount) - Healthcheck on gluetun; qBit/SAB wait for
service_healthybefore starting - LXC IP changed from DHCP to static (
192.168.8.132) viapct set+/etc/network/interfaces - After first start: Sonarr/Radarr/Lidarr download client host needs updating from
qbittorrent→gluetun(SAB similarlysabnzbd→gluetun) - Also fixed: 7 other DHCP LXCs (101 jellyfin, 103 paperless, 104 gitea, 105 apps, 114 nextcloud, 118 elementsynapse, 120 mule-images, 121 caddy) set to static IPs to prevent floating on reboot. See infrastructure/dns.md.
2026-04-28 — wiki entry created
Initial documentation.
2026-04-26 — MEDIACENTER_GID flipped 13000 → 10000
qBit was erroring every torrent with "Permission denied" because s6-setuidgid only honors the primary PGID and group_add: doesn't propagate. Setting the primary GID to 10000 (the host media group) fixed it.
2026-04-21 — *arr stack migrated yunohost → docker-compose
Old LXC 100 stopped; ezarr stack stood up here; data and DBs imported with path rewrites. flaresolverr folded in from old LXC 106. Three Caddy sites added (jellyseerr, qbit, sab) → see caddy. Rollback artifacts under /mnt/library/backup/arr-migration-2026-04-21/.