sshAuthSock: use enable flag instead of nullable submodule

This commit is contained in:
Benedikt Rips
2026-06-02 14:30:57 +02:00
committed by Austin Horstman
parent dc641330e2
commit efe95f113a
9 changed files with 179 additions and 135 deletions

View File

@@ -2,72 +2,74 @@
let
cfg = config.sshAuthSock;
mkShellInitOption =
shell:
lib.mkOption {
description = "Code that initializes {env}`SSH_AUTH_SOCK` in ${shell}.";
type = lib.types.str;
};
initSubmodule = {
options.bash = mkShellInitOption "bash";
options.fish = mkShellInitOption "fish";
options.nushell = mkShellInitOption "nushell";
};
# Preserve $SSH_AUTH_SOCK only if it stems from a forwarded agent which
# is the case if both $SSH_AUTH_SOCK and $SSH_CONNECTION are set.
bashIntegration = ''
if [ -z "$SSH_AUTH_SOCK" -o -z "$SSH_CONNECTION" ]; then
${cfg.initialization.bash}
fi
'';
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
{
meta.maintainers = [ lib.maintainers.bmrips ];
options.sshAuthSock.initialization = lib.mkOption {
description = ''
Shell-specific code to initialize {env}`SSH_AUTH_SOCK`.
options.sshAuthSock = {
RATIONALE: {env}`SSH_AUTH_SOCK` must not be set unconditionally through
{option}`home.sessionVariables` since its value needs to be preserved if
it stems from a forwarded agent. Hence, this option establishes a
centralized interface for setting {env}`SSH_AUTH_SOCK`. It checks whether
its value has to be preserved and injects the initialization code into the
proper {option}`programs.(bash|fish|nushell|zsh).*` options.
'';
example = {
bash = "export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock";
fish = "set -x SSH_AUTH_SOCK $HOME/.ssh/agent.sock";
nushell = "$env.SSH_AUTH_SOCK = $HOME/.ssh/agent.sock";
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.
'';
};
default = null;
internal = true;
type = with lib.types; nullOr (submodule initSubmodule);
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";
};
};
};
config = lib.mkIf (cfg.initialization != null) {
# $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 bashIntegration;
};
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.
bashIntegration = ''
if [ -z "$SSH_AUTH_SOCK" -o -z "$SSH_CONNECTION" ]; then
${cfg.initialization.bash}
fi
'';
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 bashIntegration;
};
}

View File

@@ -366,30 +366,33 @@ in
++ [ cfg.extraConfig ]
);
sshAuthSock.initialization = lib.mkIf cfg.enableSshSupport {
bash = ''
unset SSH_AGENT_PID
if [ "''${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)"
fi
'';
fish = ''
set -e SSH_AGENT_PID
sshAuthSock = lib.mkIf cfg.enableSshSupport {
enable = true;
initialization = {
bash = ''
unset SSH_AGENT_PID
if [ "''${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
export SSH_AUTH_SOCK="$(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)"
fi
'';
fish = ''
set -e SSH_AGENT_PID
begin
set -l gnupg_val 0
if set -q gnupg_SSH_AUTH_SOCK_by
set gnupg_val $gnupg_SSH_AUTH_SOCK_by
end
begin
set -l gnupg_val 0
if set -q gnupg_SSH_AUTH_SOCK_by
set gnupg_val $gnupg_SSH_AUTH_SOCK_by
end
if test $gnupg_val -ne %self
set -x SSH_AUTH_SOCK (${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)
if test $gnupg_val -ne %self
set -x SSH_AUTH_SOCK (${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)
end
end
end
'';
nushell = ''
$env.SSH_AUTH_SOCK = $"(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)"
'';
'';
nushell = ''
$env.SSH_AUTH_SOCK = $"(${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket)"
'';
};
};
programs = {

View File

@@ -74,15 +74,18 @@ in
lib.mkIf cfg.enable {
home.packages = [ cfg.package ];
sshAuthSock.initialization = {
bash = ''export SSH_AUTH_SOCK="${socketPath}"'';
fish = ''set -x SSH_AUTH_SOCK "${socketPath}"'';
nushell = "$env.SSH_AUTH_SOCK = ${
if pkgs.stdenv.isDarwin then
''$"(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"''
else
''$"($env.XDG_RUNTIME_DIR)/${cfg.socket}"''
}";
sshAuthSock = {
enable = true;
initialization = {
bash = ''export SSH_AUTH_SOCK="${socketPath}"'';
fish = ''set -x SSH_AUTH_SOCK "${socketPath}"'';
nushell = "$env.SSH_AUTH_SOCK = ${
if pkgs.stdenv.isDarwin then
''$"(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"''
else
''$"($env.XDG_RUNTIME_DIR)/${cfg.socket}"''
}";
};
};
systemd.user.services.proton-pass-agent = {

View File

@@ -60,24 +60,27 @@ in
config = lib.mkIf cfg.enable {
sshAuthSock.initialization =
let
socketPath =
if pkgs.stdenv.isDarwin then
"$(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"
else
"$XDG_RUNTIME_DIR/${cfg.socket}";
in
{
bash = ''export SSH_AUTH_SOCK="${socketPath}"'';
fish = ''set -x SSH_AUTH_SOCK "${socketPath}"'';
nushell = "$env.SSH_AUTH_SOCK = ${
if pkgs.stdenv.isDarwin then
''$"(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"''
else
''$"($env.XDG_RUNTIME_DIR)/${cfg.socket}"''
}";
};
sshAuthSock = {
enable = true;
initialization =
let
socketPath =
if pkgs.stdenv.isDarwin then
"$(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"
else
"$XDG_RUNTIME_DIR/${cfg.socket}";
in
{
bash = ''export SSH_AUTH_SOCK="${socketPath}"'';
fish = ''set -x SSH_AUTH_SOCK "${socketPath}"'';
nushell = "$env.SSH_AUTH_SOCK = ${
if pkgs.stdenv.isDarwin then
''$"(${lib.getExe pkgs.getconf} DARWIN_USER_TEMP_DIR)/${cfg.socket}"''
else
''$"($env.XDG_RUNTIME_DIR)/${cfg.socket}"''
}";
};
};
systemd.user.services.ssh-agent = {
Install.WantedBy = [ "default.target" ];

View File

@@ -73,10 +73,13 @@ in
# Override ssh-agent's $SSH_AUTH_SOCK definition since ssh-tpm-agent is a
# proxy to it.
sshAuthSock.initialization = lib.mkOverride 90 {
bash = ''export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-tpm-agent.sock"'';
fish = ''set -x SSH_AUTH_SOCK "$XDG_RUNTIME_DIR/ssh-tpm-agent.sock"'';
nushell = ''$env.SSH_AUTH_SOCK = $"($env.XDG_RUNTIME_DIR)/ssh-tpm-agent.sock"'';
sshAuthSock = {
enable = true;
initialization = lib.mkOverride 90 {
bash = ''export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-tpm-agent.sock"'';
fish = ''set -x SSH_AUTH_SOCK "$XDG_RUNTIME_DIR/ssh-tpm-agent.sock"'';
nushell = ''$env.SSH_AUTH_SOCK = $"($env.XDG_RUNTIME_DIR)/ssh-tpm-agent.sock"'';
};
};
systemd.user = {

View File

@@ -22,24 +22,27 @@ in
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
sshAuthSock.initialization =
let
socketPath =
if pkgs.stdenv.isDarwin then
"/tmp/yubikey-agent.sock"
else
"\${XDG_RUNTIME_DIR:-/run/user/$UID}/yubikey-agent/yubikey-agent.sock";
in
{
bash = ''export SSH_AUTH_SOCK="${socketPath}"'';
fish = ''set -x SSH_AUTH_SOCK "${socketPath}"'';
nushell = "$env.SSH_AUTH_SOCK = ${
if pkgs.stdenv.isDarwin then
"/tmp/yubikey-agent.sock"
else
''$"($env.XDG_RUNTIME_DIR | default $"/run/user/(id -u)")/yubikey-agent/yubikey-agent.sock"''
}";
};
sshAuthSock = {
enable = true;
initialization =
let
socketPath =
if pkgs.stdenv.isDarwin then
"/tmp/yubikey-agent.sock"
else
"\${XDG_RUNTIME_DIR:-/run/user/$UID}/yubikey-agent/yubikey-agent.sock";
in
{
bash = ''export SSH_AUTH_SOCK="${socketPath}"'';
fish = ''set -x SSH_AUTH_SOCK "${socketPath}"'';
nushell = "$env.SSH_AUTH_SOCK = ${
if pkgs.stdenv.isDarwin then
"/tmp/yubikey-agent.sock"
else
''$"($env.XDG_RUNTIME_DIR | default $"/run/user/(id -u)")/yubikey-agent/yubikey-agent.sock"''
}";
};
};
systemd.user.services.yubikey-agent = {
Unit = {

View File

@@ -1,3 +1,4 @@
{
sshAuthSock-initialization = ./initialization.nix;
sshAuthSock-disabled = ./disabled.nix;
sshAuthSock-enabled = ./enabled.nix;
}

View File

@@ -0,0 +1,23 @@
{
programs.bash.enable = true;
programs.fish.enable = true;
programs.nushell.enable = true;
programs.zsh.enable = true;
sshAuthSock.enable = false;
nmt.script = ''
assertFileNotRegex \
home-files/.profile \
'SSH_AUTH_SOCK'
assertFileNotRegex \
home-files/.config/fish/config.fish \
'SSH_AUTH_SOCK'
assertFileNotRegex \
home-files/.config/nushell/config.nu \
'SSH_AUTH_SOCK'
assertFileNotRegex \
home-files/.zshenv \
'SSH_AUTH_SOCK'
'';
}

View File

@@ -4,10 +4,13 @@
programs.nushell.enable = true;
programs.zsh.enable = true;
sshAuthSock.initialization = {
bash = "echo bash/zsh";
fish = "echo fish";
nushell = "echo nushell";
sshAuthSock = {
enable = true;
initialization = {
bash = "echo bash/zsh";
fish = "echo fish";
nushell = "echo nushell";
};
};
nmt.script = ''