From 31d40a5345d71bccf762fe46a6b952275e38d21d Mon Sep 17 00:00:00 2001 From: Ross Smyth <18294397+RossSmyth@users.noreply.github.com> Date: Sat, 18 Jul 2026 23:43:31 -0400 Subject: [PATCH] nixos/navidrome: Add administration wrapper --- nixos/modules/services/audio/navidrome.nix | 37 ++++++++++++++++++++-- nixos/tests/navidrome.nix | 3 ++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/nixos/modules/services/audio/navidrome.nix b/nixos/modules/services/audio/navidrome.nix index a57fa2e159c6..65326f7b797b 100644 --- a/nixos/modules/services/audio/navidrome.nix +++ b/nixos/modules/services/audio/navidrome.nix @@ -13,6 +13,8 @@ let mkPackageOption mkOption maintainers + optionals + optionalString ; inherit (lib.types) addCheck @@ -23,6 +25,10 @@ let str submodule ; + inherit (pkgs) + writeShellScriptBin + ; + cfg = config.services.navidrome; settingsFormat = pkgs.formats.json { }; in @@ -146,6 +152,29 @@ in let inherit (lib) mkIf optional getExe; WorkingDirectory = "/var/lib/navidrome"; + + settingsFile = settingsFormat.generate "navidrome.json" cfg.settings; + + # Wrapper so that users can do admin tasks with the configured navidrome + # + # Since it is common that the user may be running this from their home directory, + # or possible something else, we should not inherit the CWD or else it may error + # trying to chdir to it since this runs as the navidrome user. + wrappedNavi = writeShellScriptBin "navidrome-cli" '' + exec systemd-run \ + --quiet \ + --pty \ + --wait \ + --service-type=exec \ + --collect \ + --working-directory=${WorkingDirectory} \ + ${optionalString (cfg.environmentFile != null) "-p EnvironmentFile=${cfg.environmentFile}"} \ + -p Group=${cfg.user} \ + -p User=${cfg.group} \ + -u navidrome-admin.service \ + -- \ + ${lib.getExe cfg.package} --configfile ${settingsFile} "$@" + ''; in mkIf cfg.enable { systemd = { @@ -169,9 +198,7 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { - ExecStart = '' - ${getExe cfg.finalPackage} --configfile ${settingsFormat.generate "navidrome.json" cfg.settings} - ''; + ExecStart = "${lib.getExe cfg.finalPackage} --configfile ${settingsFile}"; EnvironmentFile = lib.mkIf (cfg.environmentFile != null) [ cfg.environmentFile ]; User = cfg.user; Group = cfg.group; @@ -235,6 +262,10 @@ in users.groups = mkIf (cfg.group == "navidrome") { navidrome = { }; }; networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.settings.Port ]; + + environment.systemPackages = [ + wrappedNavi + ]; }; meta.maintainers = with maintainers; [ fsnkty diff --git a/nixos/tests/navidrome.nix b/nixos/tests/navidrome.nix index 286fec66da2e..eaa6cd1b58b4 100644 --- a/nixos/tests/navidrome.nix +++ b/nixos/tests/navidrome.nix @@ -19,5 +19,8 @@ # Make sure we saw at least one plugin load machine.wait_for_console_text("plugin=listenbrainz-daily-playlist") machine.wait_for_open_port(4533) + # Make sure the admin wrapper is working + machine.succeed("cd ~") + assert "--version" in machine.succeed("navidrome-cli --help") ''; }