feat(nixos): add navidrome guest module

This commit is contained in:
2026-09-12 18:48:05 -04:00
parent cd220b8030
commit c21b7a632c
3 changed files with 202 additions and 1 deletions

View File

@@ -0,0 +1,109 @@
{
config,
lib,
...
}:
let
cfg = config.guests.navidrome;
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.";
};
environmentFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = "Guest path to a file containing secret Navidrome environment variables.";
};
};
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
;
};
mounts = {
${cfg.dataDir} = {
directory = cfg.dataPath;
owner = config.registry."stable-uid".${config.networking.hostName}.navidrome;
group = "storage";
mode = "0770";
};
${cfg.musicDir} = {
directory = cfg.musicPath;
owner = "root";
group = "storage";
mode = "2770";
};
};
limits = {
memory = lib.mkDefault "2G";
cpu = lib.mkDefault "200%";
tasksMax = lib.mkDefault 512;
};
};
};
}

View File

@@ -0,0 +1,92 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.modules.services.navidrome;
in
{
options.modules.services.navidrome = {
enable = lib.mkEnableOption "Navidrome";
package = lib.mkPackageOption pkgs "navidrome" { };
port = lib.mkOption {
type = lib.types.port;
default = 4533;
description = "Port Navidrome listens on.";
};
dataDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/navidrome";
description = "Directory where Navidrome stores state.";
};
musicDir = lib.mkOption {
type = lib.types.str;
default = "/music";
description = "Directory where Navidrome reads the music library.";
};
user = lib.mkOption {
type = lib.types.str;
default = "navidrome";
description = "User account that runs Navidrome.";
};
group = lib.mkOption {
type = lib.types.str;
default = "storage";
description = "Group account that owns Navidrome state and media access.";
};
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.";
};
environmentFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = "File containing secret Navidrome environment variables.";
};
};
config = lib.mkMerge [
{
registry."stable-uid".${config.networking.hostName}.navidrome = 20004;
}
(lib.mkIf cfg.enable {
users.users.${cfg.user} = {
isSystemUser = true;
uid = config.registry."stable-uid".${config.networking.hostName}.navidrome;
group = cfg.group;
home = cfg.dataDir;
};
services.navidrome = {
enable = true;
inherit (cfg) package user group environmentFile;
openFirewall = true;
settings = cfg.settings // {
Address = "0.0.0.0";
Port = cfg.port;
DataFolder = cfg.dataDir;
MusicFolder = cfg.musicDir;
EnableSharing = cfg.enableSharing;
};
};
})
];
}

View File

@@ -17,7 +17,7 @@ let
in
{
# Next stable UID: 20003
# Next stable UID: 20005
replicate = true;
type = lib.types.ints.positive;