fix(home-manager): improve pcscd availability check

Check for /run/pcscd/pcscd.comm socket file directly instead of using
systemctl, which may have D-Bus permission issues when running as a
user service. The socket file is created by systemd when pcscd.socket
is active and listening.

Increased wait time to 6 seconds (30 iterations × 0.2s) to handle
slower boot scenarios.
This commit is contained in:
Ryota 2026-01-17 02:51:59 +00:00
parent 236132d0ab
commit 83f259f34f
No known key found for this signature in database
GPG key ID: 5370567CADB11F6C

View file

@ -292,11 +292,14 @@ in
description = ''
Whether pcscd (PC/SC Smart Card Daemon) is required for age decryption.
Enable this when using hardware key plugins like age-plugin-yubikey
or age-plugin-fido2-hmac. This automatically configures the systemd
service to depend on pcscd.socket.
or age-plugin-fido2-hmac.
Note: The system must have pcscd available (usually via
`services.pcscd.enable = true` in your NixOS configuration).
This adds a pre-start check to wait for pcscd to be available before
attempting decryption.
Note: You must also enable `services.pcscd.enable = true` in your
NixOS configuration. The pcscd service runs at the system level and
will be socket-activated when the YubiKey is accessed.
'';
};
};
@ -397,6 +400,9 @@ in
);
};
# Note: pcscd.socket is a system service, not a user service, so we cannot
# add it as a direct dependency for requirePcscd. Instead, we add a pre-start
# script that waits for pcscd to be available.
systemd.user.services.sops-nix = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
Unit = {
Description = "sops-nix activation";
@ -409,14 +415,30 @@ in
lib.mapAttrsToList (name: value: "'${name}=${value}'") cfg.environment
);
ExecStart = script;
ExecStartPre = lib.mkIf cfg.age.requirePcscd [
"${pkgs.writeShellScript "wait-for-pcscd" ''
# Ensure pcscd is available for YubiKey communication.
# When pcscd.socket is enabled, systemd creates /run/pcscd/pcscd.comm
# and starts pcscd.service on-demand when the socket is accessed.
for i in $(seq 1 30); do
# Check if the pcscd socket file exists - this is the most reliable check
# and doesn't require D-Bus access
if [ -e /run/pcscd/pcscd.comm ]; then
exit 0
fi
sleep 0.2
done
echo "Warning: pcscd socket not found at /run/pcscd/pcscd.comm" >&2
echo "YubiKey decryption may fail. Ensure services.pcscd.enable = true" >&2
''}"
];
};
Install.WantedBy =
if cfg.gnupg.home != null then [ "graphical-session-pre.target" ] else [ "default.target" ];
};
# Auto-configure pcscd dependency when requirePcscd is enabled
sops.age.systemdDeps = lib.mkIf cfg.age.requirePcscd [ "pcscd.socket" ];
# Darwin: load secrets once on login
launchd.agents.sops-nix = {
enable = true;