PR #9420 added set-SSH_AUTH_SOCK.service and ordered it before sshAuthSock.systemd.socketProviderUnit. When that provider is a socket unit, systemd default dependencies already order the socket before sockets.target while service defaults place set-SSH_AUTH_SOCK.service after basic.target. That creates a sockets.target -> basic.target -> set-SSH_AUTH_SOCK.service -> provider.socket -> sockets.target cycle. For gpg-agent this makes systemd drop gpg-agent-ssh.socket, leaving SSH_AUTH_SOCK pointing at the expected S.gpg-agent.ssh path but with no socket listening there. Only order and install the environment service against non-socket providers. Socket providers still get SSH_AUTH_SOCK imported through default.target. Fixes #9432.
125 lines
4.1 KiB
Nix
125 lines
4.1 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
let
|
|
cfg = config.sshAuthSock;
|
|
socketProviderIsSocket = lib.hasSuffix ".socket" cfg.systemd.socketProviderUnit;
|
|
orderedProviderUnits = lib.optional (!socketProviderIsSocket) cfg.systemd.socketProviderUnit;
|
|
in
|
|
{
|
|
meta.maintainers = [ lib.maintainers.bmrips ];
|
|
|
|
options.sshAuthSock = {
|
|
|
|
enable = lib.mkEnableOption "" // {
|
|
description = ''
|
|
Whether to set {env}`SSH_AUTH_SOCK` in shells, systemd, and the D-BUS daemon
|
|
unless it was already defined through SSH agent forwarding.
|
|
|
|
Typically, this module will be implicitly enabled and configured by SSH
|
|
agent modules.
|
|
'';
|
|
};
|
|
|
|
initialization =
|
|
let
|
|
mkShellInitOption =
|
|
shell:
|
|
lib.mkOption {
|
|
description = "Code that initializes {env}`SSH_AUTH_SOCK` in ${shell}.";
|
|
type = lib.types.str;
|
|
};
|
|
in
|
|
{
|
|
bash = mkShellInitOption "bash" // {
|
|
example = "export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock";
|
|
};
|
|
fish = mkShellInitOption "fish" // {
|
|
example = "set -x SSH_AUTH_SOCK $HOME/.ssh/agent.sock";
|
|
};
|
|
nushell = mkShellInitOption "nushell" // {
|
|
example = "$env.SSH_AUTH_SOCK = $HOME/.ssh/agent.sock";
|
|
};
|
|
zsh = mkShellInitOption "zsh" // {
|
|
example = "export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock";
|
|
default = cfg.initialization.bash;
|
|
defaultText = lib.literalExpression "config.sshAuthSock.initialization.bash";
|
|
};
|
|
};
|
|
|
|
systemd.socketProviderUnit = lib.mkOption {
|
|
description = ''
|
|
The name of the systemd unit responsible for providing the {env}`SSH_AUTH_SOCK`.
|
|
|
|
Services that rely on an active SSH authentication agent can reference
|
|
this option to declare a dependency onto this unit, ensuring that the
|
|
socket is available and being served before they start.
|
|
'';
|
|
example = "ssh-agent.service";
|
|
type = lib.types.str;
|
|
};
|
|
|
|
};
|
|
|
|
config =
|
|
let
|
|
# Preserve $SSH_AUTH_SOCK if it stems from a forwarded agent which is the
|
|
# case if both $SSH_AUTH_SOCK and $SSH_CONNECTION are set.
|
|
mkShIntegration = code: ''
|
|
if [ -z "$SSH_AUTH_SOCK" -o -z "$SSH_CONNECTION" ]; then
|
|
${code}
|
|
fi
|
|
'';
|
|
bashIntegration = mkShIntegration cfg.initialization.bash;
|
|
zshIntegration = mkShIntegration cfg.initialization.zsh;
|
|
fishIntegration = ''
|
|
if test -z "$SSH_AUTH_SOCK"; or test -z "$SSH_CONNECTION"
|
|
${cfg.initialization.fish}
|
|
end
|
|
'';
|
|
nushellIntegration =
|
|
let
|
|
unsetOrEmpty = var: ''("${var}" not-in $env) or ($env.${var} | is-empty)'';
|
|
in
|
|
''
|
|
if ${unsetOrEmpty "SSH_AUTH_SOCK"} or ${unsetOrEmpty "SSH_CONNECTION"} {
|
|
${cfg.initialization.nushell}
|
|
}
|
|
'';
|
|
in
|
|
lib.mkIf cfg.enable {
|
|
# $SSH_AUTH_SOCK has to be set early since other tools rely on it
|
|
programs.bash.profileExtra = lib.mkOrder 900 bashIntegration;
|
|
programs.fish.shellInit = lib.mkOrder 900 fishIntegration;
|
|
programs.nushell.extraConfig = lib.mkOrder 900 nushellIntegration;
|
|
programs.zsh.envExtra = lib.mkOrder 900 zshIntegration;
|
|
|
|
# Replace this service by an environment generator as soon as they are
|
|
# available per-user. See https://github.com/systemd/systemd/issues/32423
|
|
# for more information.
|
|
systemd.user.services.set-SSH_AUTH_SOCK = {
|
|
Unit = {
|
|
Description = "Sets SSH_AUTH_SOCK in the D-BUS daemon and systemd";
|
|
# Socket units are ordered before sockets.target by systemd. Ordering
|
|
# this service before them creates a cycle through basic.target.
|
|
Before = orderedProviderUnits;
|
|
};
|
|
Service = {
|
|
Type = "oneshot";
|
|
ExecStart = pkgs.writeShellScript "set-SSH_AUTH_SOCK" ''
|
|
${bashIntegration}
|
|
${pkgs.dbus}/bin/dbus-update-activation-environment --systemd SSH_AUTH_SOCK
|
|
'';
|
|
};
|
|
Install.WantedBy = [
|
|
"default.target"
|
|
]
|
|
++ orderedProviderUnits;
|
|
};
|
|
};
|
|
}
|