sshd: Add support for socket activation

By enabling ‘services.openssh.startWhenNeeded’, sshd is started
on-demand by systemd using socket activation. This is particularly
useful if you have a zillion containers and don't want to have sshd
running permanently. Note that socket activation is not noticeable
slower, contrary to what the manpage for ‘sshd -i’ says, so we might
want to make this the default one day.
This commit is contained in:
Eelco Dolstra 2014-04-22 16:07:53 +02:00
parent 83b43cfe51
commit 03d9e5cda0
2 changed files with 59 additions and 23 deletions

View File

@ -86,6 +86,16 @@ in
''; '';
}; };
startWhenNeeded = mkOption {
type = types.bool;
default = false;
description = ''
If set, <command>sshd</command> is socket-activated; that
is, instead of having it permanently running as a daemon,
systemd will start an instance for each incoming connection.
'';
};
forwardX11 = mkOption { forwardX11 = mkOption {
type = types.bool; type = types.bool;
default = cfgc.setXAuthLocation; default = cfgc.setXAuthLocation;
@ -248,37 +258,60 @@ in
} }
]; ];
systemd.services.sshd = systemd =
{ description = "SSH Daemon"; let
service =
{ description = "SSH Daemon";
wantedBy = [ "multi-user.target" ]; wantedBy = optional (!cfg.startWhenNeeded) "multi-user.target";
stopIfChanged = false; stopIfChanged = false;
path = [ pkgs.openssh pkgs.gawk ]; path = [ pkgs.openssh pkgs.gawk ];
environment.LD_LIBRARY_PATH = nssModulesPath; environment.LD_LIBRARY_PATH = nssModulesPath;
preStart = preStart =
'' ''
mkdir -m 0755 -p /etc/ssh mkdir -m 0755 -p /etc/ssh
${flip concatMapStrings cfg.hostKeys (k: '' ${flip concatMapStrings cfg.hostKeys (k: ''
if ! [ -f "${k.path}" ]; then if ! [ -f "${k.path}" ]; then
ssh-keygen -t "${k.type}" -b "${toString k.bits}" -f "${k.path}" -N "" ssh-keygen -t "${k.type}" -b "${toString k.bits}" -f "${k.path}" -N ""
fi fi
'')} '')}
''; '';
serviceConfig = serviceConfig =
{ ExecStart = { ExecStart =
"${pkgs.openssh}/sbin/sshd " + "${pkgs.openssh}/sbin/sshd " + (optionalString cfg.startWhenNeeded "-i ") +
"-f ${pkgs.writeText "sshd_config" cfg.extraConfig}"; "-f ${pkgs.writeText "sshd_config" cfg.extraConfig}";
Restart = "always"; KillMode = "process";
Type = "forking"; } // (if cfg.startWhenNeeded then {
KillMode = "process"; StandardInput = "socket";
PIDFile = "/run/sshd.pid"; } else {
Restart = "always";
Type = "forking";
PIDFile = "/run/sshd.pid";
});
}; };
in
if cfg.startWhenNeeded then {
sockets.sshd =
{ description = "SSH Socket";
wantedBy = [ "sockets.target" ];
socketConfig.ListenStream = cfg.ports;
socketConfig.Accept = true;
};
services."sshd@" = service;
} else {
services.sshd = service;
}; };
networking.firewall.allowedTCPPorts = cfg.ports; networking.firewall.allowedTCPPorts = cfg.ports;

View File

@ -12,6 +12,9 @@ with lib;
networking.useHostResolvConf = true; networking.useHostResolvConf = true;
# Containers should be light-weight, so start sshd on demand.
services.openssh.startWhenNeeded = mkDefault true;
# Shut up warnings about not having a boot loader. # Shut up warnings about not having a boot loader.
system.build.installBootLoader = "${pkgs.coreutils}/bin/true"; system.build.installBootLoader = "${pkgs.coreutils}/bin/true";