summary refs log tree commit diff
path: root/nixos/modules/services/networking/autossh.nix
blob: 245f2bfc2cf3856ee386c59c54a93332cba0d24b (plain) (blame)
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
{ config, lib, pkgs, ... }:

with lib;

let

  cfg = config.services.autossh;

in

{

  ###### interface

  options = {

    services.autossh = {

      sessions = mkOption {
        type = types.listOf (types.submodule {
          options = {
            name = mkOption {
              type = types.str;
              example = "socks-peer";
              description = "Name of the local AutoSSH session";
            };
            user = mkOption {
              type = types.str;
              example = "bill";
              description = "Name of the user the AutoSSH session should run as";
            };
            monitoringPort = mkOption {
              type = types.int;
              default = 0;
              example = 20000;
              description = ''
                Port to be used by AutoSSH for peer monitoring. Note, that
                AutoSSH also uses mport+1. Value of 0 disables the keep-alive
                style monitoring
              '';
            };
            extraArguments = mkOption {
              type = types.separatedString " ";
              example = "-N -D4343 bill@socks.example.net";
              description = ''
                Arguments to be passed to AutoSSH and retransmitted to SSH
                process. Some meaningful options include -N (don't run remote
                command), -D (open SOCKS proxy on local port), -R (forward
                remote port), -L (forward local port), -v (Enable debug). Check
                ssh manual for the complete list.
              '';
            };
          };
        });

        default = [];
        description = ''
          List of AutoSSH sessions to start as systemd services. Each service is
          named 'autossh-{session.name}'.
        '';

        example = [
          {
            name="socks-peer";
            user="bill";
            monitoringPort = 20000;
            extraArguments="-N -D4343 billremote@socks.host.net";
          }
        ];

      };
    };

  };

  ###### implementation

  config = mkIf (cfg.sessions != []) {

    systemd.services =

      lib.foldr ( s : acc : acc //
        {
          "autossh-${s.name}" =
            let
              mport = if s ? monitoringPort then s.monitoringPort else 0;
            in
            {
              description = "AutoSSH session (" + s.name + ")";

              after = [ "network.target" ];
              wantedBy = [ "multi-user.target" ];

              # To be able to start the service with no network connection
              environment.AUTOSSH_GATETIME="0";

              # How often AutoSSH checks the network, in seconds
              environment.AUTOSSH_POLL="30";

              serviceConfig = {
                  User = "${s.user}";
                  # AutoSSH may exit with 0 code if the SSH session was
                  # gracefully terminated by either local or remote side.
                  Restart = "on-success";
                  ExecStart = "${pkgs.autossh}/bin/autossh -M ${toString mport} ${s.extraArguments}";
              };
            };
        }) {} cfg.sessions;

    environment.systemPackages = [ pkgs.autossh ];

  };
}