feat: add known hosts

This commit is contained in:
Katharina Heidenreich 2026-04-04 16:51:21 +02:00
parent ecf10628c3
commit 3afb7d5cf4
3 changed files with 159 additions and 46 deletions

View file

@ -38,6 +38,30 @@ in
proxyWebsockets = true;
};
}
{
type = "inline";
domain = net.devices.remote_proxy.domain;
endpoint = "/.well-known/matrix/server";
force_ssl = true;
port = 443;
content = {
contentType = "application/json";
status = 200;
body = ''{"m.server":"${net.devices.remote_proxy.domain}:443"}'';
};
}
{
type = "inline";
domain = net.devices.remote_proxy.domain;
endpoint = "/.well-known/matrix/client";
force_ssl = true;
port = 443;
content = {
contentType = "application/json";
status = 200;
body = ''{"m.homeserver":{"base_url":"https://${net.devices.remote_proxy.domain}"}}'';
};
}
{
type = "proxy";
domain = "torrent.${net.local_domain}";

View file

@ -205,6 +205,33 @@ let
proxyWebsockets = route.content.proxyWebsockets;
};
}
else if route.type == "inline" then
let
inlineBody =
if builtins.isString route.content then
route.content
else
route.content.body;
inlineStatus =
if builtins.isAttrs route.content && route.content ? status then
route.content.status
else
200;
inlineContentType =
if builtins.isAttrs route.content && route.content ? contentType then
route.content.contentType
else
"text/plain; charset=utf-8";
in
{
name = "= ${route.endpoint}";
value = {
return = "${toString inlineStatus} ${builtins.toJSON inlineBody}";
extraConfig = ''
default_type ${inlineContentType};
'';
};
}
else
let
statusValue =
@ -284,10 +311,43 @@ let
value = base // exposureConfig // sslConfig;
};
virtualHostsData = builtins.listToAttrs (lib.mapAttrsToList mkVirtualHost groupedByHost);
baseVirtualHostsData = builtins.listToAttrs (lib.mapAttrsToList mkVirtualHost groupedByHost);
tlsDomains =
lib.unique (map (route: route.domain) (lib.filter (route: route.force_ssl) mappedEndpoints));
mkRedirectVhost = domain: {
name = "redirect_${sanitizeHostKey domain}_80";
value = {
serverName = domain;
listen = [
{
addr = "0.0.0.0";
port = 80;
}
];
locations."/" = {
return = "301 https://$host$request_uri";
};
locations."^~ /.well-known/acme-challenge/" = {
root = "/var/lib/acme/acme-challenge";
extraConfig = ''
auth_basic off;
auth_request off;
'';
};
};
};
redirectVirtualHostsData = builtins.listToAttrs (map mkRedirectVhost tlsDomains);
virtualHostsData = baseVirtualHostsData // redirectVirtualHostsData;
nginxUsedPorts =
lib.unique (map (route: route.port) mappedEndpoints);
lib.unique (
(map (route: route.port) mappedEndpoints)
++ lib.optional (tlsDomains != []) 80
);
acmeDomains =
lib.unique (map (route: route.domain) (lib.filter (route: route.force_ssl) mappedEndpoints));

View file

@ -5,6 +5,7 @@ let
allowedProxyContentKeys = [ "type" "ip" "port" "proxyWebsockets" ];
allowedWebContentKeys = [ "type" "files" ];
allowedWebFileKeys = [ "path" "filePath" "contentType" "status" ];
allowedInlineContentKeys = [ "body" "contentType" "status" ];
ensureNoUnknownKeys = context: obj: allowedKeys:
let
@ -37,10 +38,10 @@ let
else
throw "Endpoint at index ${toString index} must define type as a string.";
_type =
if lib.elem typeValue [ "proxy" "web" ] then
if lib.elem typeValue [ "proxy" "web" "inline" ] then
null
else
throw "Endpoint at index ${toString index} type must be 'proxy' or 'web'.";
throw "Endpoint at index ${toString index} type must be 'proxy', 'web', or 'inline'.";
_domain =
if endpoint ? domain && builtins.isString endpoint.domain && endpoint.domain != "" then
null
@ -62,13 +63,14 @@ let
else
throw "Endpoint at index ${toString index} must define force_ssl as a bool.";
contentValue =
if endpoint ? content && builtins.isAttrs endpoint.content then
if endpoint ? content then
endpoint.content
else
throw "Endpoint at index ${toString index} must define content as an attrset.";
throw "Endpoint at index ${toString index} must define content.";
_content =
if typeValue == "proxy" then
let
_attrs = if builtins.isAttrs contentValue then null else throw "Proxy endpoint at index ${toString index} must define content as an attrset.";
____ = ensureNoUnknownKeys "Proxy content at endpoint index ${toString index}" contentValue allowedProxyContentKeys;
in
if !(contentValue ? type) || !builtins.isString contentValue.type then
@ -82,7 +84,9 @@ let
else
null
else
if typeValue == "web" then
let
_attrs = if builtins.isAttrs contentValue then null else throw "Web endpoint at index ${toString index} must define content as an attrset.";
____ = ensureNoUnknownKeys "Web content at endpoint index ${toString index}" contentValue allowedWebContentKeys;
filesValue =
if contentValue ? files && builtins.isList contentValue.files then
@ -126,7 +130,32 @@ let
file
) filesValue;
in
null;
null
else
if builtins.isString contentValue then
null
else if builtins.isAttrs contentValue then
let
____ = ensureNoUnknownKeys "Inline content at endpoint index ${toString index}" contentValue allowedInlineContentKeys;
_____ =
if contentValue ? body && builtins.isString contentValue.body then
null
else
throw "Inline endpoint at index ${toString index} must define content.body as a string when content is an attrset.";
______ =
if !(contentValue ? contentType) || (builtins.isString contentValue.contentType && contentValue.contentType != "") then
null
else
throw "Inline endpoint at index ${toString index} content.contentType must be a non-empty string when provided.";
_______ =
if !(contentValue ? status) || builtins.isInt contentValue.status then
null
else
throw "Inline endpoint at index ${toString index} content.status must be an int when provided.";
in
null
else
throw "Inline endpoint at index ${toString index} must define content as a string or an attrset.";
in
endpoint;