feat: add livekit
This commit is contained in:
parent
fb98563bb6
commit
eee6905637
9 changed files with 384 additions and 109 deletions
|
|
@ -1,36 +1,188 @@
|
|||
let
|
||||
lib = import <nixpkgs/lib>;
|
||||
endpoints = (import ../validation/endpoints.nix).getValidatedEndpoints (import ../config/endpoints.nix);
|
||||
net = import ../config/network.nix;
|
||||
tunnelPolicy = import ../validation/tunnel_ports.nix;
|
||||
servicesConfig = import ../config/services.nix;
|
||||
endpointsConfig = (import ../validation/endpoints.nix).getEndpointsConfig (import ../config/endpoints.nix);
|
||||
|
||||
normalizeEndpoint = endpoint:
|
||||
endpoint // {
|
||||
content = endpoint.content // {
|
||||
host = if endpoint.type == "forwarding" then net.tunnel.host else endpoint.content.host;
|
||||
tunnelOffset = 10000;
|
||||
proxyOffset = servicesConfig.nginxProxyOffset;
|
||||
|
||||
forwardingEndpoints = builtins.filter (endpoint: endpoint.type == "forwarding") endpointsConfig;
|
||||
proxyEndpoints = builtins.filter (endpoint: endpoint.type == "proxy") endpointsConfig;
|
||||
|
||||
forwardingTlsEndpoints = builtins.filter (endpoint: endpoint.content.tls or false) forwardingEndpoints;
|
||||
forwardingHttpEndpoints = builtins.filter (endpoint: !(endpoint.content.tls or false)) forwardingEndpoints;
|
||||
proxyTlsEndpoints = builtins.filter (endpoint: endpoint.force_ssl or false) proxyEndpoints;
|
||||
|
||||
forwardingTarget = endpoint: "127.0.0.1:${toString endpoint.content.port}";
|
||||
proxyBackendPort = endpoint: proxyOffset + endpoint.listenPort;
|
||||
proxyBackendTarget = endpoint: "127.0.0.1:${toString (proxyBackendPort endpoint)}";
|
||||
|
||||
mkTlsRouteEntryForForwarding = endpoint: {
|
||||
domain = endpoint.domain;
|
||||
listenPort = endpoint.listenPort;
|
||||
upstream = forwardingTarget endpoint;
|
||||
};
|
||||
|
||||
mkTlsRouteEntryForProxy = endpoint: {
|
||||
domain = endpoint.domain;
|
||||
listenPort = endpoint.listenPort;
|
||||
upstream = proxyBackendTarget endpoint;
|
||||
};
|
||||
|
||||
tlsRouteEntriesRaw =
|
||||
map mkTlsRouteEntryForForwarding forwardingTlsEndpoints
|
||||
++ map mkTlsRouteEntryForProxy proxyTlsEndpoints;
|
||||
|
||||
groupedTlsRoutes =
|
||||
lib.foldl'
|
||||
(acc: entry:
|
||||
let
|
||||
key = toString entry.listenPort;
|
||||
previous = acc.${key} or [];
|
||||
in
|
||||
acc // {
|
||||
${key} = previous ++ [ entry ];
|
||||
}
|
||||
)
|
||||
{}
|
||||
tlsRouteEntriesRaw;
|
||||
|
||||
dedupeRouteEntriesByDomain = entries:
|
||||
builtins.attrValues (builtins.listToAttrs (map (entry: {
|
||||
name = entry.domain;
|
||||
value = entry;
|
||||
}) entries));
|
||||
|
||||
mkTlsRouteMapForListenPort = listenPort:
|
||||
let
|
||||
routesForPort = groupedTlsRoutes.${toString listenPort} or [];
|
||||
routeEntries = dedupeRouteEntriesByDomain routesForPort;
|
||||
defaultRoute = if routeEntries == [] then null else (builtins.head routeEntries).upstream;
|
||||
in
|
||||
if defaultRoute == null then null else {
|
||||
inherit listenPort routeEntries defaultRoute;
|
||||
};
|
||||
};
|
||||
|
||||
normalizedEndpoints = map normalizeEndpoint endpoints;
|
||||
tlsListenPorts = lib.unique (map (entry: entry.listenPort) tlsRouteEntriesRaw);
|
||||
tlsRouteMaps = builtins.filter (mapDef: mapDef != null) (map mkTlsRouteMapForListenPort tlsListenPorts);
|
||||
|
||||
_forwardPortChecks = map (endpoint:
|
||||
if endpoint.content.host == net.tunnel.host && !(tunnelPolicy.isAllowedTunnelPort endpoint.content.port) then
|
||||
throw "Forwarding endpoint listenPort=${toString endpoint.listenPort} targets tunnel-backed local port ${toString endpoint.content.port}, which is not listed in config/network.nix tunnel.allowedPorts."
|
||||
else
|
||||
null
|
||||
) normalizedEndpoints;
|
||||
renderTlsServer = tlsRouteMap:
|
||||
let
|
||||
portString = toString tlsRouteMap.listenPort;
|
||||
in
|
||||
''
|
||||
map $ssl_preread_server_name $proxy_upstream_${portString} {
|
||||
${lib.concatStringsSep "\n" (map (entry: "${entry.domain} ${entry.upstream};") tlsRouteMap.routeEntries)}
|
||||
default ${tlsRouteMap.defaultRoute};
|
||||
}
|
||||
|
||||
mkStreamServer = endpoint: ''
|
||||
server {
|
||||
listen ${toString endpoint.listenPort};
|
||||
proxy_pass ${endpoint.content.host}:${toString endpoint.content.port};
|
||||
listen ${portString};
|
||||
proxy_pass $proxy_upstream_${portString};
|
||||
ssl_preread on;
|
||||
}
|
||||
'';
|
||||
|
||||
streamConfig = lib.concatStringsSep "\n" (map mkStreamServer normalizedEndpoints);
|
||||
groupedProxyEndpoints =
|
||||
lib.foldl'
|
||||
(acc: endpoint:
|
||||
let
|
||||
key = "${endpoint.domain}:${toString endpoint.listenPort}";
|
||||
previous = acc.${key} or {
|
||||
domain = endpoint.domain;
|
||||
publicListenPort = endpoint.listenPort;
|
||||
listenPort = proxyBackendPort endpoint;
|
||||
locations = {};
|
||||
forceSSL = false;
|
||||
};
|
||||
location = {
|
||||
proxyPass = "http://${endpoint.content.host}:${toString endpoint.content.port}/";
|
||||
} // lib.optionalAttrs (endpoint.content ? websocket && endpoint.content.websocket) {
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
in
|
||||
acc // {
|
||||
${key} = previous // {
|
||||
listenPort = proxyBackendPort endpoint;
|
||||
forceSSL = previous.forceSSL || (endpoint.force_ssl or false);
|
||||
locations = previous.locations // {
|
||||
${endpoint.endpoint} = location;
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
{}
|
||||
proxyEndpoints;
|
||||
|
||||
proxyBackendVirtualHosts = lib.mapAttrs (_: hostConfig: {
|
||||
serverName = hostConfig.domain;
|
||||
listen = [
|
||||
{
|
||||
addr = "127.0.0.1";
|
||||
port = hostConfig.listenPort;
|
||||
ssl = true;
|
||||
}
|
||||
];
|
||||
onlySSL = true;
|
||||
extraConfig = ''
|
||||
absolute_redirect off;
|
||||
port_in_redirect off;
|
||||
'';
|
||||
locations = hostConfig.locations;
|
||||
} // lib.optionalAttrs (hostConfig.forceSSL && servicesConfig.nginx.acmeEmail != null) {
|
||||
useACMEHost = hostConfig.domain;
|
||||
}) groupedProxyEndpoints;
|
||||
|
||||
forwardingHttpVirtualHosts = builtins.listToAttrs (map (endpoint: {
|
||||
name = "forward-http-${endpoint.domain}-${toString endpoint.listenPort}";
|
||||
value = {
|
||||
serverName = endpoint.domain;
|
||||
listen = [
|
||||
{
|
||||
addr = "0.0.0.0";
|
||||
port = endpoint.listenPort;
|
||||
}
|
||||
];
|
||||
locations."/".proxyPass = "http://${forwardingTarget endpoint}";
|
||||
};
|
||||
}) forwardingHttpEndpoints);
|
||||
|
||||
forwardingHttpDomains = lib.unique (map (endpoint: endpoint.domain) forwardingHttpEndpoints);
|
||||
|
||||
localServiceAcmeDomains =
|
||||
lib.unique
|
||||
(map
|
||||
(hostConfig: hostConfig.domain)
|
||||
(builtins.attrValues (lib.filterAttrs (_: hostConfig: hostConfig.forceSSL) groupedProxyEndpoints)));
|
||||
|
||||
localAcmeHttpVirtualHosts = builtins.listToAttrs (map (domain: {
|
||||
name = "acme-http-${domain}-80";
|
||||
value = {
|
||||
serverName = domain;
|
||||
listen = [
|
||||
{
|
||||
addr = "0.0.0.0";
|
||||
port = 80;
|
||||
}
|
||||
];
|
||||
locations."^~ /.well-known/acme-challenge/" = {
|
||||
root = "/var/lib/acme/acme-challenge";
|
||||
extraConfig = ''
|
||||
auth_basic off;
|
||||
auth_request off;
|
||||
'';
|
||||
};
|
||||
locations."/" = {
|
||||
return = "301 https://$host$request_uri";
|
||||
};
|
||||
};
|
||||
}) (builtins.filter (domain: !(builtins.elem domain forwardingHttpDomains)) localServiceAcmeDomains));
|
||||
|
||||
virtualHosts = forwardingHttpVirtualHosts // localAcmeHttpVirtualHosts // proxyBackendVirtualHosts;
|
||||
|
||||
streamConfig = lib.concatStringsSep "\n\n" (map renderTlsServer tlsRouteMaps);
|
||||
publicListenPorts = lib.unique (map (endpoint: endpoint.listenPort) endpointsConfig);
|
||||
in
|
||||
{
|
||||
validatedEndpoints = normalizedEndpoints;
|
||||
inherit streamConfig;
|
||||
nginxUsedPorts = lib.unique (map (endpoint: endpoint.listenPort) normalizedEndpoints);
|
||||
inherit endpointsConfig forwardingEndpoints proxyEndpoints streamConfig virtualHosts proxyOffset publicListenPorts localServiceAcmeDomains;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue