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:

ApplicationRoleWhat It Does
SonarrTV Series ManagerMonitors, downloads, and organizes TV shows
RadarrMovie ManagerMonitors, downloads, and organizes movies
ProwlarrIndexer ManagerManages indexers/trackers for Sonarr and Radarr
JellyseerrRequest PortalUsers request media through a clean UI
Jellyfin/PlexMedia ServerStreams your library to all devices

The flow: User requestsJellyseerrSonarr/RadarrProwlarr (finds sources) → Download clientOrganized libraryJellyfin/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):

/datamtd/ovmvweindelciisoonaamcdposlm/eptlee/te/####RSFIaoindnn-aaiprrsrrrhoegmmdraaenndsaaosggweendssloowttanhhdliisossaldasndhere

Key concept: Mount the same /data/media path 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.

  1. Open qBittorrent at http://your-server:8080
  2. Check the container logs for the temporary password: docker logs qbittorrent
  3. Log in and go to Tools → Options → Downloads
  4. Set Default Save Path to /data/media/downloads/complete
  5. Set Incomplete Save Path to /data/media/downloads/incomplete
  6. 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.

  1. Open Prowlarr at http://your-server:9696
  2. Set up authentication under Settings → General (required)
  3. Add indexers under Indexers → Add Indexer — search for your preferred indexers and add credentials
  4. 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)

  1. Open Sonarr at http://your-server:8989
  2. 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
  3. 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
  4. 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)

  1. Open Radarr at http://your-server:7878
  2. 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
  3. Settings → Download Clients:
    • Same as Sonarr but set Category to movies
  4. 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.

  1. Open Jellyseerr at http://your-server:5055
  2. Sign in with Jellyfin (or Plex):
    • Enter your Jellyfin URL (e.g., http://jellyfin:8096)
    • Sign in with admin credentials
  3. Configure media servers:
    • Sync your Jellyfin libraries so Jellyseerr knows what you already have
  4. 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
  5. Connect Radarr:
    • Same pattern with radarr host, port 7878
  6. 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:

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:

s}r}p}r}oarendoqaawurrrrlrerrereaese.v.vrvtvyeyereseoror.r.rususysysrereoeoed_d_u_u_opoprprpmrmrdrdraoaoooooixixmxmxnynyayay..iicscrnpnjoooa.r.emnmdcoclaaowol{r{rmlmyrras::{r{e87re98:r879r986:956055

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/media mount. If Sonarr sees /data/media/downloads but 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 (tv and movies)

Prowlarr indexers not syncing

  • Verify API keys are correct in Prowlarr’s app connections
  • Use container names (sonarr, radarr) not localhost for hostnames
  • Ensure all containers are on the same Docker network
  • All containers must mount the same parent path/data/media not separate mounts for /movies and /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.