Jellyfin
Jellyfin is the volunteer-built media solution that puts you in control of your media. Stream to any device from your own server, with no strings attached.
Installation and configuration
To get up and running with Jellyfin, add the packages pkgs.jellyfin
pkgs.jellyfin-web
& pkgs.jellyfin-ffmpeg
to your `configuration.nix` file as shown below.
{
services.jellyfin.enable = true;
environment.systemPackages = [
pkgs.jellyfin
pkgs.jellyfin-web
pkgs.jellyfin-ffmpeg
];
}
If you want more advanced configuration, use something like what's shown below and see the docs for more configuration options
{
services.jellyfin = {
enable = true;
openFirewall = true;
};
}
Once you have included the packages to be installed, and enabled and configured Jellyfin to your liking, then rebuild your system for changes to take effect.
$ sudo nixos-rebuild switch
After the rebuild is complete, Jellyfin should be running. Verify that it is with the following command.
$ sudo systemctl status jellyfin
If jellyfin is not running you should be able to start it by running jellyfin
in your terminal.
$ jellyfin
After you've verified that Jellyfin is running you can start the configuration process.
- The Jellyfin server should be running on port 8096.
- Go to http://localhost:8096 if you are setting this up on your primary computer or want to test your build locally.
- If you're logging into a remote server, replace localhost with the ip address of the server.
Allow Jellyfin to read external drives
You might encounter permission issues when you try to access external drives if you haven't configured anything else with the server yet. If you haven't explicitly set up a mounting configuration for your drives and instead let your desktop environment (e.g. GNOME or KDE) automatically mount it when you try accessing it via their file explorers, Jellyfin won't be able to access the drive. This is because the desktop environment mounts it to your user, while Jellyfin runs by default as the "jellyfin" user.
The easiest way to allow it to see these external drives is to change the service's user . Here is an example:
services.jellyfin = {
enable = true;
openFirewall = true;
user="yourusername";
};
If you have changed the user option after you have already installed Jellyfin, you have to change the ownership of the folder `/var/lib/jellyfin` to the user you set it to by doing this:
sudo chown -R yourusername:yourusername /var/lib/jellyfin
Additionally, you should also change the ownership of the cache directory to avoid transcoding issues:
sudo chown -R yourusername:yourusername /var/cache/jellyfin
Finally, restart Jellyfin for the changes to take effect:
systemctl restart jellyfin
The alternative is to explicitly mount the drives via Filesystems. This takes more effort to set up and requires every new drive to be explicitly declared, but allows more control in what Jellyfin is allowed to see.
Intro Skipper plugin
If you install the Intro Skipper plugin, it will not be able to display the skip button in the web interface. This is due to the plugin being unable to modify contents of files in the nix store. To get around this you can make the changes yourself with this:
nixpkgs.overlays = with pkgs; [
(
final: prev:
{
jellyfin-web = prev.jellyfin-web.overrideAttrs (finalAttrs: previousAttrs: {
installPhase = ''
runHook preInstall
# this is the important line
sed -i "s#</head>#<script src=\"configurationpage?name=skip-intro-button.js\"></script></head>#" dist/index.html
mkdir -p $out/share
cp -a dist $out/share/jellyfin-web
runHook postInstall
'';
});
}
)
];
Hardware transcoding
In most cases you want to make most of your hardware. Modern boards often come with a hardware accelerator, all you need to do is enable it!
Source: https://jellyfin.org/docs/general/administration/hardware-acceleration.html
VAAPI and Intel QSV
VAAPI and QSV is often available on platforms with Intel GPUs but need their corresponding packages in hardware.graphics.extraPackages
.
You have to choose between intel-vaapi-driver
(old driver for pre-Broadwell CPUs) and intel-media-driver
depending of your CPU.
{ pkgs, lib,config, ... }:
{
# 1. enable vaapi on OS-level
nixpkgs.config.packageOverrides = pkgs: {
# Only set this if using intel-vaapi-driver
intel-vaapi-driver = pkgs.intel-vaapi-driver.override { enableHybridCodec = true; };
};
systemd.services.jellyfin.environment.LIBVA_DRIVER_NAME = "iHD"; # Or "i965" if using older driver
environment.sessionVariables = { LIBVA_DRIVER_NAME = "iHD"; }; # Same here
hardware.graphics = {
enable = true;
extraPackages = with pkgs; [
intel-media-driver # For Broadwell (2014) or newer processors. LIBVA_DRIVER_NAME=iHD
intel-vaapi-driver # For older processors. LIBVA_DRIVER_NAME=i965
libva-vdpau-driver # Previously vaapiVdpau
intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
# OpenCL support for intel CPUs before 12th gen
# see: https://github.com/NixOS/nixpkgs/issues/356535
intel-compute-runtime-legacy1
vpl-gpu-rt # QSV on 11th gen or newer
intel-media-sdk # QSV up to 11th gen
intel-ocl # OpenCL support
];
};
# 2. do not forget to enable jellyfin
services.jellyfin.enable = true;
}
Troubleshooting VAAPI and Intel QSV
You can check supported vaapi profile supported by your CPU / driver with : nix-shell -p libva-utils --run vainfo
. If
You can check the OpenCL properties and devices available on the system with : nix-shell -p clinfo --run clinfo
. If clinfo shows Number of platforms 0
on the first line, OpenCL is not enabled or available.
The command intel_gpu_top
, provided by the intel-gpu-tools
package is also useful to check the status of your intel GPU: nix-shell -p intel-gpu-tools --run intel_gpu_top
.
At least on Intel N100 CPU, you will need the option hardware.enableAllFirmware = true;
otherwise GuC formware will not load properly. Here is the type of error you will get without it :
[ 4.174843] i915 0000:00:10.0: [drm] *ERROR* GT0: GuC firmware i915/tgl_guc_70.bin: fetch failed -ENOENT
[ 4.175621] i915 0000:00:10.0: [drm] GT0: GuC firmware(s) can be downloaded from https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915
[ 4.176286] i915 0000:00:10.0: [drm] GT0: GuC firmware i915/tgl_guc_70.bin version 0.0.0
[ 4.176350] i915 0000:00:10.0: [drm] *ERROR* GT0: GuC initialization failed -ENOENT
[ 4.176977] i915 0000:00:10.0: [drm] *ERROR* GT0: Enabling uc failed (-5)
[ 4.177502] i915 0000:00:10.0: [drm] *ERROR* GT0: Failed to initialize GPU, declaring it wedged!
VAAPI and Intel QSV on Arc GPU
If you want to use an Arc GPU for transcoding, you may need to override the ffmpeg version used by jellyfin to ensure that it is compiled with vpl
and, potentially, unfree
. An example to achieve this through an overlay:
{ pkgs, ... }:
let
jellyfin-ffmpeg-overlay = (
_ prev: {
jellyfin-ffmpeg = prev.jellyfin-ffmpeg.override {
# Exact version of ffmpeg_* depends on what jellyfin-ffmpeg package is using.
# In 24.11 it's ffmpeg_7-full.
# See jellyfin-ffmpeg package source for details
ffmpeg_7-full = prev.ffmpeg_7-full.override {
withMfx = false; # This corresponds to the older media driver
withVpl = true; # This is the new driver
withUnfree = true;
};
};
}
);
in
{
nixpkgs.overlays = [ jellyfin-ffmpeg-overlay ];
}
This will trigger a rebuild of Jellyfin package, but the end result is that if you select "Intel QuickSync (QSV)" you should see little to no CPU load when transcoding.
Note that if your system has an integrated GPU (one built into the CPU) and a discrete GPU, you may need to select the QSV device in the "Playback" settings. Otherwise the device may be picked at random and produce random results. You can use intel_gpu_top -L
to identify the devices.
Related: Accelerated Video Playback and Intel Graphics