python3Packages.orjson: Disable failing tests on 32 bit
[NixPkgs.git] / nixos / modules / services / networking / coturn.nix
blob2f34a72377ce2a03a4cc8b25bba34321d576dded
1 { config, lib, pkgs, ... }:
2 with lib;
3 let
4   cfg = config.services.coturn;
5   pidfile = "/run/turnserver/turnserver.pid";
6   configFile = pkgs.writeText "turnserver.conf" ''
7 listening-port=${toString cfg.listening-port}
8 tls-listening-port=${toString cfg.tls-listening-port}
9 alt-listening-port=${toString cfg.alt-listening-port}
10 alt-tls-listening-port=${toString cfg.alt-tls-listening-port}
11 ${concatStringsSep "\n" (map (x: "listening-ip=${x}") cfg.listening-ips)}
12 ${concatStringsSep "\n" (map (x: "relay-ip=${x}") cfg.relay-ips)}
13 min-port=${toString cfg.min-port}
14 max-port=${toString cfg.max-port}
15 ${lib.optionalString cfg.lt-cred-mech "lt-cred-mech"}
16 ${lib.optionalString cfg.no-auth "no-auth"}
17 ${lib.optionalString cfg.use-auth-secret "use-auth-secret"}
18 ${lib.optionalString (cfg.static-auth-secret != null) ("static-auth-secret=${cfg.static-auth-secret}")}
19 ${lib.optionalString (cfg.static-auth-secret-file != null) ("static-auth-secret=#static-auth-secret#")}
20 realm=${cfg.realm}
21 ${lib.optionalString cfg.no-udp "no-udp"}
22 ${lib.optionalString cfg.no-tcp "no-tcp"}
23 ${lib.optionalString cfg.no-tls "no-tls"}
24 ${lib.optionalString cfg.no-dtls "no-dtls"}
25 ${lib.optionalString cfg.no-udp-relay "no-udp-relay"}
26 ${lib.optionalString cfg.no-tcp-relay "no-tcp-relay"}
27 ${lib.optionalString (cfg.cert != null) "cert=${cfg.cert}"}
28 ${lib.optionalString (cfg.pkey != null) "pkey=${cfg.pkey}"}
29 ${lib.optionalString (cfg.dh-file != null) ("dh-file=${cfg.dh-file}")}
30 no-stdout-log
31 syslog
32 pidfile=${pidfile}
33 ${lib.optionalString cfg.secure-stun "secure-stun"}
34 ${lib.optionalString cfg.no-cli "no-cli"}
35 cli-ip=${cfg.cli-ip}
36 cli-port=${toString cfg.cli-port}
37 ${lib.optionalString (cfg.cli-password != null) ("cli-password=${cfg.cli-password}")}
38 ${cfg.extraConfig}
39 '';
40 in {
41   options = {
42     services.coturn = {
43       enable = mkEnableOption (lib.mdDoc "coturn TURN server");
44       listening-port = mkOption {
45         type = types.int;
46         default = 3478;
47         description = lib.mdDoc ''
48           TURN listener port for UDP and TCP.
49           Note: actually, TLS and DTLS sessions can connect to the
50           "plain" TCP and UDP port(s), too - if allowed by configuration.
51         '';
52       };
53       tls-listening-port = mkOption {
54         type = types.int;
55         default = 5349;
56         description = lib.mdDoc ''
57           TURN listener port for TLS.
58           Note: actually, "plain" TCP and UDP sessions can connect to the TLS and
59           DTLS port(s), too - if allowed by configuration. The TURN server
60           "automatically" recognizes the type of traffic. Actually, two listening
61           endpoints (the "plain" one and the "tls" one) are equivalent in terms of
62           functionality; but we keep both endpoints to satisfy the RFC 5766 specs.
63           For secure TCP connections, we currently support SSL version 3 and
64           TLS version 1.0, 1.1 and 1.2.
65           For secure UDP connections, we support DTLS version 1.
66         '';
67       };
68       alt-listening-port = mkOption {
69         type = types.int;
70         default = cfg.listening-port + 1;
71         defaultText = literalExpression "listening-port + 1";
72         description = lib.mdDoc ''
73           Alternative listening port for UDP and TCP listeners;
74           default (or zero) value means "listening port plus one".
75           This is needed for RFC 5780 support
76           (STUN extension specs, NAT behavior discovery). The TURN Server
77           supports RFC 5780 only if it is started with more than one
78           listening IP address of the same family (IPv4 or IPv6).
79           RFC 5780 is supported only by UDP protocol, other protocols
80           are listening to that endpoint only for "symmetry".
81         '';
82       };
83       alt-tls-listening-port = mkOption {
84         type = types.int;
85         default = cfg.tls-listening-port + 1;
86         defaultText = literalExpression "tls-listening-port + 1";
87         description = lib.mdDoc ''
88           Alternative listening port for TLS and DTLS protocols.
89         '';
90       };
91       listening-ips = mkOption {
92         type = types.listOf types.str;
93         default = [];
94         example = [ "203.0.113.42" "2001:DB8::42" ];
95         description = lib.mdDoc ''
96           Listener IP addresses of relay server.
97           If no IP(s) specified in the config file or in the command line options,
98           then all IPv4 and IPv6 system IPs will be used for listening.
99         '';
100       };
101       relay-ips = mkOption {
102         type = types.listOf types.str;
103         default = [];
104         example = [ "203.0.113.42" "2001:DB8::42" ];
105         description = lib.mdDoc ''
106           Relay address (the local IP address that will be used to relay the
107           packets to the peer).
108           Multiple relay addresses may be used.
109           The same IP(s) can be used as both listening IP(s) and relay IP(s).
111           If no relay IP(s) specified, then the turnserver will apply the default
112           policy: it will decide itself which relay addresses to be used, and it
113           will always be using the client socket IP address as the relay IP address
114           of the TURN session (if the requested relay address family is the same
115           as the family of the client socket).
116         '';
117       };
118       min-port = mkOption {
119         type = types.int;
120         default = 49152;
121         description = lib.mdDoc ''
122           Lower bound of UDP relay endpoints
123         '';
124       };
125       max-port = mkOption {
126         type = types.int;
127         default = 65535;
128         description = lib.mdDoc ''
129           Upper bound of UDP relay endpoints
130         '';
131       };
132       lt-cred-mech = mkOption {
133         type = types.bool;
134         default = false;
135         description = lib.mdDoc ''
136           Use long-term credential mechanism.
137         '';
138       };
139       no-auth = mkOption {
140         type = types.bool;
141         default = false;
142         description = lib.mdDoc ''
143           This option is opposite to lt-cred-mech.
144           (TURN Server with no-auth option allows anonymous access).
145           If neither option is defined, and no users are defined,
146           then no-auth is default. If at least one user is defined,
147           in this file or in command line or in usersdb file, then
148           lt-cred-mech is default.
149         '';
150       };
151       use-auth-secret = mkOption {
152         type = types.bool;
153         default = false;
154         description = lib.mdDoc ''
155           TURN REST API flag.
156           Flag that sets a special authorization option that is based upon authentication secret.
157           This feature can be used with the long-term authentication mechanism, only.
158           This feature purpose is to support "TURN Server REST API", see
159           "TURN REST API" link in the project's page
160           https://github.com/coturn/coturn/
162           This option is used with timestamp:
164           usercombo -> "timestamp:userid"
165           turn user -> usercombo
166           turn password -> base64(hmac(secret key, usercombo))
168           This allows TURN credentials to be accounted for a specific user id.
169           If you don't have a suitable id, the timestamp alone can be used.
170           This option is just turning on secret-based authentication.
171           The actual value of the secret is defined either by option static-auth-secret,
172           or can be found in the turn_secret table in the database.
173         '';
174       };
175       static-auth-secret = mkOption {
176         type = types.nullOr types.str;
177         default = null;
178         description = lib.mdDoc ''
179           'Static' authentication secret value (a string) for TURN REST API only.
180           If not set, then the turn server
181           will try to use the 'dynamic' value in turn_secret table
182           in user database (if present). The database-stored  value can be changed on-the-fly
183           by a separate program, so this is why that other mode is 'dynamic'.
184         '';
185       };
186       static-auth-secret-file = mkOption {
187         type = types.nullOr types.str;
188         default = null;
189         description = lib.mdDoc ''
190           Path to the file containing the static authentication secret.
191         '';
192       };
193       realm = mkOption {
194         type = types.str;
195         default = config.networking.hostName;
196         defaultText = literalExpression "config.networking.hostName";
197         example = "example.com";
198         description = lib.mdDoc ''
199           The default realm to be used for the users when no explicit
200           origin/realm relationship was found in the database, or if the TURN
201           server is not using any database (just the commands-line settings
202           and the userdb file). Must be used with long-term credentials
203           mechanism or with TURN REST API.
204         '';
205       };
206       cert = mkOption {
207         type = types.nullOr types.str;
208         default = null;
209         example = "/var/lib/acme/example.com/fullchain.pem";
210         description = lib.mdDoc ''
211           Certificate file in PEM format.
212         '';
213       };
214       pkey = mkOption {
215         type = types.nullOr types.str;
216         default = null;
217         example = "/var/lib/acme/example.com/key.pem";
218         description = lib.mdDoc ''
219           Private key file in PEM format.
220         '';
221       };
222       dh-file = mkOption {
223         type = types.nullOr types.str;
224         default = null;
225         description = lib.mdDoc ''
226           Use custom DH TLS key, stored in PEM format in the file.
227         '';
228       };
229       secure-stun = mkOption {
230         type = types.bool;
231         default = false;
232         description = lib.mdDoc ''
233           Require authentication of the STUN Binding request.
234           By default, the clients are allowed anonymous access to the STUN Binding functionality.
235         '';
236       };
237       no-cli = mkOption {
238         type = types.bool;
239         default = false;
240         description = lib.mdDoc ''
241           Turn OFF the CLI support.
242         '';
243       };
244       cli-ip = mkOption {
245         type = types.str;
246         default = "127.0.0.1";
247         description = lib.mdDoc ''
248           Local system IP address to be used for CLI server endpoint.
249         '';
250       };
251       cli-port = mkOption {
252         type = types.int;
253         default = 5766;
254         description = lib.mdDoc ''
255           CLI server port.
256         '';
257       };
258       cli-password = mkOption {
259         type = types.nullOr types.str;
260         default = null;
261         description = lib.mdDoc ''
262           CLI access password.
263           For the security reasons, it is recommended to use the encrypted
264           for of the password (see the -P command in the turnadmin utility).
265         '';
266       };
267       no-udp = mkOption {
268         type = types.bool;
269         default = false;
270         description = lib.mdDoc "Disable UDP client listener";
271       };
272       no-tcp = mkOption {
273         type = types.bool;
274         default = false;
275         description = lib.mdDoc "Disable TCP client listener";
276       };
277       no-tls = mkOption {
278         type = types.bool;
279         default = false;
280         description = lib.mdDoc "Disable TLS client listener";
281       };
282       no-dtls = mkOption {
283         type = types.bool;
284         default = false;
285         description = lib.mdDoc "Disable DTLS client listener";
286       };
287       no-udp-relay = mkOption {
288         type = types.bool;
289         default = false;
290         description = lib.mdDoc "Disable UDP relay endpoints";
291       };
292       no-tcp-relay = mkOption {
293         type = types.bool;
294         default = false;
295         description = lib.mdDoc "Disable TCP relay endpoints";
296       };
297       extraConfig = mkOption {
298         type = types.lines;
299         default = "";
300         description = lib.mdDoc "Additional configuration options";
301       };
302     };
303   };
305   config = mkIf cfg.enable (mkMerge ([
306     { assertions = [
307       { assertion = cfg.static-auth-secret != null -> cfg.static-auth-secret-file == null ;
308         message = "static-auth-secret and static-auth-secret-file cannot be set at the same time";
309       }
310     ];}
312     {
313       users.users.turnserver =
314         { uid = config.ids.uids.turnserver;
315           group = "turnserver";
316           description = "coturn TURN server user";
317         };
318       users.groups.turnserver =
319         { gid = config.ids.gids.turnserver;
320           members = [ "turnserver" ];
321         };
323       systemd.services.coturn = let
324         runConfig = "/run/coturn/turnserver.cfg";
325       in {
326         description = "coturn TURN server";
327         after = [ "network-online.target" ];
328         wants = [ "network-online.target" ];
329         wantedBy = [ "multi-user.target" ];
331         unitConfig = {
332           Documentation = "man:coturn(1) man:turnadmin(1) man:turnserver(1)";
333         };
335         preStart = ''
336           cat ${configFile} > ${runConfig}
337           ${optionalString (cfg.static-auth-secret-file != null) ''
338             ${pkgs.replace-secret}/bin/replace-secret \
339               "#static-auth-secret#" \
340               ${cfg.static-auth-secret-file} \
341               ${runConfig}
342           '' }
343           chmod 640 ${runConfig}
344         '';
345         serviceConfig = {
346           Type = "simple";
347           ExecStart = "${pkgs.coturn}/bin/turnserver -c ${runConfig}";
348           RuntimeDirectory = "turnserver";
349           User = "turnserver";
350           Group = "turnserver";
351           AmbientCapabilities =
352             mkIf (
353               cfg.listening-port < 1024 ||
354               cfg.alt-listening-port < 1024 ||
355               cfg.tls-listening-port < 1024 ||
356               cfg.alt-tls-listening-port < 1024 ||
357               cfg.min-port < 1024
358             ) "cap_net_bind_service";
359           Restart = "on-abort";
360         };
361       };
362     systemd.tmpfiles.rules = [
363       "d  /run/coturn 0700 turnserver turnserver - -"
364     ];
365   }]));