Loading nixos/modules/module-list.nix +2 −0 Original line number Diff line number Diff line Loading @@ -752,6 +752,7 @@ ./services/matrix/dendrite.nix ./services/matrix/hebbot.nix ./services/matrix/hookshot.nix ./services/matrix/lk-jwt-service.nix ./services/matrix/matrix-alertmanager.nix ./services/matrix/maubot.nix ./services/matrix/mautrix-meta.nix Loading Loading @@ -1181,6 +1182,7 @@ ./services/networking/lambdabot.nix ./services/networking/legit.nix ./services/networking/libreswan.nix ./services/networking/livekit.nix ./services/networking/lldpd.nix ./services/networking/logmein-hamachi.nix ./services/networking/lokinet.nix Loading nixos/modules/services/matrix/lk-jwt-service.nix 0 → 100644 +93 −0 Original line number Diff line number Diff line { config, lib, pkgs, ... }: let cfg = config.services.lk-jwt-service; in { meta.maintainers = [ lib.maintainers.quadradical ]; options.services.lk-jwt-service = { enable = lib.mkEnableOption "Enable lk-jwt-service"; package = lib.mkPackageOption pkgs "lk-jwt-service" { }; livekitUrl = lib.mkOption { type = lib.types.strMatching "^wss?://.*"; example = "wss://example.com/livekit/sfu"; description = '' The public websocket URL for livekit. The proto needs to be either `wss://` (recommended) or `ws://` (insecure). ''; }; keyFile = lib.mkOption { type = lib.types.path; description = '' Path to a file containing the credential mapping (`<keyname>: <secret>`) to access LiveKit. Example: ``` lk-jwt-service: f6lQGaHtM5HfgZjIcec3cOCRfiDqIine4CpZZnqdT5cE ``` For more information, see <https://github.com/element-hq/lk-jwt-service#configuration>. ''; }; port = lib.mkOption { type = lib.types.port; default = 8080; description = "Port that lk-jwt-service should listen on."; }; }; config = lib.mkIf cfg.enable { systemd.services.lk-jwt-service = { description = "Minimal service to issue LiveKit JWTs for MatrixRTC"; documentation = [ "https://github.com/element-hq/lk-jwt-service" ]; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; environment = { LIVEKIT_URL = cfg.livekitUrl; LIVEKIT_JWT_PORT = toString cfg.port; LIVEKIT_KEY_FILE = "/run/credentials/lk-jwt-service.service/livekit-secrets"; }; serviceConfig = { LoadCredential = [ "livekit-secrets:${cfg.keyFile}" ]; ExecStart = lib.getExe cfg.package; DynamicUser = true; LockPersonality = true; MemoryDenyWriteExecute = true; ProtectClock = true; ProtectControlGroups = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; PrivateDevices = true; PrivateMounts = true; PrivateUsers = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; RestrictNamespaces = true; RestrictRealtime = true; ProtectHome = true; SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; Restart = "on-failure"; RestartSec = 5; UMask = "077"; }; }; }; } nixos/modules/services/networking/livekit.nix 0 → 100644 +141 −0 Original line number Diff line number Diff line { config, lib, pkgs, utils, ... }: let cfg = config.services.livekit; format = pkgs.formats.json { }; in { meta.maintainers = with lib.maintainers; [ quadradical ]; options.services.livekit = { enable = lib.mkEnableOption "Enable the livekit server"; package = lib.mkPackageOption pkgs "livekit" { }; keyFile = lib.mkOption { type = lib.types.path; description = '' LiveKit key file holding one or multiple application secrets. Use `livekit-server generate-keys` to generate a random key name and secret. The file should have the format `<keyname>: <secret>`. Example: ``` lk-jwt-service: f6lQGaHtM5HfgZjIcec3cOCRfiDqIine4CpZZnqdT5cE ``` Individual key/secret pairs need to be passed to clients to connect to this instance. ''; }; openFirewall = lib.mkOption { type = lib.types.bool; default = false; description = "Opens port range for LiveKit on the firewall."; }; settings = lib.mkOption { type = lib.types.submodule { freeformType = format.type; options = { port = lib.mkOption { type = lib.types.port; default = 7880; description = "Main TCP port for RoomService and RTC endpoint."; }; rtc = { port_range_start = lib.mkOption { type = lib.types.int; default = 50000; description = "Start of UDP port range for WebRTC"; }; port_range_end = lib.mkOption { type = lib.types.int; default = 51000; description = "End of UDP port range for WebRTC"; }; use_external_ip = lib.mkOption { type = lib.types.bool; default = false; description = '' When set to true, attempts to discover the host's public IP via STUN. This is useful for cloud environments such as AWS & Google where hosts have an internal IP that maps to an external one. ''; }; }; }; }; default = { }; description = '' LiveKit configuration file expressed in nix. For an example configuration, see <https://docs.livekit.io/home/self-hosting/deployment/#configuration>. For all possible values, see <https://github.com/livekit/livekit/blob/master/config-sample.yaml>. ''; }; }; config = lib.mkIf cfg.enable { networking.firewall = lib.mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.settings.port ]; allowedUDPPortRanges = [ { from = cfg.settings.rtc.port_range_start; to = cfg.settings.rtc.port_range_end; } ]; }; systemd.services.livekit = { description = "LiveKit SFU server"; documentation = [ "https://docs.livekit.io" ]; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; serviceConfig = { LoadCredential = [ "livekit-secrets:${cfg.keyFile}" ]; ExecStart = utils.escapeSystemdExecArgs [ (lib.getExe cfg.package) "--config=${format.generate "livekit.json" cfg.settings}" "--key-file=/run/credentials/livekit.service/livekit-secrets" ]; DynamicUser = true; LockPersonality = true; MemoryDenyWriteExecute = true; ProtectClock = true; ProtectControlGroups = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; PrivateDevices = true; PrivateMounts = true; PrivateUsers = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_NETLINK" ]; RestrictNamespaces = true; RestrictRealtime = true; ProtectHome = true; SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; Restart = "on-failure"; RestartSec = 5; UMask = "077"; }; }; }; } nixos/tests/all-tests.nix +2 −0 Original line number Diff line number Diff line Loading @@ -729,11 +729,13 @@ in lidarr = handleTest ./lidarr.nix { }; lightdm = handleTest ./lightdm.nix { }; lighttpd = runTest ./lighttpd.nix; livekit = runTest ./networking/livekit.nix; limesurvey = handleTest ./limesurvey.nix { }; limine = import ./limine { inherit runTest; }; listmonk = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./listmonk.nix { }; litellm = runTest ./litellm.nix; litestream = handleTest ./litestream.nix { }; lk-jwt-service = runTest ./matrix/lk-jwt-service.nix; lldap = handleTest ./lldap.nix { }; localsend = handleTest ./localsend.nix { }; locate = handleTest ./locate.nix { }; Loading nixos/tests/matrix/lk-jwt-service.nix 0 → 100644 +26 −0 Original line number Diff line number Diff line { pkgs, lib, ... }: { name = "lk-jwt-service"; meta.maintainers = [ lib.maintainers.quadradical ]; nodes.machine = { services.lk-jwt-service = { enable = true; keyFile = pkgs.writers.writeYAML "keys.yaml" { key = "f6lQGaHtM5HfgZjIcec3cOCRfiDqIine4CpZZnqdT5cE"; }; livekitUrl = "wss://127.0.0.1:8100"; port = 8000; }; }; testScript = '' machine.wait_for_unit("lk-jwt-service.service") machine.wait_for_open_port(8000) machine.succeed('curl 127.0.0.1:8000/sfu/get -sLX POST -w "%{http_code}" | grep -q "^400"') ''; } Loading
nixos/modules/module-list.nix +2 −0 Original line number Diff line number Diff line Loading @@ -752,6 +752,7 @@ ./services/matrix/dendrite.nix ./services/matrix/hebbot.nix ./services/matrix/hookshot.nix ./services/matrix/lk-jwt-service.nix ./services/matrix/matrix-alertmanager.nix ./services/matrix/maubot.nix ./services/matrix/mautrix-meta.nix Loading Loading @@ -1181,6 +1182,7 @@ ./services/networking/lambdabot.nix ./services/networking/legit.nix ./services/networking/libreswan.nix ./services/networking/livekit.nix ./services/networking/lldpd.nix ./services/networking/logmein-hamachi.nix ./services/networking/lokinet.nix Loading
nixos/modules/services/matrix/lk-jwt-service.nix 0 → 100644 +93 −0 Original line number Diff line number Diff line { config, lib, pkgs, ... }: let cfg = config.services.lk-jwt-service; in { meta.maintainers = [ lib.maintainers.quadradical ]; options.services.lk-jwt-service = { enable = lib.mkEnableOption "Enable lk-jwt-service"; package = lib.mkPackageOption pkgs "lk-jwt-service" { }; livekitUrl = lib.mkOption { type = lib.types.strMatching "^wss?://.*"; example = "wss://example.com/livekit/sfu"; description = '' The public websocket URL for livekit. The proto needs to be either `wss://` (recommended) or `ws://` (insecure). ''; }; keyFile = lib.mkOption { type = lib.types.path; description = '' Path to a file containing the credential mapping (`<keyname>: <secret>`) to access LiveKit. Example: ``` lk-jwt-service: f6lQGaHtM5HfgZjIcec3cOCRfiDqIine4CpZZnqdT5cE ``` For more information, see <https://github.com/element-hq/lk-jwt-service#configuration>. ''; }; port = lib.mkOption { type = lib.types.port; default = 8080; description = "Port that lk-jwt-service should listen on."; }; }; config = lib.mkIf cfg.enable { systemd.services.lk-jwt-service = { description = "Minimal service to issue LiveKit JWTs for MatrixRTC"; documentation = [ "https://github.com/element-hq/lk-jwt-service" ]; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; environment = { LIVEKIT_URL = cfg.livekitUrl; LIVEKIT_JWT_PORT = toString cfg.port; LIVEKIT_KEY_FILE = "/run/credentials/lk-jwt-service.service/livekit-secrets"; }; serviceConfig = { LoadCredential = [ "livekit-secrets:${cfg.keyFile}" ]; ExecStart = lib.getExe cfg.package; DynamicUser = true; LockPersonality = true; MemoryDenyWriteExecute = true; ProtectClock = true; ProtectControlGroups = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; PrivateDevices = true; PrivateMounts = true; PrivateUsers = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; RestrictNamespaces = true; RestrictRealtime = true; ProtectHome = true; SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; Restart = "on-failure"; RestartSec = 5; UMask = "077"; }; }; }; }
nixos/modules/services/networking/livekit.nix 0 → 100644 +141 −0 Original line number Diff line number Diff line { config, lib, pkgs, utils, ... }: let cfg = config.services.livekit; format = pkgs.formats.json { }; in { meta.maintainers = with lib.maintainers; [ quadradical ]; options.services.livekit = { enable = lib.mkEnableOption "Enable the livekit server"; package = lib.mkPackageOption pkgs "livekit" { }; keyFile = lib.mkOption { type = lib.types.path; description = '' LiveKit key file holding one or multiple application secrets. Use `livekit-server generate-keys` to generate a random key name and secret. The file should have the format `<keyname>: <secret>`. Example: ``` lk-jwt-service: f6lQGaHtM5HfgZjIcec3cOCRfiDqIine4CpZZnqdT5cE ``` Individual key/secret pairs need to be passed to clients to connect to this instance. ''; }; openFirewall = lib.mkOption { type = lib.types.bool; default = false; description = "Opens port range for LiveKit on the firewall."; }; settings = lib.mkOption { type = lib.types.submodule { freeformType = format.type; options = { port = lib.mkOption { type = lib.types.port; default = 7880; description = "Main TCP port for RoomService and RTC endpoint."; }; rtc = { port_range_start = lib.mkOption { type = lib.types.int; default = 50000; description = "Start of UDP port range for WebRTC"; }; port_range_end = lib.mkOption { type = lib.types.int; default = 51000; description = "End of UDP port range for WebRTC"; }; use_external_ip = lib.mkOption { type = lib.types.bool; default = false; description = '' When set to true, attempts to discover the host's public IP via STUN. This is useful for cloud environments such as AWS & Google where hosts have an internal IP that maps to an external one. ''; }; }; }; }; default = { }; description = '' LiveKit configuration file expressed in nix. For an example configuration, see <https://docs.livekit.io/home/self-hosting/deployment/#configuration>. For all possible values, see <https://github.com/livekit/livekit/blob/master/config-sample.yaml>. ''; }; }; config = lib.mkIf cfg.enable { networking.firewall = lib.mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.settings.port ]; allowedUDPPortRanges = [ { from = cfg.settings.rtc.port_range_start; to = cfg.settings.rtc.port_range_end; } ]; }; systemd.services.livekit = { description = "LiveKit SFU server"; documentation = [ "https://docs.livekit.io" ]; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; serviceConfig = { LoadCredential = [ "livekit-secrets:${cfg.keyFile}" ]; ExecStart = utils.escapeSystemdExecArgs [ (lib.getExe cfg.package) "--config=${format.generate "livekit.json" cfg.settings}" "--key-file=/run/credentials/livekit.service/livekit-secrets" ]; DynamicUser = true; LockPersonality = true; MemoryDenyWriteExecute = true; ProtectClock = true; ProtectControlGroups = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; PrivateDevices = true; PrivateMounts = true; PrivateUsers = true; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_NETLINK" ]; RestrictNamespaces = true; RestrictRealtime = true; ProtectHome = true; SystemCallArchitectures = "native"; SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; Restart = "on-failure"; RestartSec = 5; UMask = "077"; }; }; }; }
nixos/tests/all-tests.nix +2 −0 Original line number Diff line number Diff line Loading @@ -729,11 +729,13 @@ in lidarr = handleTest ./lidarr.nix { }; lightdm = handleTest ./lightdm.nix { }; lighttpd = runTest ./lighttpd.nix; livekit = runTest ./networking/livekit.nix; limesurvey = handleTest ./limesurvey.nix { }; limine = import ./limine { inherit runTest; }; listmonk = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./listmonk.nix { }; litellm = runTest ./litellm.nix; litestream = handleTest ./litestream.nix { }; lk-jwt-service = runTest ./matrix/lk-jwt-service.nix; lldap = handleTest ./lldap.nix { }; localsend = handleTest ./localsend.nix { }; locate = handleTest ./locate.nix { }; Loading
nixos/tests/matrix/lk-jwt-service.nix 0 → 100644 +26 −0 Original line number Diff line number Diff line { pkgs, lib, ... }: { name = "lk-jwt-service"; meta.maintainers = [ lib.maintainers.quadradical ]; nodes.machine = { services.lk-jwt-service = { enable = true; keyFile = pkgs.writers.writeYAML "keys.yaml" { key = "f6lQGaHtM5HfgZjIcec3cOCRfiDqIine4CpZZnqdT5cE"; }; livekitUrl = "wss://127.0.0.1:8100"; port = 8000; }; }; testScript = '' machine.wait_for_unit("lk-jwt-service.service") machine.wait_for_open_port(8000) machine.succeed('curl 127.0.0.1:8000/sfu/get -sLX POST -w "%{http_code}" | grep -q "^400"') ''; }