let lib = import ; net = import ../config/network.nix; end = import ../config/endpoints.nix; endpointValidation = import ../validation/endpoints.nix; autoSshValidation = import ../validation/auto_ssh.nix; endpoints = endpointValidation.validateEndpointsShape end; devices = autoSshValidation.getDevices net; autoSshDevices = autoSshValidation.getAutoSshDevices devices; matchesDomain = endpointDomain: remoteDomain: if builtins.isString endpointDomain && builtins.isString remoteDomain then endpointDomain == remoteDomain || lib.hasSuffix ".${remoteDomain}" endpointDomain else throw "Endpoint and remote domains must be strings."; getRemotePortMap = device: autoSshValidation.getRemotePortMap device; resolveRemotePort = remotePortMap: endpoint: let localPort = if endpoint ? port then endpoint.port else throw "Endpoint is missing required field: port."; overrides = lib.filter (entry: entry.localPort == localPort) remotePortMap; in if overrides != [] then (builtins.head overrides).remotePort else localPort; mapEndpointToForward = remotePortMap: endpoint: { remote = resolveRemotePort remotePortMap endpoint; localAddress = "localhost"; localPort = endpoint.port; }; endpointForHttpRedirect = endpoint: endpoint // { port = 80; }; portsByRemote = lib.mapAttrs (_: device: let remoteDomain = if device ? domain then device.domain else throw "Auto SSH device is missing required field: domain."; remotePortMap = getRemotePortMap device; matchedEndpoints = lib.filter (endpoint: if endpoint.force_ssl && endpoint.port == 80 then throw "Endpoint '${endpoint.domain}${endpoint.endpoint}' cannot use force_ssl=true on port 80." else if endpoint.type == "proxy" && endpoint.content.type != "service" then throw "Proxy endpoint '${endpoint.domain}${endpoint.endpoint}' must use content.type = 'service'." else matchesDomain endpoint.domain remoteDomain ) endpoints; forwards = lib.concatMap (endpoint: let baseForward = mapEndpointToForward remotePortMap endpoint; httpRedirectForward = mapEndpointToForward remotePortMap (endpointForHttpRedirect endpoint); in if endpoint.force_ssl then [ baseForward httpRedirectForward ] else [ baseForward ] ) matchedEndpoints; in lib.unique forwards ) autoSshDevices; in rec { inherit portsByRemote; }