Installing an *arr Stack on Proxmox

In this post, I’ll be showing you how to install an *arr stack on a Proxmox host. It will contain qBittorrent with a VPN, Sonarr, and Jackett. This particular *arr stack will allow you to download your favorite TV shows and store them in a format that can be viewed by something like Jellyfin, and even automatically look for new episodes. You can also install other *arr apps that look for different types of content, but that’s outside of the scope of this post.

Regardless of your choice of apps, these steps should be pretty similar. You can also choose to have some of these apps share the same VM or container. You could even run everything in Docker containers, but that’s outside of the scope of this post, and kinda defeats the purpose of it.

Prerequisites

The only things that you will need are a Proxmox host (Obviously), some basic knowledge of using Proxmox, and optionally but highly recommended a VPN that’s compatible with OpenVPN.

You should also plan on what services should share a VM or container, or if everything should be separate. I personally have Jackett and my *arr apps (Only Sonarr in my case) share a single container, and qBittorrent with my VPN share a single VM. Regardless of what you decide, the main issue that you need to worry about is ensuring that nothing uses the same port. Besides that, there shouldn’t be any concerns of conflicts.

qBittorrent with OpenVPN

You don’t need to run qBittorrent with a VPN, but chances are for the majority of the people reading this, I would highly recommend running one. Not only will running one improve the privacy and security of your setup, but you also won’t need to worry about your ISP sending you letters or cutting off your service.

Container Setup

If you plan on running qBittorrent inside of an LXC container, there’s a few steps that you have to take while creating it. The first step is if you’re storing your downloaded content on a separate machine, uncheck “Unprivileged container”. This will allow you to enable the needed features for transferring files over the network:

After creating the container, edit its configuration file:

nano /etc/pve/lxc/container-id.conf

Add the following lines to the configuration file:

lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net dev/net none bind,create=dir

Change the owner of /dev/net/tun to allow the container to access it:

chown 100000:100000 /dev/net/tun

This will make /dev/net/tun available to the container, thus allowing you to use OpenVPN.

Finally, start the container, and access its console.

Installing qBittorrent

After ensuring that the container starts and is up to date, ensure that the following packages are installed:

apt install curl gpg

By default, the container uses root as the default user and doesn’t have sudo configured, so this post will assume that you haven’t setup sudo. If you have setup sudo, use sudo on the appropriate commands.

Add the necessary repository to APT:

echo 'deb http://download.opensuse.org/repositories/home:/nikoneko:/test/Debian_12/ /' | tee /etc/apt/sources.list.d/home:nikoneko:test.list
curl -fsSL https://download.opensuse.org/repositories/home:nikoneko:test/Debian_12/Release.key | gpg --dearmor | tee /etc/apt/trusted.gpg.d/home_nikoneko_test.gpg > /dev/null
apt update

Run the following command to install qBittorrent without a GUI and with only the web interface:

apt install qbittorrent-nox

After it has successfully installed, run the following command to start the initial setup:

qbittorrent-nox

After accepting the agreement, you’ll be prompted with a username, password, and URL to login. Replace localhost with the appropriate IP address. Press Ctrl+C to exit once you’ve confirmed that qBittorrent works.

To run the qBittorrent service in the background, run the following command:

systemctl start qbittorrent-nox@root

You can also allow it to run at startup by running the following command:

systemctl enable qbittorrent-nox@root

If you get an error about a missing unit file, create a new one under /usr/lib/systemd/system/[email protected], then add the following contents:

[Unit]
Description=qBittorrent-nox service for user %I
Documentation=man:qbittorrent-nox(1)
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target

[Service]
Type=simple
PrivateTmp=false
User=%i
ExecStart=qbittorrent-nox
TimeoutStopSec=1800

[Install]
WantedBy=multi-user.target

Run systemctl daemon-reload, and you should be able to run the aforementioned commands without issue.

As a quick side note, I noticed that the qBittorrent service can take a few minutes to stop, at least from my personal experience, so keep that in mind when rebooting the container.

Mounting Network Drives

If you plan on storing your downloaded content on a network drive, first ensure that the following check boxes are checked under Options then Features:

These features are only available on privileged containers

After enabling those features, install the needed packages:

apt install cifs-utils

Next, open /etc/fstab in a text editor, and add the following line (Add more if needed):

//ServerNameOrIP/ShareName /Path/Of/Choice cifs _netdev,username=YourUsername,password=YourPassword,iocharset=utf8 0 0

Run mount -a, then navigate to the directory that you chose to verify that it mounted correctly.

If you’re using a VM instead of a container, add the following line to your /etc/fstab (You also need cifs-utils installed)

//ServerNameOrIP/ShareName /Path/Of/Choice cifs _netdev,noauto,x-systemd.automount,username=YourUsername,password=YourPassword,iocharset=utf8,rw,uid=UIDofqBittorrentUser,gid=GIDofqBittorrentUser 0 0

You can get the UID and GID of your qBittorrent user by running id qBittorrentUser. Run mount -a, and navigate to the directory that you chose. Unlike the fstab for the container, after rebooting, the volume will only be mounted after something tries to access it, not at startup.

Log into qBittorrent, then under Options and Downloads, enter the path that you mounted your network drive to:

Adjust other save options if desired

If you’re using something like Jellyfin or Plex, you’ll need to ensure that it has access to the directory that you chose.

OpenVPN

This step is optional, but for the reasons I stated above, I would highly recommend using one. There’s probably a better way of doing this, but this is a tried and true method that I’ve used enough times. If you don’t know what VPN to use, I personally have had a great experience with ProtonVPN, but there’s various options out there.

First, install the OpenVPN package:

apt install openvpn

Next, disable the default OpenVPN service. It’s enabled by default, and if you reboot your container, you’ll be staring at a black screen for minutes, then you’ll keep getting asked for a login (I found this out the hard way).

systemctl disable openvpn

Next, obtain the needed configuration files from your provider, and your OpenVPN username and password. If you happen to be using ProtonVPN, your OpenVPN username and password is located under Account, and the configuration files are located under Downloads.

Save your downloaded configuration file under /etc/openvpn/openvpn.conf, and create a text file under /etc/openvpn/login.txt with your OpenVPN username and password. It should look something like this:

ProvidedOpenVPNUsername
ProvidedOpenVPNPassword

Next, create a new Systemd unit file under /etc/systemd/system/openvpn-qbittorrent.service, and add the following content:

[Unit]
Description=OpenVPN Client for qBittorrent
After=network.target

[Service]
ExecStart=openvpn --config  /etc/openvpn/openvpn.conf --auth-user-pass /etc/openvpn/login.txt

[Install]
WantedBy=multi-user.target

Run systemctl daemon-reload, then run systemctl start openvpn-qbittorrent, and after ensuring that it’s running correctly, run systemctl enable openvpn-qbittorrent to allow it to run at startup.

Last but most importantly, login to qBittorrent then navigate to Options, Advanced, then select tun0 as the network interface. This will ensure that qBittorrent won’t try to fall back to a different interface in case your VPN goes down:

Now you should have a working qBittorrent install that’s protected by a VPN.

Jackett, Sonarr, and Others

Now that you have a working qBittorrent install with a VPN, it’s time to do something with it by installing some indexers. This is what will actually allow you to download content by using your qBittorrent setup.

You can either run these indexers inside of the same container as qBittorrent, or in their own container. I personally chose to run all of my indexers inside of their own separate container.

Jackett

After adding indexers to Jackett, its job is to simply look for the content that you tell it to by using something like Sonarr. After it has found the content that you’re looking for, it will relay that information to Sonarr (Or whatever *arr app you’re using) so it can start downloading it.

Jackett Install

Before you can install Jackett, you need to create a new user that has access to the sudo command. This is because Jackett will fail to install if you’re using the default root user, and even if you modify the script to allow it, you’ll get a banner saying that Jackett is being ran as root everytime you launch it.

First, install the sudo package:

apt install sudo

After installing the sudo package, create a new user, then add it to the sudo group:

useradd -mG sudo username

Set a password for the user:

passwd username

Now switch to the user, and try running any command with the sudo command to ensure that it’s setup correctly:

su username
sudo apt update

After verifying that sudo works correctly, ensure that wget has been installed:

sudo apt install wget

The Jackett developers provide this handy one line installation command:

cd /opt && f=Jackett.Binaries.LinuxAMDx64.tar.gz && release=$(wget -q https://github.com/Jackett/Jackett/releases/latest -O - | grep "title>Release" | cut -d " " -f 4) && sudo wget -Nc https://github.com/Jackett/Jackett/releases/download/$release/"$f" && sudo tar -xzf "$f" && sudo rm -f "$f" && cd Jackett* && sudo ./install_service_systemd.sh && systemctl status jackett.service && cd - && echo -e "\nVisit http://127.0.0.1:9117"

After Jackett has been successfully installed, visit Jackett by typing in your container’s IP address and the listed port.

Jackett Configuration

Configuring Jackett is very simple. All you need to do is add some indexers, and you’ll be all set. Here’s the indexers I personally use:

Feel free to scroll down and explore all of the other settings. We’ll get back to Jackett in a moment. At this point, I will be assuming that you will be using the default root user.

FlareSolverr Installation/Configuration

Since some indexers might use Cloudflare’s captcha, this may prevent Jackett from indexing them. Luckily someone made a very easy solution to this problem.

Since the recommended way to install FlareSolverr is to use Docker, you’ll need to setup Docker on your container. Before installing Docker, ensure that your container is a privileged container.

First, install Docker according to their documentation. I would recommend installing Docker using the APT repository as this makes it very easy to update. After you’ve verified that Docker is installed correctly, create a file named docker-compose.yml in a place that you would remember, then add the following contents:

version: "2.1"
services:
  flaresolverr:
    # DockerHub mirror flaresolverr/flaresolverr:latest
    image: ghcr.io/flaresolverr/flaresolverr:latest
    container_name: flaresolverr
    environment:
      - LOG_LEVEL=${LOG_LEVEL:-info}
      - LOG_HTML=${LOG_HTML:-false}
      - CAPTCHA_SOLVER=${CAPTCHA_SOLVER:-none}
      - TZ=Europe/London
    ports:
      - "${PORT:-8191}:8191"
    restart: unless-stopped

You should be able to keep all of the options at their defaults without any issues. You can run the container by running the following command:

docker compose up -d

If you’d rather not use Docker Compose, use the following Docker command instead:

docker run -d --name=flaresolverr -p 8191:8191 -e LOG_LEVEL=info --restart unless-stopped ghcr.io/flaresolverr/flaresolverr:latest

After the container has been created, enter yourcontainerip:8191 into your web browser, and you should see a message stating that FlareSolverr is ready. If you want to update FlareSolverr, run the following commands:

docker rm -v flaresolverr && docker rmi ghcr.io/flaresolverr/flaresolverr

Now use the docker run command or the docker compose command depending on what you chose.

Finally, configure Jackett to use FlareSolverr by scrolling down to the bottom of the page, and entering the URL to access FlareSolverr under FlareSolverr API URL:

Sonarr

Sonarr is used to tell Jackett what content to look for inside of your indexers, and it also instructs qBittorrent to start downloading it. Sonarr can even look for new releases to automatically download. All you need to do is add the shows that you want to watch to Sonarr, and it does the rest.

Sonarr Installation

I will only be showing the installation for Sonarr, but the installation process for similar *arr apps should be very similar.

First, add the Sonarr APT repository (Even though it says Buster, it works fine on Bullseye):

apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 2009837CBFFD68F45BC180471F4F90DE2A9B4BF8
echo "deb https://apt.sonarr.tv/debian buster main" | tee /etc/apt/sources.list.d/sonarr.list

Next, install the Sonarr package:

apt update && apt install sonarr

When prompted, just hit enter to keep the defaults. This will create a user named sonarr that will be responsible for well… running Sonarr.

If you want Sonarr to store your media on a network drive, you’ll need to install cifs-utils:

apt install cifs-utils

Next, get the UID and GID of the Sonarr user:

id sonarr

The /etc/fstab configuration is similar to the one that you used for qBittorrent:

# For containers
//ServerNameOrIP/ShareName /Path/Of/Choice cifs _netdev,username=YourUsername,password=YourPassword,iocharset=utf8,rw,uid=SonarrUserUID,gid=SonarrUserGID 0 0
# For VM's
//ServerNameOrIP/ShareName /Path/Of/Choice cifs _netdev,noauto,x-systemd.automount,username=YourUsername,password=YourPassword,iocharset=utf8,rw,uid=SonarrUserUID,gid=SonarrUserGID 0 0

Run mount -a, and browse to the path that you chose to ensure that the share was mounted correctly.

Sonarr Configuration

Open your container’s IP address with port 8989 in your web browser to access Sonarr. This is where all of the configuration of Sonarr will take place. First, you’ll want to tell Sonarr where to store all of your media, so click on Settings, then Media Management in the sidebar:

Next, scroll down to Root Folders, remove any unneeded ones by clicking the little X, and add your network share by clicking on Add Root Folder:

Next, configure Sonarr to use qBittorrent by clicking on Download Clients under Settings:

Under Download Clients, click the big button with the + icon:

Ignore the fact that I’ve already configured mine

Click qBittorrent under Torrents:

Finally, fill out the needed information according to your setup, then Click Test and Save:

Next, you’ll need to configure Sonarr to use your Jackett indexers by clicking on Indexers under Settings. At this point you’ll want to have the web interface for Jackett pulled up:

Next, click the large + button under Indexers:

Like with configuring qBittorrent, ignore the fact that I’ve already added my indexers

Click Torznab under Torrents:

You should see a screen that looks something like this:

Next, navigate to Jackett, then click Copy Torznab Feed next to the indexer that you want to add:

Navigate back to Sonarr, then paste it under URL.

Next, copy the API key for Jackett. It’s displayed in the top right corner of Jackett’s page:

Paste your API key under API Key.

Finally, click on the Categories drop down menu, and select the categories as needed. This will vary from indexer to indexer. Configure all of the other settings as needed.

After you’ve configured everything, click Test and Save:

Finally, you should be able to click Series, and then add TV shows as needed. I could go over all of the options here, but I would recommend that you explore them yourself. I personally like using the interactive search instead of letting Sonarr look for new episodes automatically. Depending on how many indexers you have and other factors, it can take a long time:

Button to access the interactive search feature
Interactive search example

Conclusion

After reading this post, you should now have a working *arr stack to automatically download your favorite TV shows. Unfortunately I can’t shows the installation process for Jellyfin since GPU passthrough doesn’t work correctly on my Proxmox host, and even though you technically don’t need it, I feel like it’s an important thing to have.

Feel free to leave any thoughts, suggestions, or complaints in the comments below. If you have any questions, I’ll try my best to answer them.

References

Proxmox’s official guide on running OpenVPN in LXC: https://pve.proxmox.com/wiki/OpenVPN_in_LXC

qBittorrent Installation: https://github.com/qbittorrent/qBittorrent/wiki/Running-qBittorrent-without-X-server-(WebUI-only,-systemd-service-set-up,-Ubuntu-15.04-or-newer

Jackett Installation: https://github.com/Jackett/Jackett

FlareSolverr Installation: https://github.com/FlareSolverr/FlareSolverr/

Sonarr Installation: https://sonarr.tv/#downloads-v3-linux

Subscribe
Notify of

3 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
&Cherry
July 10, 2023 8:58 pm

undetected_chromedriver…
beep boop, I am a bobot! 😮

Michael Cooper
March 1, 2024 12:12 am

Hello Alex,
Thank you for the hard work on the article. I will probably reference you if you don’t mind. As I am writing an article for my website to do this on a Raspberry Pi 4/5, Orange Pi 5, & a Rock Pi 4b. I will probably be bothering with questions I hope that is okay. I am still new to this and stupid to how it all fits together.

Thank you again, This is awesome.
Michael