Managing a media library manually is tedious. Tracking new episodes, finding quality upgrades, organizing files — it all adds up. The Arr stack automates the entire pipeline: from request to download to organized library, ready for streaming.
This guide walks you through deploying the complete Arr stack with Docker Compose, connecting all the pieces, and getting automated media management running on your server.
What Is the Arr Stack?
The “Arr” ecosystem is a collection of open-source applications that work together:
| Application | Role | What It Does |
|---|---|---|
| Sonarr | TV Series Manager | Monitors, downloads, and organizes TV shows |
| Radarr | Movie Manager | Monitors, downloads, and organizes movies |
| Prowlarr | Indexer Manager | Manages indexers/trackers for Sonarr and Radarr |
| Jellyseerr | Request Portal | Users request media through a clean UI |
| Jellyfin/Plex | Media Server | Streams your library to all devices |
The flow: User requests → Jellyseerr → Sonarr/Radarr → Prowlarr (finds sources) → Download client → Organized library → Jellyfin/Plex.
Why This Stack?
- Fully automated — new episodes download and organize themselves
- Quality upgrades — automatically replaces low-quality files with better versions
- User requests — family/friends request content through Jellyseerr
- Centralized indexers — Prowlarr syncs indexer config across all apps
- Metadata and renaming — files are renamed and organized consistently
Prerequisites
- A Linux server with Docker and Docker Compose
- At least 2GB RAM (4GB+ recommended for the full stack)
- Storage for your media library (HDD is fine for media)
- A download client installed (we’ll cover setup with qBittorrent or SABnzbd)
- Basic understanding of Docker networking
Step 1: Directory Structure
Create a clean directory structure. The Arr apps need access to both their config and your media paths:
mkdir -p ~/arr-stack/{sonarr,radarr,prowlarr,jellyseerr,qbittorrent}/{config}
mkdir -p /data/media/{movies,tv,downloads/{complete,incomplete}}
The /data/media structure is important. All containers must see the same path to enable hardlinks (instant moves instead of copies):
Key concept: Mount the same
/data/mediapath in every container. This enables hardlinks between downloads and library folders, saving disk space and avoiding slow copy operations.
Step 2: Docker Compose Setup
Create your docker-compose.yml:
services:
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
volumes:
- ./prowlarr/config:/config
ports:
- "9696:9696"
restart: unless-stopped
sonarr:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
volumes:
- ./sonarr/config:/config
- /data/media:/data/media
ports:
- "8989:8989"
restart: unless-stopped
radarr:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
volumes:
- ./radarr/config:/config
- /data/media:/data/media
ports:
- "7878:7878"
restart: unless-stopped
jellyseerr:
image: fallenbagel/jellyseerr:latest
container_name: jellyseerr
environment:
- TZ=America/New_York
volumes:
- ./jellyseerr/config:/app/config
ports:
- "5055:5055"
restart: unless-stopped
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- WEBUI_PORT=8080
volumes:
- ./qbittorrent/config:/config
- /data/media/downloads:/data/media/downloads
ports:
- "8080:8080"
- "6881:6881"
- "6881:6881/udp"
restart: unless-stopped
Set the correct PUID and PGID (run id to check yours), then start everything:
docker compose up -d
Step 3: Configure the Download Client
qBittorrent is the most popular choice with the Arr stack.
- Open qBittorrent at
http://your-server:8080 - Check the container logs for the temporary password:
docker logs qbittorrent - Log in and go to Tools → Options → Downloads
- Set Default Save Path to
/data/media/downloads/complete - Set Incomplete Save Path to
/data/media/downloads/incomplete - Under Web UI, change the default password
Using Usenet instead? Replace qBittorrent with SABnzbd (
lscr.io/linuxserver/sabnzbd). The Arr apps support both torrent and Usenet clients — or both simultaneously.
Step 4: Configure Prowlarr (Indexer Manager)
Prowlarr is the hub for all your indexers. Configure it once, and it syncs to Sonarr and Radarr automatically.
- Open Prowlarr at
http://your-server:9696 - Set up authentication under Settings → General (required)
- Add indexers under Indexers → Add Indexer — search for your preferred indexers and add credentials
- Connect your Arr apps under Settings → Apps:
- Click +, select Sonarr
- Prowlarr Server:
http://prowlarr:9696 - Sonarr Server:
http://sonarr:8989 - API Key: (copy from Sonarr → Settings → General)
- Click Test then Save
- Repeat for Radarr (
http://radarr:7878)
Prowlarr will now automatically sync all indexers to both Sonarr and Radarr. Add or remove indexers in one place.
Step 5: Configure Sonarr (TV Shows)
- Open Sonarr at
http://your-server:8989 - Settings → Media Management:
- Enable Rename Episodes
- Standard Episode Format:
{Series TitleYear} - S{season:00}E{episode:00} - {Episode CleanTitle} [{Quality Full}]{[MediaInfo VideoDynamicRangeType]} - Add a Root Folder:
/data/media/tv
- Settings → Download Clients:
- Click +, select qBittorrent
- Host:
qbittorrent, Port:8080 - Username and password from Step 3
- Category:
tv(Sonarr auto-creates this category) - Click Test then Save
- Settings → Profiles:
- Edit quality profiles to match your preferences
- “HD-1080p” is a good default for most setups
Adding a TV Show
Go to Series → Add New, search for a show, select your quality profile and root folder, then click Add. Sonarr will search for existing episodes and monitor for new ones automatically.
Step 6: Configure Radarr (Movies)
- Open Radarr at
http://your-server:7878 - Settings → Media Management:
- Enable Rename Movies
- Standard Movie Format:
{Movie CleanTitle} {(Release Year)} {imdb-{ImdbId}} [{Quality Full}]{[MediaInfo VideoDynamicRangeType]} - Add a Root Folder:
/data/media/movies
- Settings → Download Clients:
- Same as Sonarr but set Category to
movies
- Same as Sonarr but set Category to
- Settings → Profiles:
- “HD-1080p” or “Ultra-HD” depending on your setup
Configuration mirrors Sonarr closely — if you’ve done one, the other is quick.
Step 7: Configure Jellyseerr (Request Portal)
Jellyseerr gives users a beautiful Netflix-like interface to browse and request content.
- Open Jellyseerr at
http://your-server:5055 - Sign in with Jellyfin (or Plex):
- Enter your Jellyfin URL (e.g.,
http://jellyfin:8096) - Sign in with admin credentials
- Enter your Jellyfin URL (e.g.,
- Configure media servers:
- Sync your Jellyfin libraries so Jellyseerr knows what you already have
- Connect Sonarr:
- Server Name:
Sonarr - Hostname:
sonarr, Port:8989 - API Key: (from Sonarr → Settings → General)
- Quality Profile and Root Folder: select your defaults
- Enable as Default Server
- Server Name:
- Connect Radarr:
- Same pattern with
radarrhost, port7878
- Same pattern with
- User management:
- Import Jellyfin users or create local accounts
- Set request limits per user (e.g., 10 movies/week)
Now users can search for movies and TV shows, request them, and Jellyseerr routes requests to the appropriate Arr app automatically.
Step 8: Connecting to Your Media Server
Jellyfin Integration
If you’re running Jellyfin, point your library folders:
- Movies Library →
/data/media/movies - TV Shows Library →
/data/media/tv
Jellyfin will automatically detect new files as the Arr stack adds them. Enable real-time monitoring in library settings for instant updates.
Plex Integration
Same concept — add library folders pointing to your organized media directories. Plex can also receive webhooks from Sonarr/Radarr via Connect settings to trigger immediate library scans.
Quality Profiles and Upgrades
One of the Arr stack’s best features is automatic quality upgrades. Configure this in Sonarr/Radarr under Settings → Profiles:
Recommended Profile Strategy
Standard Quality (most users):
- Minimum: HDTV-720p
- Cutoff: Bluray-1080p
- This downloads 720p immediately, then upgrades to 1080p Blu-ray when available
High Quality:
- Minimum: WEBDL-1080p
- Cutoff: Bluray-1080p / Remux-1080p
- Waits for at least 1080p web release
4K:
- Minimum: WEBDL-2160p
- Cutoff: Bluray-2160p / Remux-2160p
- Consider a separate Radarr instance for 4K (different root folder)
Custom Formats
Both Sonarr and Radarr support Custom Formats for fine-grained control:
- Prefer specific release groups
- Avoid hardcoded subtitles
- Prefer HDR/DV content
- Avoid or prefer specific audio codecs (Atmos, TrueHD, DTS-HD)
Check the TRaSH Guides for community-recommended custom format configurations.
Using a VPN with the Stack
If you want to route downloads through a VPN, Gluetun is the standard approach. Modify your Compose file:
gluetun:
image: qmcgaw/gluetun:latest
container_name: gluetun
cap_add:
- NET_ADMIN
environment:
- VPN_SERVICE_PROVIDER=your_provider
- VPN_TYPE=wireguard
# Add provider-specific variables
ports:
- "8080:8080" # qBittorrent WebUI
- "6881:6881"
- "6881:6881/udp"
restart: unless-stopped
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
network_mode: "service:gluetun" # Route through VPN
# Remove ports section — Gluetun handles them
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- WEBUI_PORT=8080
volumes:
- ./qbittorrent/config:/config
- /data/media/downloads:/data/media/downloads
restart: unless-stopped
Only the download client needs the VPN. Sonarr, Radarr, and Prowlarr communicate directly and don’t need VPN routing.
Reverse Proxy Setup
Put everything behind a reverse proxy with HTTPS. Here’s a Caddy configuration:
For Nginx configurations, check our reverse proxy comparison.
Security note: Always enable authentication on all Arr apps (Settings → General → Authentication). Prowlarr requires it by default. Set it for Sonarr and Radarr too, especially if exposing them beyond your LAN.
Backup Strategy
The Arr apps store configuration and databases in their /config volumes. Back these up regularly:
#!/bin/bash
# backup-arr-stack.sh
BACKUP_DIR="/data/backups/arr-stack/$(date +%Y-%m-%d)"
mkdir -p "$BACKUP_DIR"
# Stop containers for clean backup
docker compose stop sonarr radarr prowlarr jellyseerr
for app in sonarr radarr prowlarr jellyseerr qbittorrent; do
tar czf "$BACKUP_DIR/${app}.tar.gz" -C ./${app} config/
done
docker compose start sonarr radarr prowlarr jellyseerr
# Keep 14 days of backups
find /data/backups/arr-stack/ -maxdepth 1 -mtime +14 -exec rm -rf {} +
echo "Arr stack backup complete: $BACKUP_DIR"
For automated backup solutions, check our guides on Kopia or Duplicati.
Troubleshooting
Downloads complete but don’t import
- Check paths: all containers must use the same
/data/mediamount. If Sonarr sees/data/media/downloadsbut qBittorrent saves to/downloads, import fails - Check permissions: run
ls -la /data/media/downloads/complete— files should be owned by your PUID/PGID - Check categories: qBittorrent categories must match what Sonarr/Radarr expect (
tvandmovies)
Prowlarr indexers not syncing
- Verify API keys are correct in Prowlarr’s app connections
- Use container names (
sonarr,radarr) notlocalhostfor hostnames - Ensure all containers are on the same Docker network
Hardlinks not working
- All containers must mount the same parent path —
/data/medianot separate mounts for/moviesand/downloads - Hardlinks only work within the same filesystem/mount
- Check with:
ls -li /data/media/movies/somefile— hardlinked files share the same inode number
Jellyseerr shows “Unavailable” for content you have
- Re-sync Jellyfin/Plex libraries in Jellyseerr settings
- Check that library paths match between your media server and Arr apps
- Run a full library scan in Jellyseerr: Settings → Jellyfin → Sync Libraries
High memory or CPU usage
- Sonarr and Radarr can spike during RSS sync and searches — stagger RSS intervals
- Large libraries (5000+ movies) may need 1-2GB RAM per Arr app
- Set Prowlarr to sync indexers on a reasonable interval (every 6-24 hours, not hourly)
Power User Tips
Separate instances for 4K: Run a second Radarr instance for 4K content with its own root folder (/data/media/movies-4k). This keeps 4K and 1080p libraries separate, useful if not all devices support 4K.
Recyclarr for TRaSH Guides: Use Recyclarr to automatically sync TRaSH Guide custom formats and quality profiles. Set it and forget it.
Notifications: All Arr apps support notifications via Discord webhooks, Telegram, email, ntfy, and more. Set up alerts for grabs, downloads, and health issues under Settings → Connect.
Bazarr for subtitles: Add Bazarr to your stack for automated subtitle downloads. It integrates directly with Sonarr and Radarr.
Flaresolverr for Cloudflare-protected indexers: Some indexers use Cloudflare challenges. Add Flaresolverr as a container and configure it in Prowlarr to handle these automatically.
Overseerr vs Jellyseerr: Overseerr is Plex-only. Jellyseerr is a fork that supports both Jellyfin and Plex. If you use Jellyfin, Jellyseerr is the way to go.
Wrapping Up
The Arr stack transforms media management from a manual chore into a fully automated pipeline. Once configured, new episodes appear in your library automatically, movies upgrade to better quality over time, and users can request content through a clean interface without touching the backend.
Start with the basics — Sonarr, Radarr, Prowlarr, and a download client. Add Jellyseerr when you want request management. Layer on VPN, Bazarr, and custom formats as you get comfortable. The beauty of the modular approach is you can grow the stack at your own pace.
For related guides, check out our posts on setting up Gluetun VPN, Docker volume management, and server monitoring with Grafana and Prometheus.