Verified live: indexers->Prowlarr->per-arr QBittorrent download clients with category routing. Readarr's client parked (qB proxy auth defect in abandoned upstream). EZTV/1337x parked with reason (CloudFlare-blocked at this egress); Nyaa/sukebei/RuTor/Byrutor/YTS passed live tests and are enabled. Prowlarr v2 Applications rows now carry real arr baseUrl+apiKeys; before this every sync attempt threw NullConfig in GetIndexerMappings.
414 lines
13 KiB
Markdown
414 lines
13 KiB
Markdown
# *arr Stack
|
||
|
||
The *arr suite is a collection of automated media management tools for Usenet and BitTorrent. For Dankserver — which runs Copyparty, Calibre-Web, RomM, and Jellyfin — the *arr stack provides automatic downloading and library management that Copyparty alone does not cover: quality profile enforcement, series/movie discovery, metadata enrichment, and automated file organization.
|
||
|
||
The core chain is: **Prowlarr** (indexer API aggregator) → **Sonarr/Radarr/Lidarr/Readarr** (media-specific managers) → **qBittorrent** (download client) → **Jellyfin** (media server scan → auto-refresh).
|
||
|
||
## Service Overview
|
||
|
||
| Service | Role | Image | Port | Min RAM |
|
||
|---------|------|-------|------|---------|
|
||
| Prowlarr | Indexer management | `lscr.io/linuxserver/prowlarr:latest` | 9696 | 256 MB |
|
||
| Radarr | Movie management | `lscr.io/linuxserver/radarr:latest` | 7878 | 512 MB |
|
||
| Sonarr | TV show management | `lscr.io/linuxserver/sonarr:latest` | 8989 | 512 MB |
|
||
| Lidarr | Music management | `lscr.io/linuxserver/lidarr:latest` | 8686 | 256 MB |
|
||
| Readarr | Ebook/audiobook management | `lscr.io/linuxserver/readarr:latest` | 8787 | 256 MB |
|
||
| qBittorrent | Torrent download client | `lscr.io/linuxserver/qbittorrent:latest` | 8080 | 512 MB |
|
||
| Jackett | Indexer proxy (optional) | `lscr.io/linuxserver/jackett:latest` | 9117 | 256 MB |
|
||
| Whisparr | NSFW movie management (optional) | `lscr.io/linuxserver/whisparr:latest` | 6969 | 256 MB |
|
||
|
||
**Minimum total RAM:** ~3 GB for full stack (headroom recommended).
|
||
|
||
## Architecture
|
||
|
||
```mermaid
|
||
graph LR
|
||
I[Indexers<br/>Torrents, Usenet] --> P[Prowlarr<br/>Indexer Manager]
|
||
P --> S[Sonarr<br/>TV]
|
||
P --> R[Radarr<br/>Movies]
|
||
P --> L[Lidarr<br/>Music]
|
||
P --> Rd[Readarr<br/>Books]
|
||
S --> Q[qBittorrent]
|
||
R --> Q
|
||
L --> Q
|
||
Rd --> Q
|
||
Q --> M1[/tv/]
|
||
Q --> M2[/movies/]
|
||
Q --> M3[/music/]
|
||
Q --> M4[/books/]
|
||
M1 --> J[Jellyfin]
|
||
M2 --> J
|
||
M3 --> J
|
||
M4 --> CW[Calibre-Web]
|
||
```
|
||
|
||
## Docker Compose
|
||
|
||
```yaml
|
||
networks:
|
||
appnet:
|
||
driver: bridge
|
||
|
||
services:
|
||
prowlarr:
|
||
image: lscr.io/linuxserver/prowlarr:latest
|
||
container_name: prowlarr
|
||
restart: unless-stopped
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/New_York
|
||
- UMASK_SET=022
|
||
volumes:
|
||
- /opt/prowlarr/config:/config
|
||
- /mnt/media/downloads:/downloads:ro
|
||
ports:
|
||
- "9696:9696"
|
||
networks: [appnet]
|
||
|
||
radarr:
|
||
image: lscr.io/linuxserver/radarr:latest
|
||
container_name: radarr
|
||
restart: unless-stopped
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/New_York
|
||
- UMASK_SET=022
|
||
volumes:
|
||
- /opt/radarr/config:/config
|
||
- /mnt/media/movies:/movies
|
||
- /mnt/media/downloads:/downloads
|
||
ports:
|
||
- "7878:7878"
|
||
networks: [appnet]
|
||
|
||
sonarr:
|
||
image: lscr.io/linuxserver/sonarr:latest
|
||
container_name: sonarr
|
||
restart: unless-stopped
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/New_York
|
||
- UMASK_SET=022
|
||
volumes:
|
||
- /opt/sonarr/config:/config
|
||
- /mnt/media/tv:/tv
|
||
- /mnt/media/downloads:/downloads
|
||
ports:
|
||
- "8989:8989"
|
||
networks: [appnet]
|
||
|
||
lidarr:
|
||
image: lscr.io/linuxserver/lidarr:latest
|
||
container_name: lidarr
|
||
restart: unless-stopped
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/New_York
|
||
- UMASK_SET=022
|
||
volumes:
|
||
- /opt/lidarr/config:/config
|
||
- /mnt/media/music:/music
|
||
- /mnt/media/downloads:/downloads
|
||
ports:
|
||
- "8686:8686"
|
||
networks: [appnet]
|
||
|
||
readarr:
|
||
image: lscr.io/linuxserver/readarr:latest
|
||
container_name: readarr
|
||
restart: unless-stopped
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/New_York
|
||
- UMASK_SET=022
|
||
volumes:
|
||
- /opt/readarr/config:/config
|
||
- /mnt/media/books:/books
|
||
- /mnt/media/downloads:/downloads
|
||
ports:
|
||
- "8787:8787"
|
||
networks: [appnet]
|
||
|
||
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]
|
||
|
||
# Optional: Jackett for niche indexers
|
||
jackett:
|
||
image: lscr.io/linuxserver/jackett:latest
|
||
container_name: jackett
|
||
restart: unless-stopped
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/New_York
|
||
- UMASK_SET=022
|
||
volumes:
|
||
- /opt/jackett/config:/config
|
||
- /opt/jackett/torrences:/torrences
|
||
ports:
|
||
- "9117:9117"
|
||
networks: [appnet]
|
||
|
||
# Optional: Whisparr for adult content
|
||
whisparr:
|
||
image: lscr.io/linuxserver/whisparr:latest
|
||
container_name: whisparr
|
||
restart: unless-stopped
|
||
environment:
|
||
- PUID=1000
|
||
- PGID=1000
|
||
- TZ=America/New_York
|
||
- UMASK_SET=022
|
||
volumes:
|
||
- /opt/whisparr/config:/config
|
||
- /mnt/media/whisparr-movies:/whisparr-movies
|
||
- /mnt/media/downloads:/downloads
|
||
ports:
|
||
- "6969:6969"
|
||
networks: [appnet]
|
||
```
|
||
|
||
## Caddy Configuration
|
||
|
||
```caddy
|
||
radarr.dankserver.local {
|
||
reverse_proxy localhost:7878
|
||
}
|
||
|
||
sonarr.dankserver.local {
|
||
reverse_proxy localhost:8989
|
||
}
|
||
|
||
lidarr.dankserver.local {
|
||
reverse_proxy localhost:8686
|
||
}
|
||
|
||
readarr.dankserver.local {
|
||
reverse_proxy localhost:8787
|
||
}
|
||
|
||
prowlarr.dankserver.local {
|
||
reverse_proxy localhost:9696
|
||
}
|
||
|
||
qbittorrent.dankserver.local {
|
||
reverse_proxy localhost:8080
|
||
}
|
||
|
||
# Optional: Jackett
|
||
jackett.dankserver.local {
|
||
reverse_proxy localhost:9117
|
||
}
|
||
|
||
# Optional: Whisparr
|
||
whisparr.dankserver.local {
|
||
reverse_proxy localhost:6969
|
||
}
|
||
```
|
||
|
||
## Configuration Steps
|
||
|
||
### Phase 1: Download Client
|
||
|
||
1. Deploy qBittorrent first (or Transmission).
|
||
2. In the qBittorrent Web UI, set **No auth mode** for LAN (Settings → Web UI).
|
||
3. Create download categories: `movies`, `tv`, `music`, `books`.
|
||
4. Change the default Web UI password.
|
||
|
||
### Phase 2: Indexer Management
|
||
|
||
1. Deploy Prowlarr.
|
||
2. Add indexers (3–5 recommended for testing). Use the **Test** button on each.
|
||
3. Add qBittorrent as a download client in Prowlarr.
|
||
4. Verify search from the Prowlarr web UI.
|
||
|
||
### Phase 3: Arr Apps (one at a time)
|
||
|
||
1. Deploy Sonarr first (TV shows are the most common use case).
|
||
2. Add Prowlarr as the indexer source (Settings → Indexers → Add Prowlarr).
|
||
3. Add qBittorrent as the download client with categories.
|
||
4. Add a test series. Wait for the episode to download. Verify in `/tv/`.
|
||
5. Repeat for Radarr, Lidarr, Readarr.
|
||
|
||
### Phase 4: Media Server Integration
|
||
|
||
1. Configure Jellyfin libraries pointing to `/movies`, `/tv`, `/music`, `/books`.
|
||
2. Set **On Download** notifications in each arr app → Jellyfin webhook URL.
|
||
3. Test end-to-end: Add a movie in Radarr → download → verify in Jellyfin.
|
||
|
||
## Quality Profiles
|
||
|
||
Each arr app uses a hierarchical quality system:
|
||
|
||
1. **Quality Profile** — Defines tiers (e.g., 2160p → 1080p BluRay → 720p).
|
||
2. **Cutoff** — The quality target. Downloads at or above cutoff are accepted.
|
||
3. **Custom Formats** — Additional filters (e.g., "Has HDR", "Is Director's Cut").
|
||
4. **Search on Grab** — When content becomes available, all indexers are queried.
|
||
|
||
### Radarr (Movies)
|
||
|
||
```
|
||
Profile: Movies 4K
|
||
Tiers:
|
||
1. 2160p BluRay REMUX
|
||
2. 2160p BluRay
|
||
3. 2160p WEB-DL
|
||
4. 1080p BluRay
|
||
5. 1080p WEB-DL
|
||
6. 720p
|
||
Cutoff: 1080p BluRay
|
||
```
|
||
|
||
### Sonarr (TV)
|
||
|
||
```
|
||
Profile: TV - Standard
|
||
Tiers: 2160p → 1080p → 720p
|
||
Min Size: 500 MB
|
||
Max Size: 50 GB
|
||
Cutoff: 1080p
|
||
Language Profile: English audio preferred
|
||
```
|
||
|
||
### Lidarr (Music)
|
||
|
||
```
|
||
Profile: Music - Standard
|
||
Tiers: Lossless (FLAC) → 320 kbps → 192 kbps
|
||
Cutoff: 320 kbps (or Lossless)
|
||
```
|
||
|
||
## Metadata Sources
|
||
|
||
| App | Primary Source | Secondary |
|
||
|-----|---------------|-----------|
|
||
| Radarr | TMDB | TheMovieDB API |
|
||
| Sonarr | TMDB | TVDB |
|
||
| Lidarr | MusicBrainz | — |
|
||
| Readarr | Goodreads, StoryGraph | — |
|
||
| Whisparr | XH | TMDB |
|
||
|
||
## *arr Stack vs Copyparty
|
||
|
||
| Feature | Copyparty | *arr Stack |
|
||
|---------|-----------|------------|
|
||
| Auto-download from torrents | Basic (RSS + scripts) | Native, integrated |
|
||
| Quality profiles | No | Multi-tier, custom formats |
|
||
| Series/movie tracking | No | Watch lists, air dates |
|
||
| Manual library management | Yes | Yes, metadata-driven |
|
||
| Multi-user watchlists | No | Yes |
|
||
| Complexity | Low | Medium |
|
||
| Resource usage | Minimal | Moderate |
|
||
|
||
Use Copyparty for curated file collections. Use *arr for automatic downloads. Use both together for maximum functionality — point *arr download directories at Copyparty's watched folders.
|
||
## Live State (as-built, verified 2026-08-29)
|
||
|
||
Deployed shape differs from the design compose above — reality wins:
|
||
|
||
- Mounts are the real array paths (`/mnt/entropy/downloads`, case-exact dirs
|
||
like `Movies`/`TVShows`), not `/mnt/media/*`; TZ is `America/Los_Angeles`.
|
||
- Readarr runs `lscr.io/linuxserver/readarr:amd64-1.0.980` — LSIO ships no
|
||
untagged `latest` for readarr; the tag was pinned after a manifest probe.
|
||
- Prowlarr's `/config` mount was missing mid-deploy (off-by-one in an edit);
|
||
restored in commit `67695cf`.
|
||
- **Auth posture: every arr runs `AuthenticationMethod=None` +
|
||
`AuthenticationRequired=Enabled`** — verified live via each config.xml and by
|
||
probing `/api/v3/system/status` unauthenticated (401 on all five, local and
|
||
through the vhost). Net effect: a login screen with **zero users defined**;
|
||
whoever creates the first account owns the instance. Decide the auth method
|
||
(`None` behind the Anubis wall vs `External` via authentik) *before* WAN
|
||
exposure — first-account-wins is the current race condition.
|
||
- API keys live in each `/config/config.xml` (`<ApiKey>`); they are local-only
|
||
secrets and stop being secret the moment a vhost serves the API unauthenticated.
|
||
### Chain wiring (verified live 2026-08-29)
|
||
|
||
The download chain is wired and test-first verified: **indexers → Prowlarr →
|
||
per-arr qBittorrent clients (category = app name) → import**.
|
||
|
||
- qB webUI auth is ON (`admin` + generated password; verify before writing it
|
||
into any config — it was generated at first boot, not a default).
|
||
- Per-arr QBittorrent download clients exist on sonarr/radarr/lidarr
|
||
(enabled) and readarr (**parked**: its qB proxy fails auth live even with
|
||
correct creds — known defect of the abandoned upstream; do not enable until
|
||
the image changes). Each was **tested before enabling**; failures stay parked
|
||
with a reason, never enabled blind.
|
||
- Prowlarr runs v2.5.2 where apps are first-class rows (`Applications` table):
|
||
four Application rows (sonarr/radarr/lidarr/readarr) now carry each arr's
|
||
real baseUrl+apiKey with `SyncLevel=FullSync`. Before this, the table was
|
||
empty and every sync attempt threw `NullConfig` in `GetIndexerMappings()` —
|
||
visible in `podman logs prowlarr`, not in any UI.
|
||
- Indexers are **test-before-enable**: EZTV and 1337x stay disabled with reason
|
||
"blocked by CloudFlare Protection" (this host's egress ASN is CF-blocked at
|
||
those trackers); Nyaa.si, sukebei, RuTor, Byrutor, YTS passed live tests and
|
||
are enabled. A failed test = parked with reason, never enabled blind.
|
||
- Prowlarr v2 sync model: indexers stay in Prowlarr; arrs search *through* it
|
||
and hand off to their own qB download client (category routing). Mappings
|
||
materialize at grab time — zero mappings right after wiring is expected,
|
||
not a fault.
|
||
|
||
## Disk Layout
|
||
|
||
```
|
||
/mnt/media/
|
||
├── movies/ → Radarr root
|
||
├── tv/ → Sonarr root
|
||
├── music/ → Lidarr root
|
||
├── books/ → Readarr root
|
||
├── whisparr-movies/ → Whisparr root
|
||
├── downloads/ → qBittorrent download dir
|
||
│ ├── movies/
|
||
│ ├── tv/
|
||
│ ├── music/
|
||
│ └── books/
|
||
└── incomplete/ → qBittorrent incomplete downloads
|
||
```
|
||
|
||
## Gotchas
|
||
|
||
- **Timezone mismatch:** All containers should use the same TZ. Sonarr's scheduler is timezone-sensitive.
|
||
- **File permissions:** Set `umask=022` in qBittorrent. Ensure arr apps can read/move downloaded files.
|
||
- **Network conflicts:** *arr apps use many ports. Check for conflicts with existing Dankserver services.
|
||
- **Prowlarr API key rotation:** If rotated, update it in every arr app.
|
||
- **qBittorrent Web UI password:** Change default on first run.
|
||
- **Readarr stability:** Readarr is still in development. Do not rely on it for mission-critical collections.
|
||
- **Whisparr separate Jellyfin library:** Keep adult content separate from regular media.
|
||
- **RSS feed in qBittorrent:** Can auto-add torrents matching a pattern. Useful for podcast-like series.
|
||
|
||
## Best Practices
|
||
|
||
1. Use tags to route content to specific download clients or categories.
|
||
2. Enable the Blocklist in arr apps to prevent re-downloading failed torrents.
|
||
3. Set download limits in qBittorrent to avoid bandwidth saturation.
|
||
4. Back up arr configs regularly (they are small SQLite DBs + JSON).
|
||
5. Monitor Prowlarr indexer health — broken indexers hide new content.
|
||
6. Start with default quality profiles. Add custom formats gradually.
|
||
7. Back up arr configs: `./radarr/config`, `./sonarr/config`, etc.
|
||
|
||
## See Also
|
||
|
||
- [[Dankserver Stack]]
|
||
- [[Jellyfin]] — media server that consumes *arr downloads
|
||
- [[Copyparty]] — alternative file viewer
|
||
- [[Calibre-Web]] — manual ebook management (Readarr auto-downloads into the same library)
|
||
- [Sonarr Wiki](https://wiki.servarr.com/sonarr)
|
||
- [Radarr Wiki](https://wiki.servarr.com/radarr)
|