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...

Changed files
+38 -26
nixos
modules
config
programs
services
x11
display-managers
+1 -1
nixos/modules/config/gnu.nix
···
# 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.
+33
nixos/modules/programs/ssh.nix
···
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 = {
···
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
+
'';
+
};
}
+1
nixos/modules/rename.nix
···
++ 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
-11
nixos/modules/services/x11/display-managers/default.nix
···
''}
-
${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.
+3 -14
nixos/modules/services/x11/xserver.nix
···
'';
};
-
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;
···
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;