This guide is for someone who is looking to setup an Arr Stack for media organization and downloading. This guide requires no remote path mappings, follows Trash-Guides recommendations and every command needed is copy-pasteable. The VM’s in this guide are hosted on Proxmox 8.1.4, but you can use any Ubuntu environment (WSL-2, VirtualBox, etc.)

Arr VM Specs:

  • 2 core host
  • 8GB RAM
  • 100GB Storage

Downloader VM Specs:

  • 2 core host
  • 4GB RAM
  • 250GB Storage (can download up to this limit at a time, be careful when mass downloading or give plenty of space)

Prerequisites

  • Ubuntu 22.04
  • Any Usenet Server Subscription (preferred)
  • Any Usenet Indexer Subscription (preferred)
  • Real-Debrid Subscription (if you like torrents being fast)
  • VPN Subscription (Bare minimum needed to download torrents)

Folder Structure Setup

Run this command to make all folders, following TRASH-guides recommended naming scheme:

sudo mkdir -p /data/torrents/{books,movies,music,tv} /data/usenet/{incomplete,complete/{books,movies,music,tv}} /data/media/{books,movies,music,tv}

Mounting NAS

I use my NAS for storing all my content, this allows me to have 1 spot to have everything saved too, and not getting tripped up with different file systems. You do not need a NAS, and can just skip this part of guide and use the local filesystem. I use TrueNAS Scale with SMB. In order to mount SMB shares to Linux filesystem we need to install CIFS:

sudo apt install cifs-utils -y

then we need to tell the system which directory to map it to, to do this:

sudo nano /etc/fstab

at the end of the file, add an entry for your NAS as such:

//<NAS IP>/<NAS Share> /data/media cifs username=<user>,password=<pass>,uid=1000,gid=1000,auto,nofail 0 0

be sure to replace your credentials.

To mount your NAS, you can run:

sudo mount -a

then run the following to make sure your NAS is mounted:

ls /data/media

Everything in your NAS should be showing now, but we need to set permissions, to do that run:

sudo chown -R $USER:$USER /data
sudo chmod -R a=,a+rX,u+w,g+w /data

Install Docker

Now we have to install Docker, I use this command to install Docker and Docker Engine:

curl -fsSL https://get.docker.com | sudo sh

Now that docker is installed, we can add our user to the docker group so we dont have to use sudo every command:

sudo usermod -aG docker $USER

Now I would make a docker directory to store all your appdata, you can use your home directory if you want, but trash-guides recommend not doing so:

sudo mkdir -p /docker/appdata/{radarr,sonarr,bazarr,prowlarr,lidarr,sabnzbd,qbitty,rdt}

Then set permissions on the docker directory:

sudo chown -R $USER:$USER /docker
sudo chmod -R a=,a+rX,u+w,g+w /docker

2 VM Setup

I have my downloaders (Sab, Qbitty, Rdt-client) on a different VM than my ARR’s, this is cause when I had everything on 1 docker host, I would have constant HTTP errors from Sab mainly, and as Sab is where I get most of my media, I decided to move to another VM, and then SMB share the download directories over to my ARR’s VM.

You do not have to do this, you can just have 1 docker host, up to you. It is alot less work to do all in one 1 VM.

If you do this, you need to replicate the origin setup, making all the same directories, then run:

sudo apt update
sudo apt install samba

We need to configure Samba to tell it what we are sharing:

sudo nano /etc/samba/smb.conf

Add the following at the end of this file:

[usenet]
  path = /data/usenet
  read only = no
  guest ok = no
  create mask = 0755

[torrents]
  path = /data/torrents
  read only = no
  guest ok = no
  create mask = 0755

To create your username and password, replace your_username with your actual username:

sudo smbpasswd -a your_username

Then restart samba with:

sudo systemctl restart smbd

Go back to your Arr VM and add the following to your /etc/fstab:

//<nas-ip>/usenet /data/usenet cifs username=<username>,password=<password>,uid=1000,gid=1000,auto,nofail 0 0
//<nas-ip>/torrents /data/torrents cifs username=<username>,password=<password>,uid=1000,gid=1000,auto,nofail 0 0

Mount them with:

sudo mount -a

Then re-run our permissions command:

sudo chown -R $USER:$USER /data
sudo chmod -R a=,a+rX,u+w,g+w /data

I would reboot this VM at this point, this will make sure it auto connects to our SMB shares at boot.

Docker Compose Files

Now that everything is setup, we can actually install the services:

One VM

This is a full docker compose file for pretty much all major Arr’s and downloaders I use. I threw Lidarr in here as well, as I run Lidarr for music, but if you dont care about music you can remove lidarr:

version: "3.9"

services:
  sabnzbd:
    image: lscr.io/linuxserver/sabnzbd:latest
    container_name: sabnzbd
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/sabnzbd:/config
      - /data/usenet:/data/usenet:rw
    ports:
      - 8080:8080
    restart: unless-stopped

  arch-qbittorrentvpn:
    image: binhex/arch-qbittorrentvpn:latest
    container_name: qbittorrentvpn
    volumes:
      - '/docker/appdata/qbitty:/config'
      - '/data/torrents/:/data/torrents'
      - '/etc/localtime:/etc/localtime:ro'
    ports:
      - '49550:49550'
      - '49551:8118'
    environment:
      - VPN_ENABLED=yes
      - VPN_PROV=protonvpn
      - VPN_CLIENT=wireguard
      - VPN_USER=username+pmp
      - VPN_PASS=
      - STRICT_PORT_FORWARD=yes
      - LAN_NETWORK=10.0.0.0/24
      - ENABLE_PRIVOXY=yes
      - PUID=1000
      - PGID=1000
      - WEBUI_PORT=49550
      - UMASK=1000
      - DEBUG=false
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    privileged: true
    network_mode: bridge
    restart: unless-stopped

  rdtclient:
    container_name: rdtclient
    volumes:
      - '/data/torrents:/data/torrents'
      - '/docker/appdata/rdt:/data/db'
    image: rogerfar/rdtclient
    restart: always
    logging:
      driver: json-file
      options:
        max-size: 10m
    ports:
      - '6500:6500'

  bazarr:
    image: lscr.io/linuxserver/bazarr:latest
    ports:
      - "6767:6767"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/bazarr:/config
      - /data/media:/data/media
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

  lidarr:
    image: lscr.io/linuxserver/lidarr:latest
    ports:
      - "8686:8686"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/lidarr:/config
      - /data:/data
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    ports:
      - "9696:9696"
    volumes:
      - /docker/appdata/prowlarr:/config
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

  radarr:
    image: lscr.io/linuxserver/radarr:latest
    ports:
      - "7878:7878"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/radarr:/config
      - /data:/data
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    ports:
      - "8989:8989"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/sonarr:/config
      - /data:/data
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

networks:
  default:
    name: arrs_default

2 VM

Arrs:

version: "3.7"
services:
  bazarr:
    image: lscr.io/linuxserver/bazarr:latest
    ports:
      - "6767:6767"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/bazarr:/config
      - /data/media:/data/media
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

  lidarr:
    image: lscr.io/linuxserver/lidarr:latest
    ports:
      - "8686:8686"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/lidarr:/config
      - /data:/data
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    ports:
      - "9696:9696"
    volumes:
      - /docker/appdata/prowlarr:/config
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

  radarr:
    image: lscr.io/linuxserver/radarr:latest
    ports:
      - "7878:7878"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/radarr:/config
      - /data:/data
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    ports:
      - "8989:8989"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/sonarr:/config
      - /data:/data
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000

networks:
  default:
    name: arrs_default

Downloaders: As stated previously, Sab downloads most of my content (95%), you do not need all 3 of these, you can just copy the Sab part and just use Usenet with Sab. But I like to have a variety.

version: '3.9'
services:
  sabnzbd:
    image: lscr.io/linuxserver/sabnzbd:latest
    container_name: sabnzbd
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /docker/appdata/sabnzbd:/config
      - /data/usenet:/data/usenet:rw
    ports:
      - 8080:8080
    restart: unless-stopped

  arch-qbittorrentvpn:
    image: binhex/arch-qbittorrentvpn:latest
    container_name: qbittorrentvpn
    volumes:
      - '/docker/appdata/qbitty:/config'
      - '/data/torrents/:/data/torrents'
      - '/etc/localtime:/etc/localtime:ro'
    ports:
      - '49550:49550'
      - '49551:8118'
    environment:
      - VPN_ENABLED=yes
      - VPN_PROV=protonvpn
      - VPN_CLIENT=wireguard
      - VPN_USER=username+pmp
      - VPN_PASS=
      - STRICT_PORT_FORWARD=yes
      - LAN_NETWORK=10.0.0.0/24
      - ENABLE_PRIVOXY=yes
      - PUID=1000
      - PGID=1000
      - WEBUI_PORT=49550
      - UMASK=1000
      - DEBUG=false
    cap_add:
      - NET_ADMIN
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    privileged: true
    network_mode: bridge
    restart: unless-stopped

  rdtclient:
    container_name: rdtclient
    volumes:
      - '/data/torrents:/data/torrents'
      - '/docker/appdata/rdt:/data/db'
    image: rogerfar/rdtclient
    restart: always
    logging:
      driver: json-file
      options:
        max-size: 10m
    ports:
      - '6500:6500'

Running Docker Compose Files

In order to run these files, it depends on which option you chose, if 1 VM setup, just copy the compose file and create a new docker-compose.yml file with:

nano docker-compose.yml

Paste in the content, CTRL + X to exit nano, Y to save, ENTER to keep filename. Then run:

docker compose up -d

If you are using 2 VM’s, you need to do this 2x. One for each docker-compose file.

Conclusion

Congratulations on setting up your media library backend! We now have to go and configure all these services to work together, which I have another full blog post on which you can find here.