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 openFirewall = mkOption {
32 type = types.bool;
33 default = false;
34 description = lib.mdDoc "Whether to open the TCP port in the firewall";
35 };
36 };
37 };
38
39 config = mkIf cfg.enable {
40 networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.settings.Port];
41
42 systemd.services.navidrome = {
43 description = "Navidrome Media Server";
44 after = [ "network.target" ];
45 wantedBy = [ "multi-user.target" ];
46 serviceConfig = {
47 ExecStart = ''
48 ${cfg.package}/bin/navidrome --configfile ${settingsFormat.generate "navidrome.json" cfg.settings}
49 '';
50 DynamicUser = true;
51 StateDirectory = "navidrome";
52 WorkingDirectory = "/var/lib/navidrome";
53 RuntimeDirectory = "navidrome";
54 RootDirectory = "/run/navidrome";
55 ReadWritePaths = "";
56 BindReadOnlyPaths = [
57 # navidrome uses online services to download additional album metadata / covers
58 "${config.environment.etc."ssl/certs/ca-certificates.crt".source}:/etc/ssl/certs/ca-certificates.crt"
59 builtins.storeDir
60 "/etc"
61 ] ++ lib.optional (cfg.settings ? MusicFolder) cfg.settings.MusicFolder;
62 CapabilityBoundingSet = "";
63 RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
64 RestrictNamespaces = true;
65 PrivateDevices = true;
66 PrivateUsers = true;
67 ProtectClock = true;
68 ProtectControlGroups = true;
69 ProtectHome = true;
70 ProtectKernelLogs = true;
71 ProtectKernelModules = true;
72 ProtectKernelTunables = true;
73 SystemCallArchitectures = "native";
74 SystemCallFilter = [ "@system-service" "~@privileged" ];
75 RestrictRealtime = true;
76 LockPersonality = true;
77 MemoryDenyWriteExecute = true;
78 UMask = "0066";
79 ProtectHostname = true;
80 };
81 };
82 };
83}