at 23.11-pre 4.3 kB view raw
1{ config 2, pkgs 3, lib 4, ...}: 5 6with lib; 7let 8 cfg = config.services.polaris; 9 settingsFormat = pkgs.formats.toml {}; 10in 11{ 12 options = { 13 services.polaris = { 14 enable = mkEnableOption (lib.mdDoc "Polaris Music Server"); 15 16 package = mkPackageOptionMD pkgs "polaris" { }; 17 18 user = mkOption { 19 type = types.str; 20 default = "polaris"; 21 description = lib.mdDoc "User account under which Polaris runs."; 22 }; 23 24 group = mkOption { 25 type = types.str; 26 default = "polaris"; 27 description = lib.mdDoc "Group under which Polaris is run."; 28 }; 29 30 extraGroups = mkOption { 31 type = types.listOf types.str; 32 default = []; 33 description = lib.mdDoc "Polaris' auxiliary groups."; 34 example = literalExpression ''["media" "music"]''; 35 }; 36 37 port = mkOption { 38 type = types.port; 39 default = 5050; 40 description = lib.mdDoc '' 41 The port which the Polaris REST api and web UI should listen to. 42 Note: polaris is hardcoded to listen to the hostname "0.0.0.0". 43 ''; 44 }; 45 46 settings = mkOption { 47 type = settingsFormat.type; 48 default = {}; 49 description = lib.mdDoc '' 50 Contents for the TOML Polaris config, applied each start. 51 Although poorly documented, an example may be found here: 52 [test-config.toml](https://github.com/agersant/polaris/blob/374d0ca56fc0a466d797a4b252e2078607476797/test-data/config.toml) 53 ''; 54 example = literalExpression '' 55 { 56 settings.reindex_every_n_seconds = 7*24*60*60; # weekly, default is 1800 57 settings.album_art_pattern = 58 "(cover|front|folder)\.(jpeg|jpg|png|bmp|gif)"; 59 mount_dirs = [ 60 { 61 name = "NAS"; 62 source = "/mnt/nas/music"; 63 } 64 { 65 name = "Local"; 66 source = "/home/my_user/Music"; 67 } 68 ]; 69 } 70 ''; 71 }; 72 73 openFirewall = mkOption { 74 type = types.bool; 75 default = false; 76 description = lib.mdDoc '' 77 Open the configured port in the firewall. 78 ''; 79 }; 80 }; 81 }; 82 83 config = mkIf cfg.enable { 84 systemd.services.polaris = { 85 description = "Polaris Music Server"; 86 after = [ "network.target" ]; 87 wantedBy = [ "multi-user.target" ]; 88 89 serviceConfig = rec { 90 User = cfg.user; 91 Group = cfg.group; 92 DynamicUser = true; 93 SupplementaryGroups = cfg.extraGroups; 94 StateDirectory = "polaris"; 95 CacheDirectory = "polaris"; 96 ExecStart = escapeShellArgs ([ 97 "${cfg.package}/bin/polaris" 98 "--foreground" 99 "--port" cfg.port 100 "--database" "/var/lib/${StateDirectory}/db.sqlite" 101 "--cache" "/var/cache/${CacheDirectory}" 102 ] ++ optionals (cfg.settings != {}) [ 103 "--config" (settingsFormat.generate "polaris-config.toml" cfg.settings) 104 ]); 105 Restart = "on-failure"; 106 107 # Security options: 108 109 #NoNewPrivileges = true; # implied by DynamicUser 110 #RemoveIPC = true; # implied by DynamicUser 111 112 AmbientCapabilities = ""; 113 CapabilityBoundingSet = ""; 114 115 DeviceAllow = ""; 116 117 LockPersonality = true; 118 119 #PrivateTmp = true; # implied by DynamicUser 120 PrivateDevices = true; 121 PrivateUsers = true; 122 123 ProtectClock = true; 124 ProtectControlGroups = true; 125 ProtectHostname = true; 126 ProtectKernelLogs = true; 127 ProtectKernelModules = true; 128 ProtectKernelTunables = true; 129 130 RestrictNamespaces = true; 131 RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ]; 132 RestrictRealtime = true; 133 #RestrictSUIDSGID = true; # implied by DynamicUser 134 135 SystemCallArchitectures = "native"; 136 SystemCallErrorNumber = "EPERM"; 137 SystemCallFilter = [ 138 "@system-service" 139 "~@cpu-emulation" "~@debug" "~@keyring" "~@memlock" "~@obsolete" "~@privileged" "~@setuid" 140 ]; 141 }; 142 }; 143 144 networking.firewall = mkIf cfg.openFirewall { 145 allowedTCPPorts = [ cfg.port ]; 146 }; 147 148 }; 149 150 meta.maintainers = with maintainers; [ pbsds ]; 151}