From 709af80e7398ba1f223cf331501b6c96d4d84a16 Mon Sep 17 00:00:00 2001 From: Dominik Polakovics Date: Tue, 3 Mar 2026 09:51:47 +0100 Subject: [PATCH] feat: add coturn to matrix --- hosts/fw/configuration.nix | 1 + hosts/fw/modules/coturn.nix | 32 ++++++++++ hosts/fw/modules/firewall.nix | 3 + hosts/fw/modules/web/matrix.nix | 48 ++++++++++++-- hosts/fw/modules/web/secrets.yaml | 87 ++++++++++++------------- hosts/fw/secrets.yaml | 101 +++++++++++++++--------------- 6 files changed, 174 insertions(+), 98 deletions(-) create mode 100644 hosts/fw/modules/coturn.nix diff --git a/hosts/fw/configuration.nix b/hosts/fw/configuration.nix index d9b8591..8caf67a 100644 --- a/hosts/fw/configuration.nix +++ b/hosts/fw/configuration.nix @@ -43,6 +43,7 @@ # web ./modules/web + ./modules/coturn.nix # git ./modules/forgejo.nix diff --git a/hosts/fw/modules/coturn.nix b/hosts/fw/modules/coturn.nix new file mode 100644 index 0000000..b660d6b --- /dev/null +++ b/hosts/fw/modules/coturn.nix @@ -0,0 +1,32 @@ +{ config, ... }: +let + domain = "turn.cloonar.com"; +in +{ + security.acme.certs."${domain}" = { + group = "turnserver"; + postRun = "systemctl try-restart coturn.service"; + }; + + sops.secrets.coturn-static-secret = { + owner = "turnserver"; + }; + + services.coturn = { + enable = true; + realm = domain; + use-auth-secret = true; + static-auth-secret-file = config.sops.secrets.coturn-static-secret.path; + cert = "${config.security.acme.certs.${domain}.directory}/fullchain.pem"; + pkey = "${config.security.acme.certs.${domain}.directory}/key.pem"; + min-port = 49152; + max-port = 49999; + no-tcp-relay = true; + no-cli = true; + }; + + systemd.services.coturn = { + after = [ "acme-${domain}.service" ]; + wants = [ "acme-${domain}.service" ]; + }; +} diff --git a/hosts/fw/modules/firewall.nix b/hosts/fw/modules/firewall.nix index c876e13..61f9205 100644 --- a/hosts/fw/modules/firewall.nix +++ b/hosts/fw/modules/firewall.nix @@ -74,6 +74,9 @@ # Allow returning traffic from wan and drop everthing else iifname "wan" ct state { established, related } accept comment "Allow established traffic" iifname "wan" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + iifname "wan" udp dport { 3478, 5349 } counter accept comment "TURN/STUN UDP" + iifname "wan" tcp dport { 3478, 5349 } counter accept comment "TURN/STUN TCP + TURNS/TLS" + iifname "wan" udp dport { 49152-49999 } counter accept comment "TURN relay UDP range" iifname "wan" counter drop comment "Drop all other unsolicited traffic from wan" limit rate 60/minute burst 100 packets log prefix "Input - Drop: " comment "Log any unmatched traffic" diff --git a/hosts/fw/modules/web/matrix.nix b/hosts/fw/modules/web/matrix.nix index 8889fe2..d9a8ece 100644 --- a/hosts/fw/modules/web/matrix.nix +++ b/hosts/fw/modules/web/matrix.nix @@ -28,6 +28,8 @@ let endpoint: "http://127.0.0.1:8081" secret_path: ${config.sops.secrets.mas-matrix-secret-synapse.path} ''; + + synapseVoipConfig = "/run/matrix-synapse/voip-config.yaml"; in { # Secrets for MAS sops.secrets.mas-encryption-key = { owner = "mas"; }; @@ -40,6 +42,12 @@ in { key = "mas-matrix-secret"; }; + # TURN shared secret (for Synapse VoIP config) + sops.secrets.coturn-static-secret = { + sopsFile = ./secrets.yaml; + owner = "matrix-synapse"; + }; + sops.secrets.mautrix-whatsapp-env = { }; sops.secrets.mautrix-signal-env = { }; sops.secrets.mautrix-discord-env = { }; @@ -177,7 +185,7 @@ in { # Synapse homeserver services.matrix-synapse = { enable = true; - extraConfigFiles = [ "${synapseMasConfig}" ]; + extraConfigFiles = [ "${synapseMasConfig}" synapseVoipConfig ]; settings = { server_name = "cloonar.com"; public_baseurl = baseUrl; @@ -224,6 +232,19 @@ in { systemd.services.matrix-synapse.after = [ "matrix-authentication-service.service" ]; systemd.services.matrix-synapse.wants = [ "matrix-authentication-service.service" ]; systemd.services.matrix-synapse.serviceConfig.PrivateUsers = lib.mkForce false; + systemd.services.matrix-synapse.preStart = lib.mkAfter '' + install -m 0600 -o matrix-synapse /dev/null ${synapseVoipConfig} + TURN_SECRET=$(cat ${config.sops.secrets.coturn-static-secret.path}) + cat > ${synapseVoipConfig} <