{ config, lib, ... }: let cfg = config.guests.navidrome; envFile = "/run/secrets/navidrome.env"; hasLastfmSecrets = cfg.lastfmApiKeySecret != null && cfg.lastfmSecretSecret != null; hostSecrets = ../secrets + "/${config.networking.hostName}.yaml"; in { options.guests.navidrome = { dataPath = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; example = "/srv/navidrome"; description = "Host path bind-mounted as Navidrome's state directory."; }; musicPath = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; example = "/srv/music"; description = "Host path bind-mounted as Navidrome's music directory."; }; dataDir = lib.mkOption { type = lib.types.str; default = "/var/lib/navidrome"; description = "Guest path where Navidrome stores state."; }; musicDir = lib.mkOption { type = lib.types.str; default = "/music"; description = "Guest path where Navidrome reads the music library."; }; port = lib.mkOption { type = lib.types.port; default = 4533; description = "Port Navidrome listens on."; }; enableSharing = lib.mkOption { type = lib.types.bool; default = true; description = "Enables Navidrome sharing support."; }; settings = lib.mkOption { type = lib.types.attrs; default = { }; description = "Additional non-secret Navidrome settings."; }; lastfmApiKeySecret = lib.mkOption { type = lib.types.nullOr lib.types.str; default = "services/navidrome/lastfm/api-key"; description = "SOPS secret name containing the Navidrome Last.fm API key."; }; lastfmSecretSecret = lib.mkOption { type = lib.types.nullOr lib.types.str; default = "services/navidrome/lastfm/secret"; description = "SOPS secret name containing the Navidrome Last.fm secret."; }; }; config = lib.mkIf cfg.enable { assertions = [ { assertion = cfg.dataPath != null; message = "guests.navidrome.dataPath must point at the host directory that stores Navidrome state."; } { assertion = cfg.musicPath != null; message = "guests.navidrome.musicPath must point at the host directory that stores the music library."; } ]; guests.navidrome = { interior.modules.services.navidrome = { enable = true; inherit (cfg) dataDir musicDir port enableSharing settings ; environmentFile = if hasLastfmSecrets then envFile else null; }; mounts = { ${cfg.dataDir} = { directory = cfg.dataPath; owner = config.registry."stable-uid".${config.networking.hostName}.navidrome; group = "storage"; mode = "2770"; }; ${cfg.musicDir} = { directory = cfg.musicPath; owner = "root"; group = "storage"; mode = "2770"; }; } // lib.optionalAttrs hasLastfmSecrets { ${envFile} = { file = config.sops.templates."navidrome.env".path; readOnly = true; }; }; limits = { memory = lib.mkDefault "2G"; cpu = lib.mkDefault "200%"; tasksMax = lib.mkDefault 512; }; }; sops.secrets = lib.optionalAttrs hasLastfmSecrets { ${cfg.lastfmApiKeySecret}.sopsFile = hostSecrets; ${cfg.lastfmSecretSecret}.sopsFile = hostSecrets; }; sops.templates."navidrome.env" = lib.mkIf hasLastfmSecrets { owner = "root"; group = "storage"; mode = "0440"; content = '' ND_LASTFM_APIKEY=${config.sops.placeholder.${cfg.lastfmApiKeySecret}} ND_LASTFM_SECRET=${config.sops.placeholder.${cfg.lastfmSecretSecret}} ''; }; }; }