1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8
9 cfg = config.services.autossh;
10
11in
12
13{
14
15 ###### interface
16
17 options = {
18
19 services.autossh = {
20
21 sessions = lib.mkOption {
22 type = lib.types.listOf (
23 lib.types.submodule {
24 options = {
25 name = lib.mkOption {
26 type = lib.types.str;
27 example = "socks-peer";
28 description = "Name of the local AutoSSH session";
29 };
30 user = lib.mkOption {
31 type = lib.types.str;
32 example = "bill";
33 description = "Name of the user the AutoSSH session should run as";
34 };
35 monitoringPort = lib.mkOption {
36 type = lib.types.int;
37 default = 0;
38 example = 20000;
39 description = ''
40 Port to be used by AutoSSH for peer monitoring. Note, that
41 AutoSSH also uses mport+1. Value of 0 disables the keep-alive
42 style monitoring
43 '';
44 };
45 extraArguments = lib.mkOption {
46 type = lib.types.separatedString " ";
47 example = "-N -D4343 bill@socks.example.net";
48 description = ''
49 Arguments to be passed to AutoSSH and retransmitted to SSH
50 process. Some meaningful options include -N (don't run remote
51 command), -D (open SOCKS proxy on local port), -R (forward
52 remote port), -L (forward local port), -v (Enable debug). Check
53 ssh manual for the complete list.
54 '';
55 };
56 };
57 }
58 );
59
60 default = [ ];
61 description = ''
62 List of AutoSSH sessions to start as systemd services. Each service is
63 named 'autossh-{session.name}'.
64 '';
65
66 example = [
67 {
68 name = "socks-peer";
69 user = "bill";
70 monitoringPort = 20000;
71 extraArguments = "-N -D4343 billremote@socks.host.net";
72 }
73 ];
74
75 };
76 };
77
78 };
79
80 ###### implementation
81
82 config = lib.mkIf (cfg.sessions != [ ]) {
83
84 systemd.services =
85
86 lib.foldr (
87 s: acc:
88 acc
89 // {
90 "autossh-${s.name}" =
91 let
92 mport = if s ? monitoringPort then s.monitoringPort else 0;
93 in
94 {
95 description = "AutoSSH session (" + s.name + ")";
96
97 after = [ "network.target" ];
98 wantedBy = [ "multi-user.target" ];
99
100 # To be able to start the service with no network connection
101 environment.AUTOSSH_GATETIME = "0";
102
103 # How often AutoSSH checks the network, in seconds
104 environment.AUTOSSH_POLL = "30";
105
106 serviceConfig = {
107 User = "${s.user}";
108 # AutoSSH may exit with 0 code if the SSH session was
109 # gracefully terminated by either local or remote side.
110 Restart = "on-success";
111 ExecStart = "${pkgs.autossh}/bin/autossh -M ${toString mport} ${s.extraArguments}";
112 };
113 };
114 }
115 ) { } cfg.sessions;
116
117 environment.systemPackages = [ pkgs.autossh ];
118
119 };
120}