at master 7.2 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 9 name = "snapserver"; 10 11 inherit (lib) 12 literalExpression 13 mkEnableOption 14 mkOption 15 mkPackageOption 16 mkRemovedOptionModule 17 mkRenamedOptionModule 18 types 19 ; 20 21 cfg = config.services.snapserver; 22 23 format = pkgs.formats.ini { 24 listsAsDuplicateKeys = true; 25 }; 26 27 configFile = format.generate "snapserver.conf" cfg.settings; 28 29in 30{ 31 imports = [ 32 (mkRenamedOptionModule 33 [ "services" "snapserver" "controlPort" ] 34 [ "services" "snapserver" "tcp" "port" ] 35 ) 36 37 (mkRenamedOptionModule 38 [ "services" "snapserver" "listenAddress" ] 39 [ "services" "snapserver" "settings" "stream" "bind_to_address" ] 40 ) 41 (mkRenamedOptionModule 42 [ "services" "snapserver" "port" ] 43 [ "services" "snapserver" "settings" "stream" "port" ] 44 ) 45 (mkRenamedOptionModule 46 [ "services" "snapserver" "sampleFormat" ] 47 [ "services" "snapserver" "settings" "stream" "sampleformat" ] 48 ) 49 (mkRenamedOptionModule 50 [ "services" "snapserver" "codec" ] 51 [ "services" "snapserver" "settings" "stream" "codec" ] 52 ) 53 (mkRenamedOptionModule 54 [ "services" "snapserver" "streamBuffer" ] 55 [ "services" "snapserver" "settings" "stream" "chunk_ms" ] 56 ) 57 (mkRenamedOptionModule 58 [ "services" "snapserver" "buffer" ] 59 [ "services" "snapserver" "settings" "stream" "buffer" ] 60 ) 61 (mkRenamedOptionModule 62 [ "services" "snapserver" "send" ] 63 [ "services" "snapserver" "settings" "stream" "chunk_ms" ] 64 ) 65 66 (mkRenamedOptionModule 67 [ "services" "snapserver" "tcp" "enable" ] 68 [ "services" "snapserver" "settings" "tcp" "enabled" ] 69 ) 70 (mkRenamedOptionModule 71 [ "services" "snapserver" "tcp" "listenAddress" ] 72 [ "services" "snapserver" "settings" "tcp" "bind_to_address" ] 73 ) 74 (mkRenamedOptionModule 75 [ "services" "snapserver" "tcp" "port" ] 76 [ "services" "snapserver" "settings" "tcp" "port" ] 77 ) 78 79 (mkRenamedOptionModule 80 [ "services" "snapserver" "http" "enable" ] 81 [ "services" "snapserver" "settings" "http" "enabled" ] 82 ) 83 (mkRenamedOptionModule 84 [ "services" "snapserver" "http" "listenAddress" ] 85 [ "services" "snapserver" "settings" "http" "bind_to_address" ] 86 ) 87 (mkRenamedOptionModule 88 [ "services" "snapserver" "http" "port" ] 89 [ "services" "snapserver" "settings" "http" "port" ] 90 ) 91 (mkRenamedOptionModule 92 [ "services" "snapserver" "http" "docRoot" ] 93 [ "services" "snapserver" "settings" "http" "doc_root" ] 94 ) 95 96 (mkRemovedOptionModule [ 97 "services" 98 "snapserver" 99 "streams" 100 ] "Configure `services.snapserver.settings.stream.source` instead") 101 ]; 102 103 ###### interface 104 105 options = { 106 107 services.snapserver = { 108 109 enable = mkEnableOption "snapserver"; 110 111 package = mkPackageOption pkgs "snapcast" { }; 112 113 settings = mkOption { 114 default = { }; 115 description = '' 116 Snapserver configuration. 117 118 Refer to the [example configuration](https://github.com/badaix/snapcast/blob/develop/server/etc/snapserver.conf) for possible options. 119 ''; 120 type = types.submodule { 121 freeformType = format.type; 122 options = { 123 stream = { 124 bind_to_address = mkOption { 125 default = "::"; 126 description = '' 127 Address to listen on for snapclient connections. 128 ''; 129 }; 130 131 port = mkOption { 132 type = types.port; 133 default = 1704; 134 description = '' 135 Port to listen on for snapclient connections. 136 ''; 137 }; 138 139 source = mkOption { 140 type = with types; either str (listOf str); 141 example = "pipe:///tmp/snapfifo?name=default"; 142 description = '' 143 One or multiple URIs to PCM inpuit streams. 144 ''; 145 }; 146 }; 147 148 tcp = { 149 enabled = mkEnableOption "the TCP JSON-RPC"; 150 151 bind_to_address = mkOption { 152 default = "::"; 153 description = '' 154 Address to listen on for snapclient connections. 155 ''; 156 }; 157 158 port = mkOption { 159 type = types.port; 160 default = 1705; 161 description = '' 162 Port to listen on for snapclient connections. 163 ''; 164 }; 165 }; 166 167 http = { 168 enabled = mkEnableOption "the HTTP JSON-RPC"; 169 170 bind_to_address = mkOption { 171 default = "::"; 172 description = '' 173 Address to listen on for snapclient connections. 174 ''; 175 }; 176 177 port = mkOption { 178 type = types.port; 179 default = 1780; 180 description = '' 181 Port to listen on for snapclient connections. 182 ''; 183 }; 184 185 doc_root = lib.mkOption { 186 type = with lib.types; nullOr path; 187 default = pkgs.snapweb; 188 defaultText = literalExpression "pkgs.snapweb"; 189 description = '' 190 Path to serve from the HTTP servers root. 191 ''; 192 }; 193 }; 194 }; 195 }; 196 }; 197 198 openFirewall = lib.mkOption { 199 type = lib.types.bool; 200 default = false; 201 description = '' 202 Whether to automatically open the specified ports in the firewall. 203 ''; 204 }; 205 }; 206 }; 207 208 ###### implementation 209 210 config = lib.mkIf cfg.enable { 211 environment.etc."snapserver.conf".source = configFile; 212 213 systemd.services.snapserver = { 214 after = [ 215 "network.target" 216 "nss-lookup.target" 217 ]; 218 description = "Snapserver"; 219 wantedBy = [ "multi-user.target" ]; 220 before = [ 221 "mpd.service" 222 "mopidy.service" 223 ]; 224 restartTriggers = [ configFile ]; 225 serviceConfig = { 226 DynamicUser = true; 227 ExecStart = toString [ 228 (lib.getExe' cfg.package "snapserver") 229 "--daemon" 230 ]; 231 Type = "forking"; 232 LimitRTPRIO = 50; 233 LimitRTTIME = "infinity"; 234 NoNewPrivileges = true; 235 PIDFile = "/run/${name}/pid"; 236 ProtectKernelTunables = true; 237 ProtectControlGroups = true; 238 ProtectKernelModules = true; 239 Restart = "on-failure"; 240 RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX AF_NETLINK"; 241 RestrictNamespaces = true; 242 RuntimeDirectory = name; 243 StateDirectory = name; 244 }; 245 }; 246 247 networking.firewall.allowedTCPPorts = 248 lib.optionals cfg.openFirewall [ cfg.settings.stream.port ] 249 ++ lib.optional (cfg.openFirewall && cfg.settings.tcp.enabled) cfg.settings.tcp.port 250 ++ lib.optional (cfg.openFirewall && cfg.settings.http.enabled) cfg.settings.http.port; 251 }; 252 253 meta = { 254 maintainers = with lib.maintainers; [ tobim ]; 255 }; 256 257}