6 cfg = config.services.polaris;
7 settingsFormat = pkgs.formats.toml {};
12 enable = lib.mkEnableOption "Polaris Music Server";
14 package = lib.mkPackageOption pkgs "polaris" { };
19 description = "User account under which Polaris runs.";
22 group = lib.mkOption {
25 description = "Group under which Polaris is run.";
28 extraGroups = lib.mkOption {
29 type = lib.types.listOf lib.types.str;
31 description = "Polaris' auxiliary groups.";
32 example = lib.literalExpression ''["media" "music"]'';
36 type = lib.types.port;
39 The port which the Polaris REST api and web UI should listen to.
40 Note: polaris is hardcoded to listen to the hostname "0.0.0.0".
44 settings = lib.mkOption {
45 type = settingsFormat.type;
48 Contents for the TOML Polaris config, applied each start.
49 Although poorly documented, an example may be found here:
50 [test-config.toml](https://github.com/agersant/polaris/blob/374d0ca56fc0a466d797a4b252e2078607476797/test-data/config.toml)
52 example = lib.literalExpression ''
54 settings.reindex_every_n_seconds = 7*24*60*60; # weekly, default is 1800
55 settings.album_art_pattern =
56 "(cover|front|folder)\.(jpeg|jpg|png|bmp|gif)";
60 source = "/mnt/nas/music";
64 source = "/home/my_user/Music";
71 openFirewall = lib.mkOption {
72 type = lib.types.bool;
75 Open the configured port in the firewall.
81 config = lib.mkIf cfg.enable {
82 systemd.services.polaris = {
83 description = "Polaris Music Server";
84 after = [ "network.target" ];
85 wantedBy = [ "multi-user.target" ];
91 SupplementaryGroups = cfg.extraGroups;
92 StateDirectory = "polaris";
93 CacheDirectory = "polaris";
94 ExecStart = lib.escapeShellArgs ([
95 "${cfg.package}/bin/polaris"
98 "--database" "/var/lib/${StateDirectory}/db.sqlite"
99 "--cache" "/var/cache/${CacheDirectory}"
100 ] ++ lib.optionals (cfg.settings != {}) [
101 "--config" (settingsFormat.generate "polaris-config.toml" cfg.settings)
103 Restart = "on-failure";
107 #NoNewPrivileges = true; # implied by DynamicUser
108 #RemoveIPC = true; # implied by DynamicUser
110 AmbientCapabilities = "";
111 CapabilityBoundingSet = "";
115 LockPersonality = true;
117 #PrivateTmp = true; # implied by DynamicUser
118 PrivateDevices = true;
122 ProtectControlGroups = true;
123 ProtectHostname = true;
124 ProtectKernelLogs = true;
125 ProtectKernelModules = true;
126 ProtectKernelTunables = true;
128 RestrictNamespaces = true;
129 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
130 RestrictRealtime = true;
131 #RestrictSUIDSGID = true; # implied by DynamicUser
133 SystemCallArchitectures = "native";
134 SystemCallErrorNumber = "EPERM";
137 "~@cpu-emulation" "~@debug" "~@keyring" "~@memlock" "~@obsolete" "~@privileged" "~@setuid"
142 networking.firewall = lib.mkIf cfg.openFirewall {
143 allowedTCPPorts = [ cfg.port ];
148 meta.maintainers = with lib.maintainers; [ pbsds ];