vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / murmur.nix
blob85676d29f2b1c1ccd0c3099d12e793d571edb0c8
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.murmur;
7   forking = cfg.logFile != null;
8   configFile = pkgs.writeText "murmurd.ini" ''
9     database=/var/lib/murmur/murmur.sqlite
10     dbDriver=QSQLITE
12     autobanAttempts=${toString cfg.autobanAttempts}
13     autobanTimeframe=${toString cfg.autobanTimeframe}
14     autobanTime=${toString cfg.autobanTime}
16     logfile=${optionalString (cfg.logFile != null) cfg.logFile}
17     ${optionalString forking "pidfile=/run/murmur/murmurd.pid"}
19     welcometext="${cfg.welcometext}"
20     port=${toString cfg.port}
22     ${optionalString (cfg.hostName != "") "host=${cfg.hostName}"}
23     ${optionalString (cfg.password != "") "serverpassword=${cfg.password}"}
25     bandwidth=${toString cfg.bandwidth}
26     users=${toString cfg.users}
28     textmessagelength=${toString cfg.textMsgLength}
29     imagemessagelength=${toString cfg.imgMsgLength}
30     allowhtml=${boolToString cfg.allowHtml}
31     logdays=${toString cfg.logDays}
32     bonjour=${boolToString cfg.bonjour}
33     sendversion=${boolToString cfg.sendVersion}
35     ${optionalString (cfg.registerName != "") "registerName=${cfg.registerName}"}
36     ${optionalString (cfg.registerPassword != "") "registerPassword=${cfg.registerPassword}"}
37     ${optionalString (cfg.registerUrl != "") "registerUrl=${cfg.registerUrl}"}
38     ${optionalString (cfg.registerHostname != "") "registerHostname=${cfg.registerHostname}"}
40     certrequired=${boolToString cfg.clientCertRequired}
41     ${optionalString (cfg.sslCert != "") "sslCert=${cfg.sslCert}"}
42     ${optionalString (cfg.sslKey != "") "sslKey=${cfg.sslKey}"}
43     ${optionalString (cfg.sslCa != "") "sslCA=${cfg.sslCa}"}
45     ${optionalString (cfg.dbus != null) "dbus=${cfg.dbus}"}
47     ${cfg.extraConfig}
48   '';
51   imports = [
52     (mkRenamedOptionModule [ "services" "murmur" "welcome" ] [ "services" "murmur" "welcometext" ])
53     (mkRemovedOptionModule [ "services" "murmur" "pidfile" ] "Hardcoded to /run/murmur/murmurd.pid now")
54   ];
56   options = {
57     services.murmur = {
58       enable = mkOption {
59         type = types.bool;
60         default = false;
61         description = "If enabled, start the Murmur Mumble server.";
62       };
64       openFirewall = mkOption {
65         type = types.bool;
66         default = false;
67         description = ''
68           Open ports in the firewall for the Murmur Mumble server.
69         '';
70       };
72       autobanAttempts = mkOption {
73         type = types.int;
74         default = 10;
75         description = ''
76           Number of attempts a client is allowed to make in
77           `autobanTimeframe` seconds, before being
78           banned for `autobanTime`.
79         '';
80       };
82       autobanTimeframe = mkOption {
83         type = types.int;
84         default = 120;
85         description = ''
86           Timeframe in which a client can connect without being banned
87           for repeated attempts (in seconds).
88         '';
89       };
91       autobanTime = mkOption {
92         type = types.int;
93         default = 300;
94         description = "The amount of time an IP ban lasts (in seconds).";
95       };
97       logFile = mkOption {
98         type = types.nullOr types.path;
99         default = null;
100         example = "/var/log/murmur/murmurd.log";
101         description = "Path to the log file for Murmur daemon. Empty means log to journald.";
102       };
104       welcometext = mkOption {
105         type = types.str;
106         default = "";
107         description = "Welcome message for connected clients.";
108       };
110       port = mkOption {
111         type = types.port;
112         default = 64738;
113         description = "Ports to bind to (UDP and TCP).";
114       };
116       hostName = mkOption {
117         type = types.str;
118         default = "";
119         description = "Host to bind to. Defaults binding on all addresses.";
120       };
122       package = mkPackageOption pkgs "murmur" { };
124       password = mkOption {
125         type = types.str;
126         default = "";
127         description = "Required password to join server, if specified.";
128       };
130       bandwidth = mkOption {
131         type = types.int;
132         default = 72000;
133         description = ''
134           Maximum bandwidth (in bits per second) that clients may send
135           speech at.
136         '';
137       };
139       users = mkOption {
140         type = types.int;
141         default = 100;
142         description = "Maximum number of concurrent clients allowed.";
143       };
145       textMsgLength = mkOption {
146         type = types.int;
147         default = 5000;
148         description = "Max length of text messages. Set 0 for no limit.";
149       };
151       imgMsgLength = mkOption {
152         type = types.int;
153         default = 131072;
154         description = "Max length of image messages. Set 0 for no limit.";
155       };
157       allowHtml = mkOption {
158         type = types.bool;
159         default = true;
160         description = ''
161           Allow HTML in client messages, comments, and channel
162           descriptions.
163         '';
164       };
166       logDays = mkOption {
167         type = types.int;
168         default = 31;
169         description = ''
170           How long to store RPC logs for in the database. Set 0 to
171           keep logs forever, or -1 to disable DB logging.
172         '';
173       };
175       bonjour = mkOption {
176         type = types.bool;
177         default = false;
178         description = ''
179           Enable Bonjour auto-discovery, which allows clients over
180           your LAN to automatically discover Murmur servers.
181         '';
182       };
184       sendVersion = mkOption {
185         type = types.bool;
186         default = true;
187         description = "Send Murmur version in UDP response.";
188       };
190       registerName = mkOption {
191         type = types.str;
192         default = "";
193         description = ''
194           Public server registration name, and also the name of the
195           Root channel. Even if you don't publicly register your
196           server, you probably still want to set this.
197         '';
198       };
200       registerPassword = mkOption {
201         type = types.str;
202         default = "";
203         description = ''
204           Public server registry password, used authenticate your
205           server to the registry to prevent impersonation; required for
206           subsequent registry updates.
207         '';
208       };
210       registerUrl = mkOption {
211         type = types.str;
212         default = "";
213         description = "URL website for your server.";
214       };
216       registerHostname = mkOption {
217         type = types.str;
218         default = "";
219         description = ''
220           DNS hostname where your server can be reached. This is only
221           needed if you want your server to be accessed by its
222           hostname and not IP - but the name *must* resolve on the
223           internet properly.
224         '';
225       };
227       clientCertRequired = mkOption {
228         type = types.bool;
229         default = false;
230         description = "Require clients to authenticate via certificates.";
231       };
233       sslCert = mkOption {
234         type = types.str;
235         default = "";
236         description = "Path to your SSL certificate.";
237       };
239       sslKey = mkOption {
240         type = types.str;
241         default = "";
242         description = "Path to your SSL key.";
243       };
245       sslCa = mkOption {
246         type = types.str;
247         default = "";
248         description = "Path to your SSL CA certificate.";
249       };
251       extraConfig = mkOption {
252         type = types.lines;
253         default = "";
254         description = "Extra configuration to put into murmur.ini.";
255       };
257       environmentFile = mkOption {
258         type = types.nullOr types.path;
259         default = null;
260         example = "/var/lib/murmur/murmurd.env";
261         description = ''
262           Environment file as defined in {manpage}`systemd.exec(5)`.
264           Secrets may be passed to the service without adding them to the world-readable
265           Nix store, by specifying placeholder variables as the option value in Nix and
266           setting these variables accordingly in the environment file.
268           ```
269             # snippet of murmur-related config
270             services.murmur.password = "$MURMURD_PASSWORD";
271           ```
273           ```
274             # content of the environment file
275             MURMURD_PASSWORD=verysecretpassword
276           ```
278           Note that this file needs to be available on the host on which
279           `murmur` is running.
280         '';
281       };
283       dbus = mkOption {
284         type = types.enum [ null "session" "system" ];
285         default = null;
286         description = "Enable D-Bus remote control. Set to the bus you want Murmur to connect to.";
287       };
288     };
289   };
291   config = mkIf cfg.enable {
292     users.users.murmur = {
293       description     = "Murmur Service user";
294       home            = "/var/lib/murmur";
295       createHome      = true;
296       uid             = config.ids.uids.murmur;
297       group           = "murmur";
298     };
299     users.groups.murmur = {
300       gid             = config.ids.gids.murmur;
301     };
303     networking.firewall = mkIf cfg.openFirewall {
304       allowedTCPPorts = [ cfg.port ];
305       allowedUDPPorts = [ cfg.port ];
306     };
308     systemd.services.murmur = {
309       description = "Murmur Chat Service";
310       wantedBy    = [ "multi-user.target" ];
311       after       = [ "network.target" ];
312       preStart    = ''
313         ${pkgs.envsubst}/bin/envsubst \
314           -o /run/murmur/murmurd.ini \
315           -i ${configFile}
316       '';
318       serviceConfig = {
319         # murmurd doesn't fork when logging to the console.
320         Type = if forking then "forking" else "simple";
321         PIDFile = mkIf forking "/run/murmur/murmurd.pid";
322         EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
323         ExecStart = "${cfg.package}/bin/mumble-server -ini /run/murmur/murmurd.ini";
324         Restart = "always";
325         RuntimeDirectory = "murmur";
326         RuntimeDirectoryMode = "0700";
327         User = "murmur";
328         Group = "murmur";
330         # service hardening
331         AmbientCapabilities = "CAP_NET_BIND_SERVICE";
332         CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
333         LockPersonality = true;
334         MemoryDenyWriteExecute = true;
335         NoNewPrivileges = true;
336         PrivateDevices = true;
337         PrivateTmp = true;
338         ProtectClock = true;
339         ProtectControlGroups = true;
340         ProtectHome = true;
341         ProtectHostname = true;
342         ProtectKernelLogs = true;
343         ProtectKernelModules = true;
344         ProtectKernelTunables = true;
345         ProtectSystem = "full";
346         RestrictAddressFamilies = "~AF_PACKET AF_NETLINK";
347         RestrictNamespaces = true;
348         RestrictSUIDSGID = true;
349         RestrictRealtime = true;
350         SystemCallArchitectures = "native";
351         SystemCallFilter = "@system-service";
352       };
353     };
355     # currently not included in upstream package, addition requested at
356     # https://github.com/mumble-voip/mumble/issues/6078
357     services.dbus.packages = mkIf (cfg.dbus == "system") [(pkgs.writeTextFile {
358       name = "murmur-dbus-policy";
359       text = ''
360         <!DOCTYPE busconfig PUBLIC
361           "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
362           "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
363         <busconfig>
364           <policy user="murmur">
365             <allow own="net.sourceforge.mumble.murmur"/>
366           </policy>
368           <policy context="default">
369             <allow send_destination="net.sourceforge.mumble.murmur"/>
370             <allow receive_sender="net.sourceforge.mumble.murmur"/>
371           </policy>
372         </busconfig>
373       '';
374       destination = "/share/dbus-1/system.d/murmur.conf";
375     })];
377     security.apparmor.policies."bin.mumble-server".profile = ''
378       include <tunables/global>
380       ${cfg.package}/bin/{mumble-server,.mumble-server-wrapped} {
381         include <abstractions/base>
382         include <abstractions/nameservice>
383         include <abstractions/ssl_certs>
384         include "${pkgs.apparmorRulesFromClosure { name = "mumble-server"; } cfg.package}"
385         pix ${cfg.package}/bin/.mumble-server-wrapped,
387         r ${config.environment.etc."os-release".source},
388         r ${config.environment.etc."lsb-release".source},
389         owner rwk /var/lib/murmur/murmur.sqlite,
390         owner rw /var/lib/murmur/murmur.sqlite-journal,
391         owner r /var/lib/murmur/,
392         r /run/murmur/murmurd.pid,
393         r /run/murmur/murmurd.ini,
394         r ${configFile},
395       '' + optionalString (cfg.logFile != null) ''
396         rw ${cfg.logFile},
397       '' + optionalString (cfg.sslCert != "") ''
398         r ${cfg.sslCert},
399       '' + optionalString (cfg.sslKey != "") ''
400         r ${cfg.sslKey},
401       '' + optionalString (cfg.sslCa != "") ''
402         r ${cfg.sslCa},
403       '' + optionalString (cfg.dbus != null) ''
404         dbus bus=${cfg.dbus}
405       '' + ''
406       }
407     '';
408   };
410   meta.maintainers = with lib.maintainers; [ felixsinger ];