From 8baefe1bfd042ff1adba3a9841f9a9dd9351a2c0 Mon Sep 17 00:00:00 2001 From: Sovran Systems <99053422+naturallaw777@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:03:26 -0500 Subject: [PATCH] fix(element-calling): enable LiveKit embedded TURN with runtime matrix domain + cert LiveKit was exiting cleanly with "TURN domain required" because turn.enabled was set in the build-time config but turn.domain was never provided to the process (the old livekit-runtime-config.service wrote a YAML that nothing read). A clean exit (status 0) meant Restart=on-failure never restarted it, so the Hub reported the service as Inactive. This replaces the dead runtime-config oneshot with livekit-turn-setup.service, which at runtime: - reads the matrix domain from /var/lib/domains/matrix (no hardcoding) - copies Caddy's already-issued matrix cert/key into /var/lib/livekit - generates a complete LiveKit config (incl. turn.domain + TLS cert/key) at /run/livekit/livekit.yaml The livekit.service ExecStart is overridden to load that runtime config (mirroring the existing Caddy ExecStart override pattern in modules/core/caddy.nix), since turn.domain is only known at runtime. The cert is delivered via LoadCredential so it is readable under DynamicUser=true without weakening the sandbox. Also aligns the RTC media port range (rtc.port_range_start/end = 30000-40000) so it matches the forwarded ports, and drops the now-redundant manual 30000-40000 firewall ranges (covered by services.livekit settings/openFirewall). --- modules/element-calling.nix | 76 ++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/modules/element-calling.nix b/modules/element-calling.nix index 4ea502b..014b941 100755 --- a/modules/element-calling.nix +++ b/modules/element-calling.nix @@ -34,8 +34,8 @@ lib.mkIf config.sovran_systemsOS.features.element-calling { }; ####### ENSURE SERVICES START AFTER KEY EXISTS ####### - systemd.services.livekit.after = [ "livekit-key-setup.service" ]; - systemd.services.livekit.wants = [ "livekit-key-setup.service" ]; + systemd.services.livekit.after = [ "livekit-key-setup.service" "livekit-turn-setup.service" ]; + systemd.services.livekit.wants = [ "livekit-key-setup.service" "livekit-turn-setup.service" ]; systemd.services.lk-jwt-service.after = [ "livekit-key-setup.service" ]; systemd.services.lk-jwt-service.wants = [ "livekit-key-setup.service" ]; @@ -89,11 +89,17 @@ EOF ''; }; - ####### LIVEKIT RUNTIME CONFIG ####### - systemd.services.livekit-runtime-config = { - description = "Generate LiveKit runtime config from domain files"; + ####### LIVEKIT TURN SETUP (runtime cert + config) ####### + # Replaces the old dead livekit-runtime-config.service. At runtime this: + # * reads the matrix domain from /var/lib/domains/matrix (never hardcoded) + # * copies Caddy's already-issued matrix cert/key into /var/lib/livekit + # so LoadCredential can stage them for the (DynamicUser) livekit unit + # * writes a complete LiveKit config (with turn.domain substituted) that the + # overridden ExecStart loads. + systemd.services.livekit-turn-setup = { + description = "Stage TURN cert and generate LiveKit runtime config from domain files"; + after = [ "caddy.service" "livekit-key-setup.service" ]; before = [ "livekit.service" ]; - after = [ "livekit-key-setup.service" ]; requiredBy = [ "livekit.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { @@ -103,20 +109,42 @@ EOF unitConfig = { ConditionPathExists = "/var/lib/domains/element-calling"; }; - path = [ pkgs.coreutils ]; + path = [ pkgs.coreutils pkgs.findutils ]; script = '' MATRIX=$(cat /var/lib/domains/matrix) mkdir -p /run/livekit - cat > /run/livekit/runtime-config.yaml < /run/livekit/livekit.yaml <