I will be using Ubuntuserver in this guide. You can select whatever linux distro you prefer.
Download ubuntu server from https://ubuntu.com/download/server. Create a bootable USB drive using rufus or any other software(I prefer ventoy). Plug the usb on your computer, and select the usb drive from the boot menu and install ubuntu server. Follow the steps to install and configure ubuntu, and make sure to check "Install OpenSSH server". Don't install docker during the setup as the snap version is installed.
Once installation finishes you can now reboot and connect to your machine remotely using ssh.
ssh username@server-ip
# username you selected during installation
# Type ip a to find out the ip address of your server. Will be present against device like **enp4s0** prefixed with 192.168.
Create the directories for audiobooks, books, movies, music and tv.
I keep all my media at ~/server/media. If you will be using multiple drives you can look up how to mount drives.
We will be using hardlinks so once the torrents are downloaded they are linked to media directory as well as torrents directory without using double storage space. Read up the trash-guides to have a better understanding.
mkdir ~/server
mkdir ~/server/media # Media directory
mkdir ~/server/torrents # Torrents
# Creating the directories for torrents
cd ~/server/torrents
mkdir audiobooks books incomplete movies music tv
cd ~/server/media
mkdir audiobooks books movies music tv
Jackett is where you define all your torrent indexers. All the *arr apps use the tornzab feed provided by jackett to search torrents.
There is now an *arr app called prowlarr that is meant to be the replacement for jackett. But the flaresolverr(used for auto solving captchas) support was added very recently and doesn't work that well as compared to jackett, so I am still sticking with jackett for meantime. You can instead use prowlarr if none of your indexers use captcha.
Sonarr is a TV show scheduling and searching download program. It will take a list of shows you enjoy, search via Jackett, and add them to the qbittorrent downloads queue.
I personally only use jellyfin because it's completely free. I still have plex installed because overseerr which is used to request movies and tv shows require plex. But that's the only role plex has in my setup.
I will talk about the devices section later on.
For the media volume you only need to provide access to the /data/media directory instead of /data as jellyfin doesn't need to know about the torrents.
As I mentioned in the jellyfin section there is a section in the conmpose file as "devices". It is used for transcoding. If you don't include that section, whenever transcoding happens it will only use CPU. In order to utilise your gpu the devices must be passed on to the container.
The default username is admin and password adminadmin. You can change the user and password by going to Tools → Options → WebUI
Change "Default Save Path" in WebUI section to /data/torrents/ and "Keep incomplete torrents in" to /data/torrents/incomplete/
Create categories by right clicking on sidebar under category. Type category as TV and path as tv. Path needs to be same as the folder you created to store your media. Similarly for movies type Movies as category and path as movies. This will enable to automatically move the media to its correct folder.
Sonarr
Navigate to YOUR_SERVER_IP:8989
Under "Download Clients" add qbittorrent. Enter the host as YOUR_SERVER_IP port as **8080,** and the username and password you used for qbittorrent. In category type TV (or whatever you selected as categoryname(not path) on qbittorent). Test the connection and then save.
Under indexers, for each indexer you added in Jackett
Click on add button
Select Torzab
Copy the tornzab feed for the indexer from jackett
Copy the api key from jackett
Select the categories you want
Test and save
Under general, define the root folder as /data/media/tv
Repeat this process for Radarr, Lidarr and readarr.
Use /data/media/movies as root for Radarr and so on.
The setup for ombi/overseerr is super simple. Just hit the url and follow the on screen instructions.
Bazarr
Navigate to YOUR_SERVER_IP:6767
Go to settings and then sonarr. Enter the host as YOUR_SERVER_IP port as 8989. Copy the api key from sonarr settings→general.
Similarly for radarr, enter the host as YOUR_SERVER_IP port as 7878. Copy the api key from radarr settings→general.
Jellyfin
Go to YOUR_SERVER_IP:8096
Add all the libraries by selecting content type and then giving a name for that library. Select the particular library location from /data/media. Repeat this for movies, tv, music, books and audiobooks.
Go to dashboard→playback, and enable transcoding by selecting as VAAPI and enter the device as /dev/dri/renderD128
Monitor GPU usage while playing content using
sudo intel_gpu_top
Heimdall
Navigate to YOUR_SERVER_IP:8090
Setup all the services you use so you don't need to remember the ports like I showed in the first screenshot.
Updating docker images
With docker compose updates are very easy.
Navigate to the compose file directory ~/server/compose/media-server.
Then docker-compose pull to download the latest images.
And finally docker-compose up -d to use the latest images.
Remove old images by docker system prune -a
What's next
You can setup VPN if torrents are blocked by your ISP/Country. I wanted to keep this guide simple and I don't use VPN for my server, so I have left out the VPN part.
You can read about port forwarding to access your server over the internet.
I find Organizrr to be much more comprehensive dashboard. And Lol at running plex just to use overseerr but still streaming with Jelly 😂 just use Jellyseerr, delete plex/over, and save a TON of system resources.
Yet... I don't get why using the *Arr stack and Plex is so popular. Plex is annoying as fuck and tries to shill you their paid bullshit at every corner. The Arr stack is buggy and having a separate system for recommendations and requests and for library management is super cumbersome for me. Compare that with Stremio... I could never convince the wife to use Plex with overseer at all. Stremio is super convenient.
Im just saying this because I spent my weekend getting another Arr stack running after years of absence and noticed that the whole thing is as convoluted and fiddly as ever and that really got me wondering why people just take this as the industry standard for torrenting.
Nice. Just want to point out that there is jellyseerr for jellyfin as an alternative to overseerr.
There is also reiverr which is new which allows managing sonarr,radarr, and jellyfin (basically it providers an interface to watch jellyfin content and also add episodes and movies to sonarr/radarr. I use reiverr for me as admin but it doesnt do requests as of now so i keep jellyseerr for my users
There is also watchtower on docker that automatically updates your images
And finally there is rdt-client (real-debrid torrent client) which is a real debrid client that pretends to be qbittorrent and allows sonarr/radarr to download from real debrid instead of torrenting it
I want to echo thanks for this, because this is such an incredible resource and it's finally motivated my lazy ass to get to work setting up my server.
Best community, thanks again for this excellent guide.
I recommend to use relevativ paths in the compose files. e.g.
- '/home/${USER}/server/configs/heimdall:/config'
becomes
- './configs/heimdall:/config'
you may want to add ":ro" to configs while you are at it.
also I like to put my service in /srv/ instead of home.
also I don't see anything about https/ssl. I recommend adding a section for letsencrypt.
when services rely on each other, it's a good idea to put them into the same compose file. (on 2nd thought: I am not sure if you already do that? To me it is not clear, if you use 1 big compose file for everything or many small ones. I would prefer to have 1 big one)
you can use "depends_on" to link services together.
you should be consistent with conventions between configurations. And you should remove config-properties that serve no purpose.:
you don't need to specifiy "container_name", when it would be same name as the service
PUID=1000 and PGID=1000 shouldn't be needed, I think.
sometimes you add explicit ":latest" to the version, and sometimes you don't
while you are at it, you may want to consider using an .env file where you could move everything that would differ between different deployment. e.g.
PUID
TZ
exposed ports, maybe
consider using podman instead of docker. The configuration is pretty much identical to docker-syntax. The main difference is, that it doesn't require a deamon with root privileges.
you may want to consider to pin version for the containers.
pro version pinning:
no unexpected changes, when you restart the container (e.g. because you accidentally pulled)
con version pinning:
when you DO want to make an update, you have to spent 2 minutes to go to docker hub to find out which version you want.
Just a tip, you can do all this even without an array of monitors. In fact, if you're feeling really adventurous, you can even just use your smartphone with no monitors involved.
the hyphened "docker-compose" cmd is deprecated and does not receive updates anymore. Use "docker compose" (as in a subcommand of the docker cli) instead. You might docker compose files that the old thing refuses.
I use minidlna, qbittorrent, qbittorrent-nox on a very old raspberry pi. A 4tb USB hard drive is attached via a powered hub. I can stream 4k Atmos using vlc installed on my "smart" tv. Can't it be this simple? What's the reason to dive into docker and plex?
As an FYI to anyone trying this, I ran into the following problems and solved them.
Port 53 (DNS) was already bound to systemd-resolved. This caused the Adguard container to fail.
https://hub.docker.com/r/adguard/adguardhome
From their documentation, do this. I added the commands I did below.
sudo mkdir /etc/systemd/resolved.conf.d
sudo touch /etc/systemd/resolved.conf.d/adguardhome.conf
sudo nano /etc/systemd/resolved.conf.d/adguardhome.conf
#Copy this in and save
[Resolve]
DNS=127.0.0.1
DNSStubListener=no
DHCP on the interface I was using on my VM was already bound to DHCP. To resolve this, set a static IP. I used the following.
sudo nano /etc/netplan/00-installer-config.yaml
#Overwrite with the following. Make sure if your adapter isn''t labeled ens33, you change it appropriately.
network:
renderer: networkd
ethernets:
ens33:
addresses:
- 192.168.1.200/24
nameservers:
addresses: [192.168.1.1]
routes:
- to: default
via: 192.168.1.1
version: 2
Nice guide! However, I've always wondered if all of these even make sense. Like, can't you just stream from the internet? I understand having thing on your physical storage device is an extra degree of freedom but it's very rare for me watching something more then once. Also while you can technically run it off a Raspberry Pi, it's not really recommended and you would need a separate PC which just adds to the cost. Meanwhile, with a simple app like Cloudstream, you can just get whatever you want whenever you want. The only advantage I see of the *arr +media server approach is not needing to connect to a VPN.
EDIT: After reading the replys just realized I should have specified by streaming sites I mean the shady ones, in my country we use different words and I see how that can confuse some people
Is it possible to do this all on Raspberry Pi OS? I purchased an 8GB RPi 4 and it came with Buster pre-installed. I don’t have any other computer. I have no way of writing Ubuntu onto a micro SD. :/
It's nice to have everything in one place, but that's not a complete guide. For instance, you mention Jellyfin and Plex, but from this text it's impossible to figure out how they work, what's the difference between these two and what should I choose. If you add a bit more context, it'll be a great material!
Can anyone assist with an issue? I get to this part of the guide: > Save the following content to the docker-compose.yml file.
I am not quite sure how to “save” it. I tried the :wq thing and it seemed to work? But then when I tried starting the contaner by inputting >docker-compose up -d
I get >usr/local/bin/docker-compose: line 1: Not: command not found
I’m stuck at this point. Any tips would be appreciated!
Truenas scale with truecharts makes all this fairly easy to get going. You don't even really need to understand kubernetes all that well. I use traefik for ingress and just set up a bunch of dns aliases so I don't have to remember port numbers
I appreciate the effort but the ad-block server does not work for YouTube on smart TVs. For all other applications (pc, android) I already have ad-block or ReVanced that stops ads.
With that, it just doesn't give enough value to dedicate a PC to run Linux for media server. I have Emby running dlna server on my gaming PC, that i can wake up from my phone whenever I need to stream something on my 70" TV in living room.
So what I could use is something that hase like phases... phase 1 being just ripping your own to whatever and being able to watch that on your tv... then other bite-sized phases. Some of us have kids lol. We don’t get hours at a time.