130 lines
3.5 KiB
Nix
130 lines
3.5 KiB
Nix
{ lib }:
|
|
let
|
|
mkRouteOptions =
|
|
{
|
|
name ? null,
|
|
subject ? "route",
|
|
enableDefault ? true,
|
|
}:
|
|
{
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = enableDefault;
|
|
description = "Whether this reverse-proxy ${subject} is active.";
|
|
};
|
|
|
|
host = lib.mkOption (
|
|
{
|
|
type = lib.types.str;
|
|
description = "Primary hostname served by this reverse-proxy ${subject}.";
|
|
}
|
|
// lib.optionalAttrs (name != null) {
|
|
default = name;
|
|
defaultText = lib.literalMD "the route attribute name";
|
|
}
|
|
);
|
|
|
|
aliases = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
description = "Additional hostnames served by this reverse-proxy ${subject}.";
|
|
};
|
|
|
|
path = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "/";
|
|
description = "URL path prefix proxied by this reverse-proxy ${subject}.";
|
|
};
|
|
|
|
backend = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "Full HTTP backend URL that receives proxied traffic.";
|
|
};
|
|
|
|
endpoint = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
description = "Fleet network endpoint key used to derive the backend URL.";
|
|
};
|
|
|
|
port = lib.mkOption {
|
|
type = lib.types.nullOr (lib.types.ints.between 1 65535);
|
|
default = null;
|
|
example = 3923;
|
|
description = "Backend TCP port used with the fleet network endpoint.";
|
|
};
|
|
|
|
scheme = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "http";
|
|
description = "Backend URL scheme used with the fleet network endpoint.";
|
|
};
|
|
|
|
tls = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Whether to serve this reverse-proxy ${subject} with ACME-backed TLS.";
|
|
};
|
|
|
|
websockets = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Whether to enable websocket proxy headers for this reverse-proxy ${subject}.";
|
|
};
|
|
};
|
|
|
|
routeFields = route: {
|
|
inherit (route)
|
|
host
|
|
aliases
|
|
path
|
|
backend
|
|
endpoint
|
|
port
|
|
scheme
|
|
tls
|
|
websockets
|
|
;
|
|
};
|
|
|
|
endpointBackend = endpoints: route:
|
|
let
|
|
endpoint = endpoints.${route.endpoint} or (
|
|
throw "Unknown reverse-proxy endpoint `${route.endpoint}`. Known endpoints: ${lib.concatStringsSep ", " (lib.attrNames endpoints)}"
|
|
);
|
|
in
|
|
"${route.scheme}://${endpoint.address}:${toString route.port}";
|
|
|
|
resolvedRouteFields = endpoints: route:
|
|
let
|
|
routeWithBackend =
|
|
if route.backend != null then
|
|
route
|
|
else if route.endpoint != null && route.port != null then
|
|
route // { backend = endpointBackend endpoints route; }
|
|
else
|
|
throw "Reverse-proxy route `${route.host}${route.path}` needs either backend or endpoint plus port.";
|
|
in
|
|
routeFields routeWithBackend;
|
|
|
|
collectFleetRoutes =
|
|
hosts: endpoints:
|
|
lib.concatMapAttrs (
|
|
hostName: host:
|
|
lib.mapAttrs' (
|
|
routeName: route: lib.nameValuePair "${hostName}-${routeName}" (resolvedRouteFields endpoints route)
|
|
) host.config.modules.reverse-proxy.routes
|
|
) hosts;
|
|
in
|
|
{
|
|
inherit collectFleetRoutes mkRouteOptions resolvedRouteFields routeFields;
|
|
|
|
routeType = lib.types.submodule (
|
|
{ name, ... }:
|
|
{
|
|
options = mkRouteOptions { inherit name; };
|
|
}
|
|
);
|
|
}
|