Jellyfin #
Introduction #
Jellyfin is a free and open-source media server and suite of multimedia applications designed to organize, manage, and share digital media files to networked devices. It is an alternative to Emby and Plex.
This will serve as a guide to configuring Jellyfin in a Debian Proxmox LXC with hardware transcoding on Intel hardware.12
Installation #
This guide will cover the installation of Jellyfin on Debian Bullseye with non-free repositories enabled.
In my case, I will be using Debian in a Linux container (LXC) on Proxmox.
Proxmox LXC Configuration #
Ensure that you have a Debian LXC template downloaded. On Proxmox, you can do this by navigating to the storage menu on the Proxmox GUI configured for CT Templates. In a default Proxmox install, this is typically under the ’local’ storage.
Create a Debian CT and configure it as you would with your environment. Give it a static IP as it will be running a server.
Note: To enable hardware acceleration, Jellyfin needs to run in a privileged LXC container. Ensure that the “unprivileged” option is not enabled when initially creating the container in Proxmox.
Please note the risks of running a privileged LXC container:
Installing Jellyfin #
Main article:3 https://jellyfin.org/docs/general/installation/linux/#debian
The Jellyfin team provides a Debian repository for Buster and Bullseye. There are two options to enable this:
- Ensure that
curl
andgnupg
are installed:
sudo apt install curl gnupg
- Download the signing key:
sudo mkdir /etc/apt/keyrings
curl -fsSL https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release )/jellyfin_team.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/jellyfin.gpg
- Add a repository configuration to apt:
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
Install extrepo
and enable the jellyfin repos:
sudo apt install extrepo
sudo extrepo enable jellyfin
After enabling the repository, you can proceed to install Jellyfin:
sudo apt update
sudo apt install jellyfin
Enabling Hardware Acceleration on Proxmox LXC #
Main article:4 https://jellyfin.org/docs/general/administration/hardware-acceleration/#va-api-and-qsv-hardware-acceleration-on-lxc-on-proxmox
At this point, you should shut down the LXC container as we will be modifying its configuration.
-
Ensure that the required drivers are installed on the Proxmox host. Since Proxmox runs on top of Debian, a simple Google search of “debian drivers for x” should assist here.
-
Add your GPU to the container by editing
/etc/pve/lxc/<container-id>.conf
:5Versions prior to Proxmox VE 7.1 should use
cgroup
instead ofcgroup2
lxc.cgroup2.devices.allow: c 226:0 rwm
lxc.cgroup2.devices.allow: c 226:128 rwm
lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,create=file
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
-
Reboot the container.
-
Verify that a
render
device is now present in/dev/dri
in the container:
# ls -l /dev/dri
total 0
crw-rw---- 1 root video 226, 0 Dec 31 00:00 card0
crw-rw---- 1 root input 226, 128 Dec 31 00:00 renderD128
- Install
jellyfin-ffmpeg
and make sure it is version 4.4.1-2 or higher. This should ship withintel-media-driver
, which is necessary for Intel QuickSync.6
sudo apt install jellyfin-ffmpeg5
- Check the output of
vainfo
, and make sure the iHD driver is loaded for Intel QuickSync:
sudo /usr/lib/jellyfin-ffmpeg/vainfo | grep iHD
- Add the
jellyfin
user tovideo
,render
, or theinput
group depending on which one owns the device in the container, as seen in step 4. Then restart Jellyfin, to allowffmpeg
to access the device. In my case it was theinput
group:
sudo usermod -aG input jellyfin
sudo systemctl restart jellyfin
-
Log in to Jellyfin via the WebUI on
http://{SERVER-IP}:8096
, access the administrator dashboard in the settings, and underServer > Playback > Transcoding
, select either VAAPI or QSV, depending on your preference. -
Finally, check if transcoding is enabled by opening media that requires transcoding, and looking through your logs to find
ffmpeg-transcode-*.txt
under/var/log/jellyfin
, or theAdvanced > Logs
in the admin dashboard.
Web Server Configurations #
Nginx Reverse Proxy #
https://jellyfin.org/docs/general/networking/#running-jellyfin-behind-a-reverse-proxy https://jellyfin.org/docs/general/networking/nginx/
server {
server_name jellyfin.domain.tld;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_buffering off;
proxy_pass http://(SERVER-IP):8096;
}
location = / {
return 302 http://$host/web/;
#return 302 https://$host/web/;
}
# location block for /web - This is purely for aesthetics so /web/#!/ works instead of having to go to /web/index.html/#!/
location = /web/ {
# Proxy main Jellyfin traffic
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_pass http://(SERVER-IP):8096/web/index.html;
}
location /socket {
# Proxy Jellyfin Websockets traffic
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_pass http://(SERVER-IP):8096;
}
client_max_body_size 20M;
listen [::]:443 ssl http2; # managed by Certbot
listen 443 ssl http2; # managed by Certbot
ssl_certificate (generate these options using certbot); # managed by Certbot
ssl_certificate_key (generate these options using certbot); # managed by Certbot
include (generate these options using certbot); # managed by Certbot
ssl_dhparam (generate these options using certbot); # managed by Certbot
}
Extras #
Change transcoding folder #
If Jellyfin was installed in an LXC, it is likely that a small 8-16 GB disk image was used as the root disk for the OS.
If this is the case, it is highly recommended to change the transcoding folder to another disk (which is hopefully also present, as you will likely need to store several gigabytes of media to serve.)
This can be accomplished in the admin dashboard under Server > Playback > Transcoding > Transcode path
.
-
https://www.reddit.com/r/PleX/comments/hdoh9l/nvidia_nvenc_vs_intel_quick_sync/ ↩︎
-
https://www.reddit.com/r/ffmpeg/comments/ro5l7x/quicksync_vs_nvenc_vs_cpu_for_transcoding/ ↩︎
-
https://jellyfin.org/docs/general/installation/linux/#debian ↩︎
-
https://jellyfin.org/docs/general/administration/hardware-acceleration/ ↩︎
-
https://blog.konpat.me/dev/2019/03/11/setting-up-lxc-for-intel-gpu-proxmox.html ↩︎