Start ssh-agent as a user unit

This has some advantages:

* You get ssh-agent regardless of how you logged in. Previously it was
  only started for X11 sessions.

* All sessions of a user share the same agent. So if you added a key
  on tty1, it will also be available on tty2.

* Systemd will restart ssh-agent if it dies.

* $SSH_AUTH_SOCK now points to the /run/user/<uid> directory, which is
  more secure than /tmp.

For bonus points, we should patch ssh-agent to support socket-based
activation...
This commit is contained in:
Eelco Dolstra 2014-04-18 00:45:26 +02:00
parent e34a1589fe
commit ffedee6ed5
5 changed files with 38 additions and 26 deletions

View file

@ -36,7 +36,7 @@ with lib;
# GNU lsh.
services.openssh.enable = false;
services.lshd.enable = true;
services.xserver.startOpenSSHAgent = false;
programs.ssh.startAgent = false;
services.xserver.startGnuPGAgent = true;
# TODO: GNU dico.

View file

@ -47,7 +47,20 @@ in
for help.
'';
};
startAgent = mkOption {
type = types.bool;
default = true;
description = ''
Whether to start the OpenSSH agent when you log in. The OpenSSH agent
remembers private keys for you so that you don't have to type in
passphrases every time you make an SSH connection. Use
<command>ssh-add</command> to add a key to the agent.
'';
};
};
};
config = {
@ -71,5 +84,25 @@ in
target = "ssh/ssh_config";
}
];
# FIXME: this should really be socket-activated for über-awesomeness.
systemd.user.services.ssh-agent =
{ enable = cfg.startAgent;
description = "SSH Agent";
wantedBy = [ "default.target" ];
serviceConfig =
{ ExecStart = "${pkgs.openssh}/bin/ssh-agent -a %t/ssh-agent";
Type = "forking";
Restart = "on-failure";
};
};
environment.extraInit = optionalString cfg.startAgent
''
if [ -z "$SSH_AUTH_SOCK" -a -n "$XDG_RUNTIME_DIR" ]; then
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent"
fi
'';
};
}

View file

@ -103,6 +103,7 @@ in zipModules ([]
++ obsolete [ "services" "sshd" "gatewayPorts" ] [ "services" "openssh" "gatewayPorts" ]
++ obsolete [ "services" "sshd" "permitRootLogin" ] [ "services" "openssh" "permitRootLogin" ]
++ obsolete [ "services" "xserver" "startSSHAgent" ] [ "services" "xserver" "startOpenSSHAgent" ]
++ obsolete [ "services" "xserver" "startOpenSSHAgent" ] [ "programs" "ssh" "startAgent" ]
++ obsolete [ "services" "xserver" "windowManager" "xbmc" ] [ "services" "xserver" "desktopManager" "xbmc" ]
# KDE

View file

@ -51,17 +51,6 @@ let
''}
${optionalString cfg.startOpenSSHAgent ''
if test -z "$SSH_AUTH_SOCK"; then
# Restart this script as a child of the SSH agent. (It is
# also possible to start the agent as a child that prints
# the required environment variabled on stdout, but in
# that mode ssh-agent is not terminated when we log out.)
export SSH_ASKPASS=${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass
exec ${pkgs.openssh}/bin/ssh-agent "$0" "$sessionType"
fi
''}
${optionalString cfg.startGnuPGAgent ''
if test -z "$SSH_AUTH_SOCK"; then
# Restart this script as a child of the GnuPG agent.

View file

@ -201,17 +201,6 @@ in
'';
};
startOpenSSHAgent = mkOption {
type = types.bool;
default = true;
description = ''
Whether to start the OpenSSH agent when you log in. The OpenSSH agent
remembers private keys for you so that you don't have to type in
passphrases every time you make an SSH connection. Use
<command>ssh-add</command> to add a key to the agent.
'';
};
startGnuPGAgent = mkOption {
type = types.bool;
default = false;
@ -400,11 +389,11 @@ in
hardware.opengl.videoDrivers = mkIf (cfg.videoDriver != null) [ cfg.videoDriver ];
assertions =
[ { assertion = !(cfg.startOpenSSHAgent && cfg.startGnuPGAgent);
[ { assertion = !(config.programs.ssh.startAgent && cfg.startGnuPGAgent);
message =
''
The OpenSSH agent and GnuPG agent cannot be started both.
Choose between `startOpenSSHAgent' and `startGnuPGAgent'.
The OpenSSH agent and GnuPG agent cannot be started both. Please
choose between programs.ssh.startAgent and services.xserver.startGnuPGAgent.
'';
}
{ assertion = config.security.polkit.enable;