feat: add port offset handling for auto SSH devices

This commit is contained in:
Katharina Heidenreich 2026-04-04 19:45:40 +02:00
parent 2c1316a0a6
commit 3385709208
3 changed files with 34 additions and 9 deletions

View file

@ -36,6 +36,7 @@ rec {
sshUser = "root"; sshUser = "root";
key = secrets.byName.autossh_remote_proxy_key.path; key = secrets.byName.autossh_remote_proxy_key.path;
known_hosts = secrets.byName.autossh_remote_proxy_known_hosts.path; known_hosts = secrets.byName.autossh_remote_proxy_known_hosts.path;
portOffset = 10000;
}; };
}; };
}; };

View file

@ -19,22 +19,31 @@ let
getRemotePortMap = device: getRemotePortMap = device:
autoSshValidation.getRemotePortMap device; autoSshValidation.getRemotePortMap device;
resolveRemotePort = remotePortMap: endpoint: getPortOffset = device:
autoSshValidation.getPortOffset device;
ensurePortRange = context: port:
if builtins.isInt port && port >= 1 && port <= 65535 then
port
else
throw "${context} must be in range 1..65535.";
resolveRemotePort = remotePortMap: portOffset: endpoint:
let let
localPort = localPort =
if endpoint ? port then if endpoint ? port then
endpoint.port ensurePortRange "Endpoint port '${toString endpoint.port}'" endpoint.port
else else
throw "Endpoint is missing required field: port."; throw "Endpoint is missing required field: port.";
overrides = lib.filter (entry: entry.localPort == localPort) remotePortMap; overrides = lib.filter (entry: entry.localPort == localPort) remotePortMap;
in in
if overrides != [] then if overrides != [] then
(builtins.head overrides).remotePort ensurePortRange "remotePortMap remotePort '${toString (builtins.head overrides).remotePort}'" (builtins.head overrides).remotePort
else else
localPort; ensurePortRange "Computed remote port (local ${toString localPort} + offset ${toString portOffset})" (localPort + portOffset);
mapEndpointToForward = remotePortMap: endpoint: { mapEndpointToForward = remotePortMap: portOffset: endpoint: {
remote = resolveRemotePort remotePortMap endpoint; remote = resolveRemotePort remotePortMap portOffset endpoint;
localAddress = "localhost"; localAddress = "localhost";
localPort = endpoint.port; localPort = endpoint.port;
}; };
@ -50,6 +59,7 @@ let
else else
throw "Auto SSH device is missing required field: domain."; throw "Auto SSH device is missing required field: domain.";
remotePortMap = getRemotePortMap device; remotePortMap = getRemotePortMap device;
portOffset = getPortOffset device;
matchedEndpoints = matchedEndpoints =
lib.filter (endpoint: lib.filter (endpoint:
if endpoint.force_ssl && endpoint.port == 80 then if endpoint.force_ssl && endpoint.port == 80 then
@ -61,8 +71,8 @@ let
) endpoints; ) endpoints;
forwards = lib.concatMap (endpoint: forwards = lib.concatMap (endpoint:
let let
baseForward = mapEndpointToForward remotePortMap endpoint; baseForward = mapEndpointToForward remotePortMap portOffset endpoint;
httpRedirectForward = mapEndpointToForward remotePortMap (endpointForHttpRedirect endpoint); httpRedirectForward = mapEndpointToForward remotePortMap portOffset (endpointForHttpRedirect endpoint);
in in
if endpoint.force_ssl then if endpoint.force_ssl then
[ baseForward httpRedirectForward ] [ baseForward httpRedirectForward ]

View file

@ -53,9 +53,23 @@ let
else else
device.auto_ssh.remotePortMap; device.auto_ssh.remotePortMap;
getPortOffset = device:
if !(device ? auto_ssh) then
0
else if !builtins.isAttrs device.auto_ssh then
throw "Device auto_ssh must be an attrset when present."
else if !(device.auto_ssh ? portOffset) then
0
else if !builtins.isInt device.auto_ssh.portOffset then
throw "Device auto_ssh.portOffset must be an int."
else if device.auto_ssh.portOffset < 0 then
throw "Device auto_ssh.portOffset must be >= 0."
else
device.auto_ssh.portOffset;
isSafeName = name: isSafeName = name:
builtins.match "^[a-z_][a-z0-9_-]*$" name != null; builtins.match "^[a-z_][a-z0-9_-]*$" name != null;
in in
{ {
inherit getDevices getAutoSshDevices getAutoSshDomains getAutoSshConfig getRemotePortMap isSafeName; inherit getDevices getAutoSshDevices getAutoSshDomains getAutoSshConfig getRemotePortMap getPortOffset isSafeName;
} }