blob: e3179096c3629d8da503fbf3494af1e699351e52 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
{ lib, sysConfig, config, pkgs, ... }:
let
cfg = config.services.autosshProxy;
in {
options = {
services.autosshProxy = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, config, ... }: {
options = {
port = lib.mkOption {
type = lib.types.port;
};
socksPort = lib.mkOption {
type = lib.types.port;
default = config.port - 1;
};
host = lib.mkOption {
type = lib.types.str;
default = name;
};
sshpassSecret = lib.mkOption {
type = lib.types.nullOr lib.types.str;
};
};
}));
};
};
config = {
assertions = [
{
assertion = builtins.length (lib.unique (lib.concatMap (cfg: [cfg.port cfg.socksPort]) (builtins.attrValues cfg))) == builtins.length (builtins.attrValues cfg) * 2;
message = "autosshProxy ports are not unique";
}
];
systemd.user.services = lib.mkMerge (map (cfg: {
"autossh-socks@${cfg.host}:${toString cfg.socksPort}" = {
Service = {
Type = "notify";
NotifyAccess = "all";
WorkingDirectory = "~";
Restart = "always";
RestartSec = "23s";
ExecStart = "${pkgs.writeScript "autossh" ''
#!${lib.getExe config.programs.zsh.package} -xe
host="''${1%:*}"
port="''${1#*:}"
typeset -a cmd
cmd=()
if [[ -n "''${SSHPASS_SECRET}" ]]; then
cmd+=(${lib.getExe' pkgs.sshpassSecret "sshpass-secret"})
cmd+=("''${(@s/:/)SSHPASS_SECRET}")
cmd+=(--)
fi
cmd+=(${lib.getExe' pkgs.openssh "ssh"} -vN -D 127.0.0.1:''${port} -o ControlPath=none -o ExitOnForwardFailure=yes -o ServerAliveCountMax=15 -o ServerAliveInterval=2 "''${host}")
( exec -a "''${cmd[1]}" -- ''${cmd} ) &
pid=$!
newpid=""
i=200
while ! { newpid=$(${lib.getExe' pkgs.iproute2 "ss"} -HO -pln "src localhost sport ''${port}" | ${lib.getExe pkgs.gnused} -r 's/^.*pid=([0-9]+).*$/\1/'); [[ -n $newpid ]] }; do
if ! kill -0 "''${pid}"; then
wait "''${pid}"
exit $?
fi
[[ "''${i}" -gt 0 ]] || exit 1
i=$((''${i} - 1))
${lib.getExe' pkgs.coreutils "sleep"} 0.1
done
${lib.getExe' sysConfig.systemd.package "systemd-notify"} --pid=''${newpid} --ready
''} \"%I\"";
Environment = lib.optional (cfg.sshpassSecret != null) "SSHPASS_SECRET=${cfg.sshpassSecret}";
};
Unit = {
StopWhenUnneeded = true;
StartLimitInterval = "180s";
StartLimitBurst = 7;
};
};
"proxy-to-autossh-socks@${toString cfg.port}" = {
Unit = {
BindsTo = ["autossh-socks@${cfg.host}:${toString cfg.socksPort}.service" "proxy-to-autossh-socks@${toString cfg.port}.socket"];
After = ["autossh-socks@${cfg.host}:${toString cfg.socksPort}.service" "proxy-to-autossh-socks@${toString cfg.port}.socket"];
};
Service = {
ExecStart = "${sysConfig.systemd.package}/lib/systemd/systemd-socket-proxyd --exit-idle-time=60s 127.0.0.1:${toString cfg.socksPort}";
Restart = "always";
RestartSec = "23s";
};
};
}) (builtins.attrValues cfg));
systemd.user.sockets = builtins.listToAttrs (map (cfg: lib.nameValuePair "proxy-to-autossh-socks@${toString cfg.port}" {
Socket = {
ListenStream = "%I";
TriggerLimitIntervalSec = 0;
PollLimitIntervalSec = "180s";
PollLimitBurst = 6;
};
Install = {
WantedBy = ["sockets.target"];
};
}) (builtins.attrValues cfg));
};
}
|