at master 5.4 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 utils, 6 ... 7}: 8let 9 cfg = config.services.livekit.ingress; 10 format = pkgs.formats.yaml { }; 11 settings = lib.filterAttrsRecursive (_: v: v != null) cfg.settings; 12 13 isLocallyDistributed = config.services.livekit.enable; 14in 15{ 16 meta.maintainers = with lib.maintainers; [ k900 ]; 17 options.services.livekit.ingress = { 18 enable = lib.mkEnableOption "the livekit ingress service"; 19 package = lib.mkPackageOption pkgs "livekit-ingress" { }; 20 21 openFirewall = { 22 rtc = lib.mkOption { 23 type = lib.types.bool; 24 default = false; 25 description = "Open WebRTC ports in the firewall."; 26 }; 27 28 rtmp = lib.mkOption { 29 type = lib.types.bool; 30 default = false; 31 description = "Open RTMP port in the firewall."; 32 }; 33 34 whip = lib.mkOption { 35 type = lib.types.bool; 36 default = false; 37 description = "Open WHIP port in the firewall."; 38 }; 39 }; 40 41 settings = lib.mkOption { 42 type = lib.types.submodule { 43 freeformType = format.type; 44 options = { 45 rtmp_port = lib.mkOption { 46 type = lib.types.port; 47 default = 1935; 48 description = "TCP port for RTMP connections"; 49 }; 50 51 whip_port = lib.mkOption { 52 type = lib.types.port; 53 default = 8080; 54 description = "TCP port for WHIP connections"; 55 }; 56 57 redis = { 58 address = lib.mkOption { 59 type = with lib.types; nullOr str; 60 default = 61 if isLocallyDistributed then 62 "${config.services.livekit.redis.host}:${toString config.services.livekit.redis.port}" 63 else 64 null; 65 example = "redis.example.com:6379"; 66 defaultText = "Host and port of the local livekit redis instance, if enabled, or null"; 67 description = "Address or hostname and port for redis connection"; 68 }; 69 70 }; 71 72 rtc_config = { 73 port_range_start = lib.mkOption { 74 type = lib.types.port; 75 default = 50000; 76 description = "Start of UDP port range for WebRTC"; 77 }; 78 79 port_range_end = lib.mkOption { 80 type = lib.types.port; 81 default = 51000; 82 description = "End of UDP port range for WebRTC"; 83 }; 84 85 use_external_ip = lib.mkOption { 86 type = lib.types.bool; 87 default = false; 88 description = '' 89 When set to true, attempts to discover the host's public IP via STUN. 90 This is useful for cloud environments such as AWS & Google where hosts have an internal IP that maps to an external one. 91 ''; 92 }; 93 }; 94 }; 95 }; 96 default = { }; 97 description = '' 98 LiveKit Ingress configuration. 99 100 See <https://github.com/livekit/ingress?tab=readme-ov-file#config> for possible options. 101 ''; 102 example = { 103 prometheus_port = 9039; 104 cpu_cost = { 105 rtmp_cpu_cost = 3.0; 106 whip_cpu_cost = 1.0; 107 }; 108 }; 109 }; 110 111 environmentFile = lib.mkOption { 112 type = lib.types.nullOr lib.types.path; 113 default = null; 114 description = '' 115 Environment file as defined in {manpage}`systemd.exec(5)` passed to the service. 116 117 Use this to specify `LIVEKIT_API_KEY` and `LIVEKIT_API_SECRET`. 118 ''; 119 }; 120 }; 121 122 config = lib.mkIf cfg.enable { 123 networking.firewall = { 124 allowedTCPPorts = lib.mkMerge [ 125 (lib.mkIf cfg.openFirewall.rtmp [ cfg.settings.rtmp_port ]) 126 (lib.mkIf cfg.openFirewall.whip [ cfg.settings.whip_port ]) 127 ]; 128 allowedUDPPortRanges = lib.mkIf cfg.openFirewall.rtc [ 129 { 130 from = cfg.settings.rtc_config.port_range_start; 131 to = cfg.settings.rtc_config.port_range_end; 132 } 133 ]; 134 }; 135 136 systemd.services.livekit-ingress = { 137 description = "LiveKit Ingress server"; 138 documentation = [ "https://docs.livekit.io/home/self-hosting/ingress/" ]; 139 wantedBy = [ "multi-user.target" ]; 140 wants = [ "network-online.target" ]; 141 after = [ "network-online.target" ]; 142 143 serviceConfig = { 144 ExecStart = utils.escapeSystemdExecArgs [ 145 (lib.getExe cfg.package) 146 "--config=${format.generate "ingress.yaml" settings}" 147 ]; 148 EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; 149 DynamicUser = true; 150 LockPersonality = true; 151 MemoryDenyWriteExecute = true; 152 ProtectClock = true; 153 ProtectControlGroups = true; 154 ProtectHostname = true; 155 ProtectKernelLogs = true; 156 ProtectKernelModules = true; 157 ProtectKernelTunables = true; 158 PrivateDevices = true; 159 PrivateMounts = true; 160 PrivateUsers = true; 161 RestrictAddressFamilies = [ 162 "AF_INET" 163 "AF_INET6" 164 "AF_NETLINK" 165 ]; 166 RestrictNamespaces = true; 167 RestrictRealtime = true; 168 ProtectHome = true; 169 SystemCallArchitectures = "native"; 170 SystemCallFilter = [ 171 "@system-service" 172 "~@privileged" 173 "~@resources" 174 ]; 175 Restart = "on-failure"; 176 RestartSec = 5; 177 UMask = "077"; 178 }; 179 }; 180 }; 181}