selfhostblocks/modules/services/jellyfin/docs/default.md
2026-02-24 20:00:36 +01:00

6 KiB

Jellyfin Service

Defined in /modules/services/jellyfin.nix.

This NixOS module is a service that sets up a Jellyfin instance.

Compared to the stock module from nixpkgs, this one sets up, in a fully declarative manner:

  • the initial wizard with an admin user thanks to a custom Jellyfin CLI and a custom restart logic to apply the changes from the CLI.
  • LDAP and SSO integration thanks to a custom declarative installation of plugins.

Features

Usage

Initial Configuration

The following snippet assumes a few blocks have been setup already:

shb.jellyfin = {
  enable = true;
  subdomain = "jellyfin";
  domain = "example.com";

  admin = {
    username = "admin";
    password.result = config.shb.sops.secret."jellyfin/adminPassword".result;
  };

  ldap = {
    enable = true;
    host = "127.0.0.1";
    port = config.shb.lldap.ldapPort;
    dcdomain = config.shb.lldap.dcdomain;
    adminPassword.result = config.shb.sops.secret."jellyfin/ldap/adminPassword".result
  };

  sso = {
    enable = true;
    endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
  
    secretFile = config.shb.sops.secret."jellyfin/sso_secret".result;
    secretFileForAuthelia = config.shb.sops.secret."jellyfin/authelia/sso_secret".result;
  };
};

shb.sops.secret."jellyfin/adminPassword".request = config.shb.jellyfin.admin.password.request;

shb.sops.secret."jellyfin/ldap/adminPassword".request = config.shb.jellyfin.ldap.adminPassword.request;

shb.sops.secret."jellyfin/sso_secret".request = config.shb.jellyfin.sso.sharedSecret.request;
shb.sops.secret."jellyfin/authelia/sso_secret" = {
  request = config.shb.jellyfin.sso.sharedSecretForAuthelia.request;
  settings.key = "jellyfin/sso_secret";
};

Secrets can be randomly generated with nix run nixpkgs#openssl -- rand -hex 64.

The user and admin LDAP groups are created automatically.

The shb.jellyfin.sso.secretFile and shb.jellyfin.sso.secretFileForAuthelia options must have the same content. The former is a file that must be owned by the jellyfin user while the latter must be owned by the authelia user. I want to avoid needing to define the same secret twice with a future secrets SHB block.

Certificates

For Let's Encrypt certificates, add:

{
  shb.certs.certs.letsencrypt.${domain}.extraDomains = [
    "${config.shb.jellyfin.subdomain}.${config.shb.jellyfin.domain}"
  ];
}

Backup

Backing up Jellyfin using the Restic block is done like so:

shb.restic.instances."jellyfin" = {
  request = config.shb.jellyfin.backup;
  settings = {
    enable = true;
  };
};

The name "jellyfin" in the instances can be anything. The config.shb.jellyfin.backup option provides what directories to backup. You can define any number of Restic instances to backup Jellyfin multiple times.

You will then need to configure more options like the repository, as explained in the restic documentation.

Impermanence

To save the data folder in an impermanence setup, add:

{
  shb.zfs.datasets."safe/jellyfin".path = config.shb.jellyfin.impermanence;
}

Declarative LDAP

To add a user USERNAME to the user and admin groups for jellyfin, add:

shb.lldap.ensureUsers.USERNAME.groups = [
  config.shb.jellyfin.ldap.userGroup
  config.shb.jellyfin.ldap.adminGroup
];

Application Dashboard

Integration with the dashboard contract is provided by the dashboard option.

For example using the Homepage service:

{
  shb.homepage.servicesGroups.Media.services.Jellyfin = {
    sortOrder = 1;
    dashboard.request = config.shb.jellyfin.dashboard.request;
  };
}

An API key can be set to show extra info:

{
  shb.homepage.servicesGroups.Media.services.Jellyfin = {
    apiKey.result = config.shb.sops.secret."jellyfin/homepageApiKey".result;
  };

  shb.sops.secret."jellyfin/homepageApiKey".request =
    config.shb.homepage.servicesGroups.Media.services.Jellyfin.apiKey.request;
}

Debug

In case of an issue, check the logs for systemd service jellyfin.service.

Enable verbose logging by setting the shb.jellyfin.debug boolean to true.

Options Reference

id-prefix: services-jellyfin-options-
list-id: selfhostblocks-service-jellyfin-options
source: @OPTIONS_JSON@