Skip to content

Servarr

Automated Media Management Stack

The Servarr stack automates media acquisition and organization. This setup bundles Prowlarr (indexer manager), Radarr (movies), Sonarr (TV shows), and qBittorrent (download client) into a single Incus container, all running under a shared arr user.

Why Choose Servarr?

  • Unified stack - Prowlarr, Radarr, Sonarr, and qBittorrent in one container
  • Automated workflow - search, grab, rename, and organize media hands-free
  • Quality profiles - define resolution, codec, and language preferences per title
  • Calendar and monitoring - track upcoming releases and download progress

Install

Infrastructure as Code

This Servarr instance is deployed using OpenTofu with a custom Incus image. The infrastructure configuration manages container provisioning, persistent storage, and media library access.

The canonical configuration is maintained at Benoit/OpenTofu.

Custom Servarr Image

The Servarr Incus image is built and maintained at forgejo.benoit.jp.net/Benoit/Laminar. It installs Prowlarr, Radarr, Sonarr, and qBittorrent-nox from upstream releases on an Ubuntu 25.10 base.

Infrastructure Configuration

The OpenTofu configuration provisions:

  • Incus instance running the custom Servarr image with macvlan networking
  • Persistent backup volume at /var/backups/arr
  • Shared media directory mounting TrueNAS downloads with UID/GID mapping
  • macvlan NIC so the container gets its own LAN IP, allowing Tailscale with a Mullvad exit node independently from the host's Tailscale network
OpenTofu Configuration
resource "incus_storage_volume" "arr_var_backups_arr" {
  name = "arr_var_backups_arr"
  pool = incus_storage_pool.default.name
}

resource "incus_instance" "arr" {
  name  = "arr"
  image = "laminar.incus:arr-2025-11-20-2benoitjpnet"

  device {
    name = "var_backups_arr"
    type = "disk"
    properties = {
      path   = "/var/backups/arr"
      source = incus_storage_volume.arr_var_backups_arr.name
      pool   = incus_storage_pool.default.name
    }
  }

  device {
    name = "mnt_truenas_downloads"
    type = "disk"
    properties = {
      path   = "/mnt/truenas/downloads"
      source = "/mnt/truenas/downloads"
    }
  }

  config = {
    # host UID/GID 3000 โ†’ container UID/GID 3000
    # truenas is 3000
    "raw.idmap" = <<-EOT
      uid 3000 3000
      gid 3000 3000
    EOT
  }

  # macvlan so we get an IP in the LAN, not in incus bridge
  device {
    name = "eth0"
    type = "nic"
    properties = {
      nictype = "macvlan"
      parent  = "enp1s0"
    }
  }
}

Deploy Infrastructure

Apply OpenTofu configuration
tofu apply

The container gets its own LAN IP via macvlan. Find it with incus list arr. The web UIs are then accessible at:

Service Port
Prowlarr 9696
Radarr 7878
Sonarr 8989
qBittorrent 8080

qBittorrent Initial Password

On first start, qBittorrent generates a random admin password. Retrieve it from the service journal:

Get qBittorrent temporary password
journalctl -u qbittorrent-nox@arr.service

Log in to the web UI with user admin and the temporary password, then change it in Settings.

Configure Prowlarr first (add indexers), then connect it to Radarr and Sonarr. Point the download client in both Radarr and Sonarr to the local qBittorrent instance. Set media root folders to /mnt/truenas/downloads.

Upgrade

Incus Image Upgrade

When upgrading to a newer Incus image version, follow these steps to migrate your data. Service data lives on the container root filesystem, so a backup/restore cycle is required.

Backup current instance data before upgrading:

Enter Incus container
incus shell arr

Stop all services

Stop Servarr services
systemctl stop prowlarr radarr sonarr qbittorrent-nox@arr

Back up all service data

Copy data to persistent backup volume
cp -a /var/lib/prowlarr /var/backups/arr/
cp -a /var/lib/radarr /var/backups/arr/
cp -a /var/lib/sonarr /var/backups/arr/
cp -a /var/lib/qbittorrent /var/backups/arr/

Remove old machine from Tailscale

Before upgrading, remove the old arr machine from the Tailscale Admin Console. The new container will be added as a fresh machine after the upgrade.

Deploy to new Incus image and restore data:

Update OpenTofu configuration

Edit your OpenTofu configuration file to update the image version:

resource "incus_instance" "arr" {
  name  = "arr"
  image = "laminar.incus:arr-NEW-VERSION"  # (1)!
  # ...
}
  1. Replace NEW-VERSION with the target image alias, e.g. 2026-03-31-1benoitjpnet.

Apply infrastructure changes

Provision new Incus container
tofu apply
Enter Incus container
incus shell arr

Stop services and restore data

Stop services, restore backups, fix ownership
systemctl stop prowlarr radarr sonarr qbittorrent-nox@arr
cp -a /var/backups/arr/prowlarr/* /var/lib/prowlarr/
cp -a /var/backups/arr/radarr/* /var/lib/radarr/
cp -a /var/backups/arr/sonarr/* /var/lib/sonarr/
cp -a /var/backups/arr/qbittorrent/* /var/lib/qbittorrent/
chown -R arr:arr /var/lib/prowlarr /var/lib/radarr /var/lib/sonarr /var/lib/qbittorrent

Start all services

Start Servarr services
systemctl start prowlarr radarr sonarr qbittorrent-nox@arr

Re-install Tailscale

Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
Authenticate with new auth key
tailscale up --auth-key=<new-auth-key>

Generate a new auth key from the Tailscale Admin Console.

Re-enable Mullvad for this machine in the Tailscale Mullvad settings, then route traffic through the Mullvad exit node:

Enable Mullvad exit node
tailscale up --exit-node=jp-tyo-wg-001.mullvad.ts.net
Confirm traffic is routed through Mullvad
curl ipinfo.io
curl v6.ipinfo.io

Retrieve qBittorrent password

qBittorrent generates a new random admin password on the fresh container:

Get qBittorrent temporary password
journalctl -u qbittorrent-nox@arr.service

Log in to the web UI with user admin and the temporary password, then change it in Settings.

Upgrade Complete

All four services are now running on the new Incus image with your previous configuration, databases, and download history restored.