feat: try rework
This commit is contained in:
parent
1ddbd3b8b6
commit
ecf10628c3
51 changed files with 1941 additions and 445 deletions
|
|
@ -1,57 +1,145 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
net = import ../data/network.nix;
|
||||
serv = import ../data/services.nix;
|
||||
net = import ../config/network.nix;
|
||||
rem = import ../intermediate/remote.nix;
|
||||
autoSshValidation = import ../validation/auto_ssh.nix;
|
||||
|
||||
autoForwards = map (port: {
|
||||
remote = port;
|
||||
localAddress = "localhost";
|
||||
localPort = port;
|
||||
}) net.usedPorts;
|
||||
fordwards = lib.unique (serv.autossh.forwards ++ autoForwards);
|
||||
devices = autoSshValidation.getDevices net;
|
||||
|
||||
forwardStrings = map (port: "-R ${toString port.remote}:${port.localAddress}:${toString port.localPort}") fordwards;
|
||||
forwardString = builtins.concatStringsSep " " forwardStrings;
|
||||
portsByRemote =
|
||||
if rem ? portsByRemote && builtins.isAttrs rem.portsByRemote then
|
||||
rem.portsByRemote
|
||||
else
|
||||
throw "intermediate/remote.nix must export portsByRemote as an attrset.";
|
||||
|
||||
sshHost = net.services.remoteProxy.ip;
|
||||
sshPort = 22;
|
||||
sshUser = "root";
|
||||
sshKeyPath = serv.autossh.key_path;
|
||||
trustedHostsFile = serv.autossh.known_hosts;
|
||||
autoSshDevices = autoSshValidation.getAutoSshDevices devices;
|
||||
|
||||
getAutoSsh = deviceName: device:
|
||||
autoSshValidation.getAutoSshConfig deviceName device;
|
||||
|
||||
validateForwards = deviceName: forwards:
|
||||
if !builtins.isList forwards then
|
||||
throw "portsByRemote.${deviceName} must be a list of forward objects."
|
||||
else if !lib.all (forward:
|
||||
builtins.isAttrs forward
|
||||
&& forward ? remote
|
||||
&& forward ? localAddress
|
||||
&& forward ? localPort
|
||||
&& builtins.isInt forward.remote
|
||||
&& builtins.isString forward.localAddress
|
||||
&& builtins.isInt forward.localPort
|
||||
) forwards then
|
||||
throw "Each forward in portsByRemote.${deviceName} must be { remote = int; localAddress = string; localPort = int; }."
|
||||
else
|
||||
forwards;
|
||||
|
||||
getForwards = deviceName:
|
||||
if portsByRemote ? ${deviceName} then
|
||||
validateForwards deviceName portsByRemote.${deviceName}
|
||||
else
|
||||
throw "Missing mapped forwards for auto_ssh device '${deviceName}' in intermediate/remote.nix portsByRemote.";
|
||||
|
||||
enabledAutoSshDevices =
|
||||
lib.filterAttrs (deviceName: device:
|
||||
let
|
||||
_ =
|
||||
if autoSshValidation.isSafeName deviceName then
|
||||
null
|
||||
else
|
||||
throw "Auto SSH device name '${deviceName}' is not safe for Linux user/systemd names. Use lowercase letters, numbers, '_' or '-' and start with a letter or '_'.";
|
||||
autoSsh = getAutoSsh deviceName device;
|
||||
in
|
||||
if !(autoSsh ? enable) then
|
||||
throw "Auto SSH device '${deviceName}' is missing required field: auto_ssh.enable."
|
||||
else if !builtins.isBool autoSsh.enable then
|
||||
throw "Auto SSH device '${deviceName}' field auto_ssh.enable must be a bool."
|
||||
else
|
||||
autoSsh.enable
|
||||
) autoSshDevices;
|
||||
|
||||
getField = deviceName: autoSsh: fieldName: typeCheck: typeName:
|
||||
if !(autoSsh ? ${fieldName}) then
|
||||
throw "Auto SSH device '${deviceName}' is missing required field: auto_ssh.${fieldName}."
|
||||
else if !typeCheck autoSsh.${fieldName} then
|
||||
throw "Auto SSH device '${deviceName}' field auto_ssh.${fieldName} must be ${typeName}."
|
||||
else
|
||||
autoSsh.${fieldName};
|
||||
|
||||
mkForwardString = forwards:
|
||||
builtins.concatStringsSep " " (map (forward:
|
||||
"-R ${toString forward.remote}:${forward.localAddress}:${toString forward.localPort}"
|
||||
) forwards);
|
||||
|
||||
mkService = deviceName: device:
|
||||
let
|
||||
autoSsh = getAutoSsh deviceName device;
|
||||
sshHost =
|
||||
if device ? ip && builtins.isString device.ip then
|
||||
device.ip
|
||||
else
|
||||
throw "Auto SSH device '${deviceName}' must define ip as string.";
|
||||
sshPort = getField deviceName autoSsh "sshPort" builtins.isInt "an int";
|
||||
sshUser = getField deviceName autoSsh "sshUser" builtins.isString "a string";
|
||||
sshKeyPath = getField deviceName autoSsh "key" (value: builtins.isString value || builtins.isPath value) "a string or path";
|
||||
trustedHostsFile = getField deviceName autoSsh "known_hosts" (value: builtins.isString value || builtins.isPath value) "a string or path";
|
||||
forwards = getForwards deviceName;
|
||||
_ = if forwards == [] then throw "Auto SSH device '${deviceName}' has no mapped forwards. Add matching endpoints or disable this remote." else null;
|
||||
forwardString = mkForwardString forwards;
|
||||
serviceName = "autossh-${deviceName}";
|
||||
in {
|
||||
name = serviceName;
|
||||
value = {
|
||||
description = "AutoSSH reverse tunnel for ${deviceName}";
|
||||
after = [ "network.target" "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = serviceName;
|
||||
Restart = "always";
|
||||
RestartSec = 10;
|
||||
|
||||
ExecStart = ''
|
||||
${pkgs.autossh}/bin/autossh \
|
||||
-N \
|
||||
-T \
|
||||
-M 0 \
|
||||
-o ServerAliveInterval=10 \
|
||||
-o ExitOnForwardFailure=yes \
|
||||
-o UserKnownHostsFile=${trustedHostsFile} \
|
||||
${forwardString} \
|
||||
-i ${sshKeyPath} \
|
||||
-p ${toString sshPort} \
|
||||
${sshUser}@${sshHost}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
generatedServices = builtins.listToAttrs (lib.mapAttrsToList mkService enabledAutoSshDevices);
|
||||
|
||||
generatedUsers = builtins.listToAttrs (lib.mapAttrsToList (deviceName: _: {
|
||||
name = "autossh-${deviceName}";
|
||||
value = {
|
||||
isSystemUser = true;
|
||||
group = "autossh-${deviceName}";
|
||||
extraGroups = [ "keys" ];
|
||||
description = "AutoSSH user for ${deviceName}";
|
||||
};
|
||||
}) enabledAutoSshDevices);
|
||||
|
||||
generatedGroups = builtins.listToAttrs (lib.mapAttrsToList (deviceName: _: {
|
||||
name = "autossh-${deviceName}";
|
||||
value = {};
|
||||
}) enabledAutoSshDevices);
|
||||
in
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
autossh
|
||||
moreutils
|
||||
];
|
||||
|
||||
systemd.services.autossh-tunnel = {
|
||||
description = "Autossh Reverse SSH Tunnel";
|
||||
after = [ "network.target" "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "autossh-tunnel";
|
||||
Restart = "always";
|
||||
RestartSec = 10;
|
||||
|
||||
ExecStart = ''
|
||||
${pkgs.autossh}/bin/autossh \
|
||||
-N \
|
||||
-T \
|
||||
-M 0 \
|
||||
-o ServerAliveInterval=10 \
|
||||
-o ExitOnForwardFailure=yes \
|
||||
-o UserKnownHostsFile=${trustedHostsFile} \
|
||||
${forwardString} \
|
||||
-i ${sshKeyPath} \
|
||||
-p ${toString sshPort} \
|
||||
${sshUser}@${sshHost}
|
||||
'';
|
||||
};
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
}
|
||||
users.users = generatedUsers;
|
||||
users.groups = generatedGroups;
|
||||
systemd.services = generatedServices;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue