Media Stack¶
Nota (2026-07-17): Lidarr está de vuelta con un pipeline de música basado en Soulseek (Lidarr + slskd + soularr) — ya no usa Deemix ni torrents como fuente principal. Ver Music Acquisition (Soulseek) abajo.
Core media automation and streaming services. Always running.
| Compose file | media/compose.yaml |
| Status | Always on |
| Dependencies | NFS mount at /mnt/nfs_media |
Architecture¶
┌──────────────┐
│ Jellyseerr │ ← User requests
│ :5055 │
└──────┬───────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Sonarr │ │ Radarr │ │ Lidarr │
│ :8989 │ │ :7878 │ │ :8686 │
└────┬─────┘ └────┬─────┘ └──────────┘
│ │
└────────┬───────┘
▼
┌─────────────────────────┐
│ Prowlarr │ ← Indexer management
│ :9696 │
│ (FlareSolverr :8191) │
└─────────────┬───────────┘
│
┌─────────────▼───────────┐
│ Plundrio │ ← Put.io downloader
│ :9091 │
└─────────────┬───────────┘
│
┌─────────────▼───────────┐ ┌──────────────┐
│ Plundrio-Scanner │────▶│ Plundrio- │
│ :8086 │ │ Hunter :8087 │
└─────────────────────────┘ └──────────────┘
│
▼
┌─────────────────────────┐
│ Jellyfin │ ← Streaming
│ :8096 │
└─────────────┬───────────┘
│
┌───────┴───────┐
▼ ▼
┌──────────┐ ┌──────────┐
│ Jellystat│ │ Tunarr │
│ :3100 │ │ :8555 │
└──────────┘ └──────────┘
Services¶
Media Management¶
| Service | Port | Image | Purpose |
|---|---|---|---|
| Sonarr | 8989 | linuxserver/sonarr | TV show automation |
| Radarr | 7878 | linuxserver/radarr | Movie automation |
| Lidarr | 8686 | lscr.io/linuxserver/lidarr | Music library + wanted list (Soulseek acquisition — ver Music) |
| Bazarr | 6767 | linuxserver/bazarr | Subtitle management |
| Prowlarr | 9696 | linuxserver/prowlarr | Indexer management |
| FlareSolverr | 8191 | flaresolverr/flaresolverr | Cloudflare bypass proxy |
Download Management (Plundrio Ecosystem)¶
Custom Put.io integration built locally. See ~/plundrio/README.md (separate git repo).
| Service | Port | Purpose | Watchtower |
|---|---|---|---|
| Plundrio | 9091 | Put.io download client | Yes |
| Plundrio-Scanner | 8086 | Verifies imports, cleans up, cancels dead torrents; ManualImport fallback + orphan sweep (2026-07-16: fixes files DownloadedEpisodesScan silently skips — season packs / tracker-prefixed names) |
No (custom build) |
| Plundrio-Hunter | 8087 | Proactively searches for missing media | No (custom build) |
Key settings (turbo-boosted):
- PLDR_WORKERS=6 - Parallel download threads
- POLL_INTERVAL=20 - Scanner checks every 20s
- HUNT_BATCH_SIZE=6 - Items per hunt cycle
- HOURLY_CAP=60 - Max searches per hour
Music Acquisition (Soulseek)¶
Re-added 2026-07-17. Music uses a Soulseek pipeline (not torrents/Deemix as the primary source) — Soulseek has the best coverage for 2000s / back-catalog music. Repo: plundrio-ecosystem is unrelated; these are stock images + config.
| Service | Port | Image | Purpose |
|---|---|---|---|
| Lidarr | 8686 | lscr.io/linuxserver/lidarr | Music library + wanted/missing list |
| slskd | 5030 / 50300 | slskd/slskd | Soulseek daemon (search + download) |
| soularr | 8265 | ghcr.io/mrusse/soularr | Bridge: Lidarr wanted → slskd → import |
Flow: Lidarr catalogues each artist's discography → marks missing albums → soularr reads the wanted list, searches slskd (Soulseek), downloads FLAC/MP3 to /downloads/soulseek/complete, then triggers Lidarr to import into /data/music.
Config & tuning:
- Library root:
/data/music(/mnt/nfs_media/music); Soulseek downloads land in/mnt/nfs_media/downloads/soulseek/. slskd.yml(~/appdata/slskd/): Soulseek creds + web login + an API key for soularr. Shares/musicread-only.- soularr
config.ini(~/appdata/soularr/), tuned for max coverage:allowed_filetypes = flac,mp3,minimum_filename_match_ratio = 0.4,number_of_albums_to_grab = 30,search_type = incrementing_page,search_source = all. - Lidarr quality profile = Any for all artists (accepts SD/MP3 → lossless), so nothing is rejected on quality.
- Secondary source: Lidarr also grabs music torrents via Putioarr (the plundrio Transmission client) + Prowlarr indexers. Download client category is empty so it resolves to
/data/downloads(flat, where plundrio writes).
Indexers (Prowlarr, expanded 2026-07-16): added EZTV, 1337x, LimeTorrents, Knaben, Nyaa.si, RuTor, RuTracker.org — 1337x / EZTV / RuTracker route through FlareSolverr (tagged cloudflare). RuTracker needs a (free) account.
External access: lidarr / slskd / soularr.monxas.casa — routed by homelab-ctl sync (tunnel.hostname labels) behind CF Access / PocketID.
Streaming & Stats¶
Música → doc dedicado
El streaming de música (Navidrome), la curación de metadatos (beets), letras, ReplayGain, smart playlists y la radio por IA (AudioMuse-AI) tienen su propio doc: Música — Navidrome + AudioMuse-AI.
| Service | Port | Purpose |
|---|---|---|
| Jellyfin | 8096 | Media streaming server |
| Navidrome | 4533 | Music streaming (Subsonic) — ver doc dedicado |
| Jellyseerr | 5055 | Request management UI |
| Jellystat | 3100 | Viewing statistics dashboard |
| Tunarr | 8555 | Custom TV channels from library |
| Audiobookshelf | 13378 | Podcast/audiobook server |
Sharing & Utilities¶
| Service | Port | Purpose |
|---|---|---|
| Jellyfin-Share | 8097 | Temporary shareable links |
| ntfy | 8082 | Push notifications |
| Torrentland-Torznab | 5075 | Custom indexer scraper |
| Beszel-Agent | 45876 | System metrics agent |
Data Paths¶
| Container Path | Host Path | Purpose |
|---|---|---|
/data |
/mnt/nfs_media |
Full NAS mount |
/downloads |
/mnt/nfs_media/downloads |
Download staging |
/config |
/home/monxas/appdata/<service> |
Service config |
Dependencies¶
FlareSolverr (no deps)
└── Prowlarr
├── Sonarr
├── Radarr
└── Lidarr
Plundrio (no deps)
└── Plundrio-Scanner
└── Plundrio-Hunter
Jellyfin (no deps)
├── Jellyseerr
├── Jellystat → jellystat-db
├── Tunarr
└── Jellyfin-Share → jellyfin-share-db
ntfy (no deps) ← Used by Scanner, Hunter
Rebuilding Custom Services¶
Plundrio-Scanner and Hunter are built from local source:
cd ~/stacks/media
# Rebuild after code changes
docker compose build plundrio-scanner plundrio-hunter
# Restart with new build
docker compose up -d plundrio-scanner plundrio-hunter
# Force rebuild without cache
docker compose build --no-cache plundrio-scanner
Environment Variables¶
Key environment variables for this stack (from ~/.env):
| Variable | Used By | Description |
|---|---|---|
SONARR_API_KEY |
Scanner, Hunter | Sonarr API access |
RADARR_API_KEY |
Scanner, Hunter | Radarr API access |
PUTIO_TOKEN |
Plundrio, Scanner, Hunter | Put.io OAuth token |
PLUNDRIO_USER |
All Plundrio services | RPC authentication |
PLUNDRIO_PASS |
All Plundrio services | RPC authentication |
JELLYFIN_API_KEY |
Jellystat, JF-Share | Jellyfin API access |
POSTGRES_PASSWORD |
jellystat-db, jf-share-db | Database password |
Troubleshooting¶
Plundrio not downloading?
# Check health
curl -s "http://localhost:9091/health" -u "monxas:$PLUNDRIO_PASS" # ver secrets.local.md
# Check Put.io slots
curl -s "https://api.put.io/v2/transfers/list?oauth_token=YOUR_TOKEN" | jq '.transfers | length'
Scanner not importing?
# Check dashboard
open http://localhost:8086
# Check logs
docker logs plundrio-scanner -f --tail 100
Sonarr/Radarr not finding releases?
# Check Prowlarr indexers
open http://localhost:9696
# Test FlareSolverr
curl -X POST "http://localhost:8191/v1" -H "Content-Type: application/json" \
-d '{"cmd":"request.get","url":"https://example.com"}'
Downloads stalled / queue not draining?
Dead torrents (no seeders) pile up on put.io in WAITING and clog the download slots so
good transfers never start. Purge them — Sonarr's autoRedownloadFailed then re-searches
for seeded alternatives:
TOKEN=$(grep ^PUTIO_TOKEN= ~/.env | cut -d= -f2-)
# IDs of the dead ones (ERROR, or WAITING/DOWNLOADING with availability 0 and no speed):
IDS=$(curl -s "https://api.put.io/v2/transfers/list" -H "Authorization: Bearer $TOKEN" | \
jq -r '.transfers[] | select(.status=="ERROR" or ((.status=="WAITING" or .status=="DOWNLOADING") and (.availability//0)==0 and (.down_speed//0)==0)) | .id' | paste -sd,)
# cancel them:
curl -s -X POST "https://api.put.io/v2/transfers/cancel" -H "Authorization: Bearer $TOKEN" \
--data-urlencode "transfer_ids=$IDS"
(plundrio-hunter also detects + removes dead torrents over time.)