Jellyfin

Jellyfin

2023, Mar 24    

Quite some time ago I switched from Kodi to OSMC. It has run on a Raspberry Pi with an attached USB drive in my living room and happily served the family for many years. Recently, I came across Jellyfin and decided to give it a test run. It is currently replacing OSMC altogether, although that is not entirely decided at this point.

Both of these applications allow me to browse and watch our library of movies and TV shows from the comfort of our living room couch on our TV with a familiar remote and very nice polished interfaces. The user experience is as nice as browsing streaming services, such as Hulu, Netflix, etc.

Before going further, please note that I do not advocate for digital piracy. My assumption is these tools will be used for browsing and watching personally owned or licensed media, not stolen property.

Jellyfin vs. OSMC

This is not intended to be a review or in depth guide to the features of either system, but I will touch on one key difference that drove me to test run Jellyfin. As noted above, OSMC has been running well on a Raspberry Pi in my living room for years. Jellyfin is designed as a client/server model. The server manages the library (for me running on a VM in Proxmox in my basement home lab). Clients are available for a variety of systems to connect to your server. The server can stream to multiple clients and can transcode to different formats depending on the needs of the client connected.

Having the Jellyfin Android client on my phone allows me to take my full media library with me. This has already proven useful. During a bad storm my son was scared and having trouble going to sleep. I grabbed my phone and headphones and sat by his crib watching a movie while he fell asleep. We recently traveled out of state to visit family. One night we wanted to watch a movie together that I happened to own. I used their Firestick to sign in to my Jellyfin server.

The only downside so far has been while running the client on a Roku 2 in my living room browsing the library has felt a bit sluggish at times compared to my OSMC experience. As I continue to play with this new setup, I may explore other clients. One option may be to continue to use OSMC. The are references to Kodi plugins that can connect to the Jellyfin server, so I may end up continuing to run OSMC on a Raspberry Pi connect to the Jellyfin server, but that is a future experiment and post.

VM Creation

Jellyfin is hosted on my Proxmox VE Server.

Created a VM with

  • Name: jf
  • ISO image: ubuntu-22.04.2-live-server-amd64.iso
  • Cores: 4
  • Memory: 8192 / min 2048
  • VLAN Tag: # « Set to appropriate VLAN if used

Boot and run through the Ubuntu install:

  • Selected Ubuntu Server (minimized)
  • Your name: **
  • Server name: jf
  • Username: **
  • Password: **
  • Install OpenSSH Server

After reboot, update the system

sudo apt update
sudo apt upgrade

Install Jellyfin

This is straightforward, following the install guide on Jellyfin’s site.

sudo add-apt-repository universe

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://repo.jellyfin.org/jellyfin_team.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/jellyfin.gpg

cat <<EOF | sudo tee /etc/apt/sources.list.d/jellyfin.sources
Types: deb
URIs: https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release )
Suites: $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release )
Components: main
Architectures: $( dpkg --print-architecture )
Signed-By: /etc/apt/keyrings/jellyfin.gpg
EOF

sudo apt update

sudo apt install jellyfin

edit/vi the file /usr/share/jellyfin/web/config.json Remove the ChromecastPlayer plugin

"plugins/chromecastPlayer/plugin"

Manage the Jellyfin system service with your tool of choice:

sudo service jellyfin status
sudo systemctl restart jellyfin
sudo /etc/init.d/jellyfin stop

Connect to the web portal: http://jf:8096

Run through the initial setup guide. (Mostly just accepted the defaults)

SSL Certificate

I use a wildcard certificate for my domain, updated by Acme.sh. See my post here for details.

Updated my acme.sh configuration with:

export DEPLOY_SSH_SERVER="jf.theharps.cloud"
export DEPLOY_SSH_USER="********"
export DEPLOY_SSH_KEYFILE="/ssl/privkey.pem"
export DEPLOY_SSH_CERTFILE="/ssl/cert.pem"
export DEPLOY_SSH_CAFILE="/ssl/chain.pem"
export DEPLOY_SSH_FULLCHAIN="/ssl/fullchain.pem"

export DEPLOY_SSH_REMOTE_CMD='systemctl restart apache2'

acme.sh --deploy -d *.theharps.cloud --deploy-hook ssh

Apache2

Apache2 is used as a proxy in front of Jellyfin and enables SSL

sudo apt install apache2

VI: /etc/apache2/sites-available/harps.cloud.conf

<VirtualHost *:80>
    ServerName jf.theharps.cloud

    # Comment to prevent HTTP to HTTPS redirect
    Redirect permanent / https://jf.theharps.cloud:8443

    ErrorLog /var/log/apache2/harps.cloud-error.log
    CustomLog /var/log/apache2/harps.cloud-access.log combined
</VirtualHost>

<IfModule mod_ssl.c>
Listen *:8443
<VirtualHost *:8443>
    ServerName jf.theharps.cloud

    ProxyPreserveHost On

    # Tell Jellyfin to forward that requests came from TLS connections
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "8443"

    ProxyPass "/socket" "ws://127.0.0.1:8096/socket"
    ProxyPassReverse "/socket" "ws://127.0.0.1:8096/socket"

    ProxyPass "/" "http://127.0.0.1:8096/"
    ProxyPassReverse "/" "http://127.0.0.1:8096/"

    SSLEngine on
    SSLCertificateFile /ssl/fullchain.pem
    SSLCertificateKeyFile /ssl/privkey.pem
    Protocols h2 http/1.1

    # Enable only strong encryption ciphers and prefer versions with Forward Secrecy
    SSLCipherSuite HIGH:RC4-SHA:AES128-SHA:!aNULL:!MD5
    SSLHonorCipherOrder on

    # Disable insecure SSL and TLS versions
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

    ErrorLog /var/log/apache2/harps.cloud-error.log
    CustomLog /var/log/apache2/harps.cloud-access.log combined
</VirtualHost>
</IfModule>

Enable the required Apache2 modules and enable our site.

# Enable the required apache modules
a2enmod headers proxy proxy_http ssl proxy_wstunnel remoteip http2

# Test our configuration
apache2ctl configtest

# Enable our site and disable the default
a2ensite harps.cloud.conf
a2dissite 000-default.conf

# Restart apache
systemctl restart apache2

USB Drive

Attach the USB drive to an available USB slot on the Proxmox host. (This is the drive that was attached to my Raspberry Pi and already contained my media library).

In the Proxmox UI, on the Jellyfin VM, go to Hardware, Add USB, and select the USB drive. Restart the VM.

SSH to the Jellyfin VM. The following commands may be useful for identifying the drive:

lsusb  # list usb devices - confirm that the drive is present.

fdisk -l   # should show the partitions on the drive...

lsblk -o name,size,type,fstype,mountpoints   # confirm format (ntfs) and partition (/dev/sdb2)

Create a mount point and test the mount:

mkdir /media/usb_drive
mount -t ntfs-3g /dev/sdb2 /media/usb_drive

Use blkid to get the UUID

$ blkid
/dev/sdb2: LABEL="Media Drive" BLOCK_SIZE="512" UUID="1A04AADE04BAAFFF" TYPE="ntfs" PARTLABEL="Basic data partition" PARTUUID="5498cc86-7793-4ecc-FF20-555554899cff"
...

Make a backup of fstab

cp /etc/fstab /etc/fstab.orig

Add mount to /etc/fstab

UUID=1A04AADE04BAAFFF /media/usb_drive ntfs-3g  defaults,windows_names,locale=en_US.utf8  0 0

In the Jellyfin web console, add sources for Movies and Shows and point those to the folders on the mounted drive.

DNS and Port forwarding

In my DNS provider I updated jf.theharps.cloud to my public IP address

Next I updated my gateway to forward the Jellyfin port back to the SSL port that Apache2 is configured to run on.

Final notes

I still highly recommend OSMC and may end up using it in conjunction with Jellyfin. However, having a client/server streaming setup has already proven beneficial, and so far we aren’t missing any aspects of OSMC, so I can confidently recommend either or a combination of these tools depending on your needs.