diff --git a/nixos/tako/services/matrix/tuwunel.nix b/nixos/tako/services/matrix/tuwunel.nix index 6d73164b..bc67106c 100644 --- a/nixos/tako/services/matrix/tuwunel.nix +++ b/nixos/tako/services/matrix/tuwunel.nix @@ -1,11 +1,21 @@ { config, pkgs, + lib, ... }: let port = 6167; base_domain = "darksailor.dev"; client_id = "tuwunel"; + rtc_domain = "matrix-rtc.${base_domain}"; + livekit_port = 7880; + livekit_rtc_tcp_port = 7881; + livekit_rtc_port_start = 50100; + livekit_rtc_port_end = 50200; + livekit_turn_udp_port = 3478; + livekit_turn_relay_start = 50300; + livekit_turn_relay_end = 65535; + jwt_port = 8081; elementConfig = builtins.toJSON { default_server_config = { "m.homeserver" = { @@ -19,6 +29,25 @@ }; }; elementConfigFile = pkgs.writeText "element-config.json" elementConfig; + livekitConfigTemplate = pkgs.writeText "livekit.yaml.template" '' + port: ${toString livekit_port} + bind_addresses: + - "" + rtc: + tcp_port: ${toString livekit_rtc_tcp_port} + port_range_start: ${toString livekit_rtc_port_start} + port_range_end: ${toString livekit_rtc_port_end} + use_external_ip: true + enable_loopback_candidate: false + keys: + LIVEKIT_KEY_PLACEHOLDER: LIVEKIT_SECRET_PLACEHOLDER + turn: + enabled: true + udp_port: ${toString livekit_turn_udp_port} + relay_range_start: ${toString livekit_turn_relay_start} + relay_range_end: ${toString livekit_turn_relay_end} + domain: ${rtc_domain} + ''; in { sops = { secrets."tuwunel/client_id" = { @@ -32,6 +61,8 @@ in { mode = "0440"; }; secrets."tuwunel/registration_token".owner = config.services.matrix-tuwunel.user; + secrets."livekit/key_name" = {}; + secrets."livekit/key_secret" = {}; }; services.matrix-tuwunel = { enable = true; @@ -56,6 +87,12 @@ in { well_known = { client = "https://matrix.${base_domain}"; server = "matrix.${base_domain}:443"; + rtc_transports = [ + { + type = "livekit"; + livekit_service_url = "https://${rtc_domain}"; + } + ]; }; }; package = pkgs.matrix-tuwunel; @@ -76,11 +113,87 @@ in { # "matrix.${base_domain}:8448".extraConfig = '' # reverse_proxy /_matrix/* localhost:${toString port} # ''; + "${rtc_domain}".extraConfig = '' + @jwt_service { + path /sfu/get* /healthz* + } + handle @jwt_service { + reverse_proxy localhost:${toString jwt_port} + } + handle { + reverse_proxy localhost:${toString livekit_port} { + header_up Connection "upgrade" + header_up Upgrade {http.request.header.Upgrade} + } + } + ''; + }; + networking.firewall = { + allowedTCPPorts = [8448 livekit_rtc_tcp_port]; + allowedUDPPorts = [livekit_turn_udp_port]; + allowedUDPPortRanges = [ + { + from = livekit_rtc_port_start; + to = livekit_rtc_port_end; + } + { + from = livekit_turn_relay_start; + to = livekit_turn_relay_end; + } + ]; }; - networking.firewall.allowedTCPPorts = [8448]; users.users.${config.services.caddy.user}.extraGroups = [config.services.matrix-tuwunel.group]; + # LiveKit server + systemd.services.livekit = { + description = "LiveKit SFU server"; + after = ["network-online.target"]; + wants = ["network-online.target"]; + wantedBy = ["multi-user.target"]; + serviceConfig = { + DynamicUser = true; + StateDirectory = "livekit"; + RuntimeDirectory = "livekit"; + ExecStartPre = let + script = pkgs.writeShellScript "livekit-config" '' + KEY_NAME=$(cat ${config.sops.secrets."livekit/key_name".path}) + KEY_SECRET=$(cat ${config.sops.secrets."livekit/key_secret".path}) + ${lib.getExe pkgs.gnused} \ + -e "s|LIVEKIT_KEY_PLACEHOLDER|$KEY_NAME|g" \ + -e "s|LIVEKIT_SECRET_PLACEHOLDER|$KEY_SECRET|g" \ + ${livekitConfigTemplate} > /run/livekit/livekit.yaml + ''; + in "${script}"; + ExecStart = "${lib.getExe pkgs.livekit} --config /run/livekit/livekit.yaml"; + Restart = "on-failure"; + RestartSec = 5; + AmbientCapabilities = ["CAP_NET_BIND_SERVICE"]; + }; + }; + + # LiveKit JWT service for MatrixRTC + systemd.services.lk-jwt-service = { + description = "LiveKit JWT service for MatrixRTC"; + after = ["network-online.target" "livekit.service"]; + wants = ["network-online.target"]; + requires = ["livekit.service"]; + wantedBy = ["multi-user.target"]; + serviceConfig = { + DynamicUser = true; + ExecStart = "${lib.getExe pkgs.lk-jwt-service}"; + Restart = "on-failure"; + RestartSec = 5; + }; + environment = { + LIVEKIT_JWT_BIND = ":${toString jwt_port}"; + LIVEKIT_URL = "wss://${rtc_domain}"; + LIVEKIT_KEY_FILE = config.sops.secrets."livekit/key_name".path; + LIVEKIT_SECRET_FILE = config.sops.secrets."livekit/key_secret".path; + LIVEKIT_FULL_ACCESS_HOMESERVERS = base_domain; + }; + }; + services = { authelia = { instances.darksailor = {