Self-host your own digital island
1{ config, pkgs, lib, ... }:
2
3with lib;
4let
5 cfg = config.eilean;
6 domain = config.networking.domain;
7 staticAuthSecretFile = "/run/coturn/static-auth-secret";
8in
9{
10 options.eilean.turn = {
11 enable = mkEnableOption "TURN server";
12 };
13
14 config = mkIf cfg.turn.enable {
15 services.coturn = rec {
16 enable = true;
17 no-cli = true;
18 no-tcp-relay = true;
19 secure-stun = true;
20 use-auth-secret = true;
21 static-auth-secret-file = staticAuthSecretFile;
22 realm = "turn.${domain}";
23 relay-ips = with config.eilean; [
24 serverIpv4
25 serverIpv6
26 ];
27 cert = "${config.security.acme.certs.${realm}.directory}/full.pem";
28 pkey = "${config.security.acme.certs.${realm}.directory}/key.pem";
29 };
30
31 systemd.services = {
32 coturn-static-auth-secret-generator = {
33 description = "Generate coturn static auth secret file";
34 script = ''
35 if [ ! -f '${staticAuthSecretFile}' ]; then
36 umask 077
37 tr -dc A-Za-z0-9 </dev/urandom | head -c 32 > '${staticAuthSecretFile}'
38 chown ${config.systemd.services.coturn.serviceConfig.User}:${config.systemd.services.coturn.serviceConfig.Group} '${staticAuthSecretFile}'
39 fi
40 '';
41 serviceConfig.Type = "oneshot";
42 serviceConfig.RemainAfterExit = true;
43 };
44 "coturn" = {
45 after = [ "coturn-static-auth-secret-generator.service" ];
46 requires = [ "coturn-static-auth-secret-generator.service" ];
47 };
48 };
49
50 networking.firewall =
51 with config.services.coturn;
52 let
53 turn-range = {
54 from = min-port;
55 to = max-port;
56 };
57 stun-ports = [
58 listening-port
59 tls-listening-port
60 # these are only used if server has more than one IP address (of the same family
61 #alt-listening-port
62 #alt-tls-listening-port
63 ];
64 in {
65 allowedTCPPorts = stun-ports;
66 allowedTCPPortRanges = [ turn-range ];
67 allowedUDPPorts = stun-ports;
68 allowedUDPPortRanges = [ turn-range ];
69 };
70
71 security.acme.certs.${config.services.coturn.realm} = {
72 postRun = "systemctl reload nginx.service; systemctl restart coturn.service";
73 group = "turnserver";
74 };
75 services.nginx.enable = true;
76 services.nginx.virtualHosts = {
77 "${config.services.coturn.realm}" = {
78 forceSSL = true;
79 enableACME = true;
80 };
81 };
82 users.groups."turnserver".members = [ config.services.nginx.user ];
83
84 eilean.dns.enable = true;
85 eilean.services.dns.zones.${config.networking.domain}.records = [
86 {
87 name = "turn";
88 type = "CNAME";
89 data = "vps";
90 }
91 ];
92 };
93}