add documentation for jellyfin

This commit is contained in:
ibizaman 2025-07-12 23:04:07 +02:00 committed by Pierre Penninckx
parent 99c0a10b93
commit d78d0912ac
5 changed files with 437 additions and 5 deletions

View file

@ -2438,6 +2438,246 @@
"services-home-assistant-usage-voice": [
"services-home-assistant.html#services-home-assistant-usage-voice"
],
"services-jellyfin": [
"services-jellyfin.html#services-jellyfin"
],
"services-jellyfin-debug": [
"services-jellyfin.html#services-jellyfin-debug"
],
"services-jellyfin-features": [
"services-jellyfin.html#services-jellyfin-features"
],
"services-jellyfin-options": [
"services-jellyfin.html#services-jellyfin-options"
],
"services-jellyfin-options-shb.jellyfin.admin": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin"
],
"services-jellyfin-options-shb.jellyfin.admin.password": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.password"
],
"services-jellyfin-options-shb.jellyfin.admin.password.request": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.password.request"
],
"services-jellyfin-options-shb.jellyfin.admin.password.request.group": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.password.request.group"
],
"services-jellyfin-options-shb.jellyfin.admin.password.request.mode": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.password.request.mode"
],
"services-jellyfin-options-shb.jellyfin.admin.password.request.owner": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.password.request.owner"
],
"services-jellyfin-options-shb.jellyfin.admin.password.request.restartUnits": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.password.request.restartUnits"
],
"services-jellyfin-options-shb.jellyfin.admin.password.result": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.password.result"
],
"services-jellyfin-options-shb.jellyfin.admin.password.result.path": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.password.result.path"
],
"services-jellyfin-options-shb.jellyfin.admin.username": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.admin.username"
],
"services-jellyfin-options-shb.jellyfin.backup": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup"
],
"services-jellyfin-options-shb.jellyfin.backup.request": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.request"
],
"services-jellyfin-options-shb.jellyfin.backup.request.excludePatterns": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.request.excludePatterns"
],
"services-jellyfin-options-shb.jellyfin.backup.request.hooks": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.request.hooks"
],
"services-jellyfin-options-shb.jellyfin.backup.request.hooks.afterBackup": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.request.hooks.afterBackup"
],
"services-jellyfin-options-shb.jellyfin.backup.request.hooks.beforeBackup": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.request.hooks.beforeBackup"
],
"services-jellyfin-options-shb.jellyfin.backup.request.sourceDirectories": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.request.sourceDirectories"
],
"services-jellyfin-options-shb.jellyfin.backup.request.user": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.request.user"
],
"services-jellyfin-options-shb.jellyfin.backup.result": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.result"
],
"services-jellyfin-options-shb.jellyfin.backup.result.backupService": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.result.backupService"
],
"services-jellyfin-options-shb.jellyfin.backup.result.restoreScript": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.backup.result.restoreScript"
],
"services-jellyfin-options-shb.jellyfin.debug": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.debug"
],
"services-jellyfin-options-shb.jellyfin.domain": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.domain"
],
"services-jellyfin-options-shb.jellyfin.enable": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.enable"
],
"services-jellyfin-options-shb.jellyfin.ldap": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminGroup": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminGroup"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminPassword": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminPassword"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request.group": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request.group"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request.mode": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request.mode"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request.owner": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request.owner"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request.restartUnits": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminPassword.request.restartUnits"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminPassword.result": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminPassword.result"
],
"services-jellyfin-options-shb.jellyfin.ldap.adminPassword.result.path": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.adminPassword.result.path"
],
"services-jellyfin-options-shb.jellyfin.ldap.dcdomain": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.dcdomain"
],
"services-jellyfin-options-shb.jellyfin.ldap.enable": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.enable"
],
"services-jellyfin-options-shb.jellyfin.ldap.host": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.host"
],
"services-jellyfin-options-shb.jellyfin.ldap.port": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.port"
],
"services-jellyfin-options-shb.jellyfin.ldap.userGroup": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ldap.userGroup"
],
"services-jellyfin-options-shb.jellyfin.port": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.port"
],
"services-jellyfin-options-shb.jellyfin.ssl": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ssl"
],
"services-jellyfin-options-shb.jellyfin.ssl.paths": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ssl.paths"
],
"services-jellyfin-options-shb.jellyfin.ssl.paths.cert": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ssl.paths.cert"
],
"services-jellyfin-options-shb.jellyfin.ssl.paths.key": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ssl.paths.key"
],
"services-jellyfin-options-shb.jellyfin.ssl.systemdService": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.ssl.systemdService"
],
"services-jellyfin-options-shb.jellyfin.sso": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso"
],
"services-jellyfin-options-shb.jellyfin.sso.adminUserGroup": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.adminUserGroup"
],
"services-jellyfin-options-shb.jellyfin.sso.authorization_policy": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.authorization_policy"
],
"services-jellyfin-options-shb.jellyfin.sso.clientID": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.clientID"
],
"services-jellyfin-options-shb.jellyfin.sso.enable": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.enable"
],
"services-jellyfin-options-shb.jellyfin.sso.endpoint": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.endpoint"
],
"services-jellyfin-options-shb.jellyfin.sso.provider": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.provider"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecret": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecret"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request.group": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request.group"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request.mode": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request.mode"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request.owner": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request.owner"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request.restartUnits": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecret.request.restartUnits"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecret.result": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecret.result"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecret.result.path": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecret.result.path"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request.group": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request.group"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request.mode": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request.mode"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request.owner": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request.owner"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request.restartUnits": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.request.restartUnits"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.result": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.result"
],
"services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.result.path": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.sharedSecretForAuthelia.result.path"
],
"services-jellyfin-options-shb.jellyfin.sso.userGroup": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.sso.userGroup"
],
"services-jellyfin-options-shb.jellyfin.subdomain": [
"services-jellyfin.html#services-jellyfin-options-shb.jellyfin.subdomain"
],
"services-jellyfin-usage": [
"services-jellyfin.html#services-jellyfin-usage"
],
"services-jellyfin-usage-backup": [
"services-jellyfin.html#services-jellyfin-usage-backup"
],
"services-jellyfin-usage-configuration": [
"services-jellyfin.html#services-jellyfin-usage-configuration"
],
"services-jellyfin-usage-https": [
"services-jellyfin.html#services-jellyfin-usage-https"
],
"services-jellyfin-usage-ldap": [
"services-jellyfin.html#services-jellyfin-usage-ldap"
],
"services-jellyfin-usage-sso": [
"services-jellyfin.html#services-jellyfin-usage-sso"
],
"services-nextcloudserver": [
"services-nextcloud.html#services-nextcloudserver"
],

View file

@ -13,11 +13,12 @@ information is provided in the respective manual sections.
| Service | Backup | Reverse Proxy | SSO | LDAP | Monitoring | Profiling |
|-----------------------|--------|---------------|-----|-------|------------|-----------|
| [*Arr][] | Y (1) | Y | Y | Y (4) | Y (2) | N |
| [Forgejo][] | Y (1) | Y | Y | Y | Y (2) | N |
| [Home-Assistant][] | Y (1) | Y | N | Y | Y (2) | N |
| [Nextcloud Server][] | Y (1) | Y | Y | Y | Y (2) | P (3) |
| [Vaultwarden][] | Y (1) | Y | Y | Y | Y (2) | N |
| [*Arr][] | Y (1) | Y | Y | Y (4) | Y (2) | N |
| [Forgejo][] | Y (1) | Y | Y | Y | Y (2) | N |
| [Jellyfin][] | Y (1) | Y | Y | Y | Y (2) | N |
| [Home-Assistant][] | Y (1) | Y | N | Y | Y (2) | N |
| [Nextcloud Server][] | Y (1) | Y | Y | Y | Y (2) | P (3) |
| [Vaultwarden][] | Y (1) | Y | Y | Y | Y (2) | N |
Legend: **N**: no but WIP; **P**: partial; **Y**: yes
@ -31,6 +32,7 @@ Legend: **N**: no but WIP; **P**: partial; **Y**: yes
[*Arr]: services-arr.html
[Forgejo]: services-forgejo.html
[Home-Assistant]: services-home-assistant.html
[Jellyfin]: services-jellyfin.html
[Nextcloud Server]: services-nextcloud.html
[Vaultwarden]: services-vaultwarden.html
@ -42,6 +44,10 @@ modules/services/arr/docs/default.md
modules/services/forgejo/docs/default.md
```
```{=include=} chapters html:into-file=//services-jellyfin.html
modules/services/jellyfin/docs/default.md
```
```{=include=} chapters html:into-file=//services-home-assistant.html
modules/services/home-assistant/docs/default.md
```

View file

@ -164,6 +164,7 @@
(pkgs.path + "/nixos/modules/services/misc/forgejo.nix")
];
"services/home-assistant" = ./modules/services/home-assistant.nix;
"services/jellyfin" = ./modules/services/jellyfin.nix;
"services/nextcloud-server" = ./modules/services/nextcloud-server.nix;
"services/vaultwarden" = ./modules/services/vaultwarden.nix;
"contracts/backup" = ./modules/contracts/backup/dummyModule.nix;

View file

@ -180,6 +180,7 @@ in
type = types.submodule {
options = contracts.secret.mkRequester {
mode = "0400";
ownerText = "config.shb.authelia.autheliaUser";
owner = config.shb.authelia.autheliaUser;
};
};

View file

@ -0,0 +1,184 @@
# Jellyfin Service {#services-jellyfin}
Defined in [`/modules/services/jellyfin.nix`](@REPO@/modules/services/jellyfin.nix).
This NixOS module is a service that sets up a [Jellyfin](https://jellyfin.org/) instance.
Compared to the stock module from nixpkgs,
this one sets up, in a fully declarative manner
the initial wizard with an admin user
and LDAP and SSO integration.
## Features {#services-jellyfin-features}
- Declarative creation of admin user.
- Declarative selection of listening port.
- Access through [subdomain](#services-jellyfin-options-shb.jellyfin.subdomain) using reverse proxy. [Manual](#services-jellyfin-usage-configuration).
- Access through [HTTPS](#services-jellyfin-options-shb.jellyfin.ssl) using reverse proxy. [Manual](#services-jellyfin-usage-https).
- Declarative [LDAP](#services-jellyfin-options-shb.jellyfin.ldap) configuration. [Manual](#services-jellyfin-usage-ldap).
- Declarative [SSO](#services-jellyfin-options-shb.jellyfin.sso) configuration. [Manual](#services-jellyfin-usage-sso).
- [Backup](#services-jellyfin-options-shb.jellyfin.backup) through the [backup block](./blocks-backup.html). [Manual](#services-jellyfin-usage-backup).
## Usage {#services-jellyfin-usage}
### Initial Configuration {#services-jellyfin-usage-configuration}
The following snippet enables Jellyfin and makes it available under the `jellyfin.example.com` endpoint.
```nix
shb.jellyfin = {
enable = true;
subdomain = "jellyfin";
domain = "example.com";
admin = {
username = "admin";
password.result = config.shb.sops.secret.jellyfinAdminPassword.result;
};
};
shb.sops.secret.jellyfinAdminPassword.request = config.shb.jellyfin.admin.password.request;
```
This assumes secrets are setup with SOPS
as mentioned in [the secrets setup section](usage.html#usage-secrets) of the manual.
### Jellyfin through HTTPS {#services-jellyfin-usage-https}
:::: {.note}
We will build upon the [Initial Configuration](#services-jellyfin-usage-configuration) section,
so please follow that first.
::::
If the `shb.ssl` block is used (see [manual](blocks-ssl.html#usage) on how to set it up),
the instance will be reachable at `https://jellyfin.example.com`.
Here is an example with Let's Encrypt certificates, validated using the HTTP method.
First, set the global configuration for your domain:
```nix
shb.certs.certs.letsencrypt."example.com" = {
domain = "example.com";
group = "nginx";
reloadServices = [ "nginx.service" ];
adminEmail = "myemail@mydomain.com";
};
```
Then you can tell Jellyfin to use those certificates.
```nix
shb.certs.certs.letsencrypt."example.com".extraDomains = [ "jellyfin.example.com" ];
shb.jellyfin = {
ssl = config.shb.certs.certs.letsencrypt."example.com";
};
```
### With LDAP Support {#services-jellyfin-usage-ldap}
:::: {.note}
We will build upon the [HTTPS](#services-jellyfin-usage-https) section,
so please follow that first.
::::
We will use the [LLDAP block][] provided by Self Host Blocks.
Assuming it [has been set already][LLDAP block setup], add the following configuration:
[LLDAP block]: blocks-lldap.html
[LLDAP block setup]: blocks-lldap.html#blocks-lldap-global-setup
```nix
shb.jellyfin.ldap
enable = true;
host = "127.0.0.1";
port = config.shb.ldap.ldapPort;
dcdomain = config.shb.ldap.dcdomain;
adminPassword.result = config.shb.sops.secrets."jellyfin/ldap/adminPassword".result
};
shb.sops.secrets."jellyfin/ldap/adminPassword" = {
request = config.shb.jellyfin.ldap.adminPassword.request;
settings.key = "ldap/userPassword";
};
```
The `shb.jellyfin.ldap.adminPasswordFile` must be the same
as the `shb.ldap.ldapUserPasswordFile` which is achieved
with the `key` option.
The other secrets can be randomly generated with
`nix run nixpkgs#openssl -- rand -hex 64`.
And that's it.
Now, go to the LDAP server at `http://ldap.example.com`,
create the `jellyfin_user` and `jellyfin_admin` groups,
create a user and add it to one or both groups.
When that's done, go back to the Jellyfin server at
`http://jellyfin.example.com` and login with that user.
Work is in progress to make the creation of the LDAP user and group declarative too.
### With SSO Support {#services-jellyfin-usage-sso}
:::: {.note}
We will build upon the [LDAP](#services-jellyfin-usage-ldap) section,
so please follow that first.
::::
We will use the [SSO block][] provided by Self Host Blocks.
Assuming it [has been set already][SSO block setup], add the following configuration:
[SSO block]: blocks-sso.html
[SSO block setup]: blocks-sso.html#blocks-sso-global-setup
```nix
shb.jellyfin.sso = {
enable = true;
endpoint = "https://${config.shb.authelia.subdomain}.${config.shb.authelia.domain}";
secretFile = <path/to/oidcJellyfinSharedSecret>;
secretFileForAuthelia = <path/to/oidcJellyfinSharedSecret>;
};
```
Passing the `ssl` option will auto-configure nginx to force SSL connections with the given
certificate.
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.
### Backup {#services-jellyfin-usage-backup}
Backing up Jellyfin using the [Restic block](blocks-restic.html) is done like so:
```nix
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](blocks-restic.html) documentation.
## Debug {#services-jellyfin-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 {#services-jellyfin-options}
```{=include=} options
id-prefix: services-jellyfin-options-
list-id: selfhostblocks-service-jellyfin-options
source: @OPTIONS_JSON@
```