1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.navidrome;
7 settingsFormat = pkgs.formats.json {};
8in {
9 options = {
10 services.navidrome = {
11
12 enable = mkEnableOption (lib.mdDoc "Navidrome music server");
13
14 package = mkPackageOptionMD pkgs "navidrome" { };
15
16 settings = mkOption rec {
17 type = settingsFormat.type;
18 apply = recursiveUpdate default;
19 default = {
20 Address = "127.0.0.1";
21 Port = 4533;
22 };
23 example = {
24 MusicFolder = "/mnt/music";
25 };
26 description = lib.mdDoc ''
27 Configuration for Navidrome, see <https://www.navidrome.org/docs/usage/configuration-options/> for supported values.
28 '';
29 };
30
31 };
32 };
33
34 config = mkIf cfg.enable {
35 systemd.services.navidrome = {
36 description = "Navidrome Media Server";
37 after = [ "network.target" ];
38 wantedBy = [ "multi-user.target" ];
39 serviceConfig = {
40 ExecStart = ''
41 ${cfg.package}/bin/navidrome --configfile ${settingsFormat.generate "navidrome.json" cfg.settings}
42 '';
43 DynamicUser = true;
44 StateDirectory = "navidrome";
45 WorkingDirectory = "/var/lib/navidrome";
46 RuntimeDirectory = "navidrome";
47 RootDirectory = "/run/navidrome";
48 ReadWritePaths = "";
49 BindReadOnlyPaths = [
50 # navidrome uses online services to download additional album metadata / covers
51 "${config.environment.etc."ssl/certs/ca-certificates.crt".source}:/etc/ssl/certs/ca-certificates.crt"
52 builtins.storeDir
53 "/etc"
54 ] ++ lib.optional (cfg.settings ? MusicFolder) cfg.settings.MusicFolder;
55 CapabilityBoundingSet = "";
56 RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
57 RestrictNamespaces = true;
58 PrivateDevices = true;
59 PrivateUsers = true;
60 ProtectClock = true;
61 ProtectControlGroups = true;
62 ProtectHome = true;
63 ProtectKernelLogs = true;
64 ProtectKernelModules = true;
65 ProtectKernelTunables = true;
66 SystemCallArchitectures = "native";
67 SystemCallFilter = [ "@system-service" "~@privileged" ];
68 RestrictRealtime = true;
69 LockPersonality = true;
70 MemoryDenyWriteExecute = true;
71 UMask = "0066";
72 ProtectHostname = true;
73 };
74 };
75 };
76}