diff --git a/modules/services/jellyfin.nix b/modules/services/jellyfin.nix index 3f40dda..39c6e64 100644 --- a/modules/services/jellyfin.nix +++ b/modules/services/jellyfin.nix @@ -65,6 +65,12 @@ let in "${meta.name}_${meta.version}"; + pluginNamePrefix = + src: + let + meta = builtins.fromJSON (builtins.readFile "${src}/meta.json"); + in + "${meta.name}"; in { options.shb.jellyfin = { @@ -137,6 +143,15 @@ in The interface for plugin creation is WIP. Feel free to add yours following the examples from the LDAP and SSO plugins but know that they may require some tweaks later on. + Notably, configuration is not yet handled by this option + so that will be added in the future. + + Each plugin's meta.json must be writeable because Jellyfin appends some information + upon installing the plugin, like its active or disabled status. + SHB automatically enables the plugin + and deletes any plugin with the same prefix but other versions. + Note that SHB does not attempt to find which version is latest. + If twice the same plugin is added, the last one in the "plugins" list wins. ''; default = [ ]; type = types.listOf types.package; @@ -289,8 +304,9 @@ in ]; sourceDirectoriesText = '' [ - "services.jellyfin.dataDir" - ]''; + "services.jellyfin.dataDir" + ] + ''; }; }; }; @@ -685,6 +701,18 @@ in autoUpdate: false, assemblies: [] }" "${p}/meta.json" > "$pluginDir/meta.json" + + echo "Disabling other versions of plugin ${pluginName p}" + for p in "${config.services.jellyfin.dataDir}/plugins/${pluginNamePrefix p}"*; do + if [ "$p" = "$pluginDir" ]; then + continue + fi + echo "Marking plugin $p as disabled" + ${pkgs.jq}/bin/jq ". + { + status: \"Disabled\", + }" "$p/meta.json" > "$p/meta.json.new" + mv "$p/meta.json.new" "$p/meta.json" + done ''; in lib.concatMapStringsSep "\n" pluginInstallScript cfg.plugins diff --git a/modules/services/jellyfin/docs/default.md b/modules/services/jellyfin/docs/default.md index 53b6e56..ee964f6 100644 --- a/modules/services/jellyfin/docs/default.md +++ b/modules/services/jellyfin/docs/default.md @@ -5,9 +5,10 @@ Defined in [`/modules/services/jellyfin.nix`](@REPO@/modules/services/jellyfin.n 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. +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 {#services-jellyfin-features} diff --git a/test/services/jellyfin.nix b/test/services/jellyfin.nix index 394401d..9a9679f 100644 --- a/test/services/jellyfin.nix +++ b/test/services/jellyfin.nix @@ -128,7 +128,7 @@ let }; ldap = - { config, ... }: + { config, lib, ... }: { shb.jellyfin = { ldap = { @@ -142,6 +142,20 @@ let }; }; + # There's something weird happending here + # where this plugin disappears after a jellyfin restart. + # I don't know why this is the case. + # I tried using a real plugin here instead of a mock or just creating a meta.json file. + # But this didn't help. + shb.jellyfin.plugins = lib.mkBefore [ + (shb.mkJellyfinPlugin (rec { + pname = "jellyfin-plugin-ldapauth"; + version = "19"; + url = "https://github.com/jellyfin/${pname}/releases/download/v${version}/ldap-authentication_${version}.0.0.0.zip"; + hash = "sha256-NunkpdYjsxYT6a4RaDXLkgRn4scRw8GaWvyHGs9IdWo="; + })) + ]; + shb.hardcodedsecret.jellyfinLdapUserPassword = { request = config.shb.jellyfin.ldap.adminPassword.request; settings.content = "ldapUserPassword"; @@ -417,7 +431,23 @@ in ]; }; - testScript = commonTestScript.access; + testScript = commonTestScript.access.override { + extraScript = + { + node, + ... + }: + # I have no idea why the LDAP Authentication_19.0.0.0 plugin disappears. + '' + r = server.execute('cat "${node.config.services.jellyfin.dataDir}/plugins/LDAP Authentication_19.0.0.0/meta.json"') + if r[0] != 0: + print("meta.json for plugin LDAP Authentication_19.0.0.0 not found") + else: + c = json.loads(r[1]) + if "status" in c and c["status"] != "Disabled": + raise Exception(f'meta.json status: expected Disabled, got: {c["status"]}') + ''; + }; }; sso = jellyfinTest "sso" {