DEV Community

Cover image for My Unnecessary Adventure in (Re)Building a Media Sever
Kyle Schwartz
Kyle Schwartz

Posted on

My Unnecessary Adventure in (Re)Building a Media Sever

Welcome! Strap in because this is gonna be a long ride.

To preface, I had an existing media server that I broke some permissions and reinstalling was the only option. I had an existing RAID 0 setup with lots of data I did not want to lose, plus a standalone SSD. So, without further adieu, here we go!

Installing Ubuntu Server

I chose Ubuntu Server because Ubuntu has a great deal of community support and I have no need for a desktop GUI.

Download the ISO from here. You may have to choose 'Option 3' to actually get a download. At the time of writing, I'm using 20.04.1, so take that into account.

My tool of choice for burning ISOs is balenaEtcher.

Plug in the USB, boot to it, and follow setup. Make sure you enable the SSH server AND NO LVM ON THE SSD. Check to make sure the full capacity of the SSD is mounted to / and then you're good to go. Finish the setup, remove the USB, and reboot. Now we'll switch to SSH.

Configuring SSH

Port 22 sucks, but we need to login with it. Connect to the server on port 22 with the credentials you added during install.

Open the port in the firewall

sudo ufw allow 8364/tcp 
Enter fullscreen mode Exit fullscreen mode

Open the SSH config file and change the port used

sudo nano /etc/ssh/sshd_config 
Enter fullscreen mode Exit fullscreen mode

Find the line containing Port 22, uncomment, and change to Port 8364. Save (ctrl x).

Restart the SSH server and then reconnect on your client.

sudo systemctl restart ssh 
Enter fullscreen mode Exit fullscreen mode

Drive Mounting

Find the UUID of the drive:

sudo blkid 
Enter fullscreen mode Exit fullscreen mode

Add your drive to /etc/fstab (BE CAREFUL, THIS CAN BRICK STUFF):

sudo nano /etc/fstab 
Enter fullscreen mode Exit fullscreen mode

E.g:

UUID=ccc56606-385e-4a16-89c4-7f1513ab1641 /home ext4 defaults 0 0 
Enter fullscreen mode Exit fullscreen mode

Reboot the system and your drive your be properly mounted.

Docker

First, update your system:

sudo apt update sudo apt upgrade 
Enter fullscreen mode Exit fullscreen mode

Instead of repeating things, go follow the official Docker tutorial here. Just follow the 'Install using the repository' and 'Install Docker Engine' sections.

Then, install Docker Compose by following the tutorial here.

The next part is taken mostly from Smart Home Beginner.

We will add the current user to the docker group to simplify some things in the future.

sudo gpasswd -a $USER docker 
Enter fullscreen mode Exit fullscreen mode

Activate the changes using the following:

newgrp docker 
Enter fullscreen mode Exit fullscreen mode

Portainer

Portainer is our docker management solution. Yes, I have serious issues with it but currently don't have an alternative. Maybe this will change in the future, but here we are.

Run the following commands to get Portainer up and running:

docker volume create portainer_data docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce docker run -d -p 9001:9001 --name portainer_agent --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes portainer/agent 
Enter fullscreen mode Exit fullscreen mode

Open a browser and go to your computer's IP with the port 9000. For me, that's http://192.168.1.50:9000. Chose a username and password, then create user.

Choose "Docker" and press "Connect".

Now that you are in the web panel, click on 'local' in the middle, and then the 'Stacks' tab on the left. Click 'Add stack' and give it a name such as "main_stack". Paste in the following config and adjust it to fit your needs.

--- version: "2.3" services: organizr: image: linuxserver/organizr container_name: organizr environment: - PUID=${PUID} - PGID=${PGID} - TZ=${TZ} volumes: - ${USERDIR}/organizr:/config ports: - 9983:80 restart: unless-stopped watchtower: container_name: watchtower restart: always image: containrrr/watchtower volumes: - /var/run/docker.sock:/var/run/docker.sock command: --schedule "0 0 4 * * *" --cleanup radarr: image: linuxserver/radarr container_name: radarr environment: - PUID=${PUID} - PGID=${PGID} - TZ=${TZ} volumes: - ${USERDIR}/radarr:/config - ${USERDIR}/media/movies:/movies - ${USERDIR}/downloads:/downloads ports: - 7878:7878 restart: unless-stopped sonarr: image: linuxserver/sonarr container_name: sonarr environment: - PUID=${PUID} - PGID=${PGID} - TZ=${TZ} volumes: - ${USERDIR}/sonarr:/config - ${USERDIR}/media/tv:/tv - ${USERDIR}/downloads:/downloads ports: - 8989:8989 restart: unless-stopped duckdns: image: linuxserver/duckdns container_name: duckdns environment: - TZ=${TZ} - SUBDOMAINS=kyleserver - TOKEN=326ab158-e842-4d0e-aa20-233e0f7e51e3 restart: unless-stopped minecraft-creative: container_name: minecraft-creative image: itzg/minecraft-server environment: EULA: "true" TYPE: PAPER VERSION: 1.16.2 CONSOLE: "false" LEVEL_TYPE: "flat" ports: - 25566:25565 volumes: - ${USERDIR}/minecraft-creative:/data restart: unless-stopped minecraft-survival: container_name: minecraft-survival image: itzg/minecraft-server environment: EULA: "true" TYPE: PAPER VERSION: 1.16.2 CONSOLE: "false" MEMORY: 2G ports: - 25565:25565 volumes: - ${USERDIR}/minecraft-survival:/data restart: unless-stopped qbittorrent: image: linuxserver/qbittorrent:14.2.5.99202004250119-7015-2c65b79ubuntu18.04.1-ls93 container_name: qbittorrent network_mode: "service:gluetun" volumes: - ${USERDIR}/docker/qbittorrent:/config - ${USERDIR}/downloads:/downloads restart: unless-stopped environment: - PUID=${PUID} - PGID=${PGID} - TZ=${TZ} - UMASK_SET=002 - WEBUI_PORT=4545 gluetun: image: qmcgaw/private-internet-access container_name: gluetun cap_add: - NET_ADMIN network_mode: bridge ports: - 8888:8888 - 8388:8388 - 8388:8388/udp # Shadowsocks - 8001:8001 - 4545:4545 - 6881:6881 - 6881:6881/udp volumes: - ${USERDIR}/gluetun:/gluetun environment: - VPNSP=surfshark - TZ=${TZ} - USER=USERNAME - PASSWORD=PASSWORD - REGION=Canada Toronto restart: unless-stopped 
Enter fullscreen mode Exit fullscreen mode

Next, run id and note your uid and pid. We will input these as PUID and PGID in the "Environment" section.

PUID=1000 PGID=1000 TZ="America/Toronto" USERDIR="/home/user" 
Enter fullscreen mode Exit fullscreen mode

Add any environment variables that you need NOW as I don't believe these can be changed in the future.

Click 'Deploy the stack'.

Currently, qbittorrent has an issue with mismatched torrent names, that's why it's using a custom image version. If it gets resolved in the future, remove everything after the colon.

These are simply the containers I use for everything I do. The 'gluetun' container connects to Surfshark VPN and routes the qbittorrent container's traffic through, allowing a normal container to connect to a VPN. This can be done with any container by moving its ports to gluetun and setting its network_mode to "service:gluetun". After that, go and check each container to make sure it's working.

Jellyfin

Welp, this is gonna be a fun one. If you don't want to do hardware transcoding with a GPU, simply add a standard container to the above compose file. Otherwise, come along for this hell of a ride. There is no guarantee that some of these steps aren't redundant as I have no clue how any of this works. But, ideally, everything will work by the end of this.

Firstly, we need to install the NVIDIA drivers. I'm using a GTX 1050ti but it should work for any NVIDIA card 10-series or newer.

Run these commands first to disable Nouveau:

sudo bash -c "echo blacklist nouveau > /etc/modprobe.d/blacklist-nvidia-nouveau.conf" sudo bash -c "echo blacklist nouveau > /etc/modprobe.d/blacklist-nvidia-nouveau.conf" 
Enter fullscreen mode Exit fullscreen mode

What is Nouveau and why are we disabling it? How dare you ask! Subsequently, I have no clue but it's what we gotta do.

Reboot.

Install DMKS:

sudo apt install dkms 
Enter fullscreen mode Exit fullscreen mode

Follow the instructions here to install the drivers.
Additional Notes:

  • Update the version number in the other commands
  • Each command needs the be run with sudo

Click 'Yes' for everything, and after exiting the GUI, reboot, then run the test commands.

Install ffmpeg:

sudo apt install ffmpeg 
Enter fullscreen mode Exit fullscreen mode

Next, we need to setup the NVIDIA Container Toolkit. Follow the official instructions here.

Now the GPU should be good to go! Next, we need to actually setup Jellyfin. Going back to SSH, go to your home dir (cd).

Create a new docker compose file called docker-compose.yml and fill it with the following:

version: "2.3" services: jellyfin: image: linuxserver/jellyfin container_name: jellyfin network_mode: "host" runtime: nvidia environment: - PUID=1000 - PGID=1000 - TZ=America/Toronto - NVIDIA_VISIBLE_DEVICES=all volumes: - /home/user/jellyfin:/config - /home/user/media/tv:/data/tvshows - /home/user/media/movies:/data/movies ports: - 8080:8096 - 7359:7359/udp restart: unless-stopped 
Enter fullscreen mode Exit fullscreen mode

Run docker-compose up -d and Jellyfin will be running. Counterintuitvly, go to port 8096 on your server's IP and login.

Change Jellyfin Settings

  • Go to Settings > Advanced > Networking. Change "Local HTTP port number" and "Public HTTP port number" to 8080.
  • Go to Server > Playback and under "Hardware acceleration" choose 'Nvidia NVENC'. Select which files you want to decode.
  • Change 'ffmpeg path' to /usr/bin

Restart Jellyfin from Portainer, and you're good to go!

Conclusion

It was a lot of work, but hopefully everything works. Remember, DuckDuckGo and StackOverflow are your friends. If something doesn't work, let me know below and I'll do my best to help.

Good luck and stay curious!

Sources

Top comments (0)