mirror of
https://github.com/nix-community/home-manager.git
synced 2025-12-15 05:21:06 +01:00
gpg-agent: add launchd service agent and sockets
This adds a Darwin Launchd agent along with its sockets to make gpg-agent starts at load or whenever the sockets are needed. Fixes: https://github.com/nix-community/home-manager/issues/3864
This commit is contained in:
parent
c82fc8cf3f
commit
ef50612457
6 changed files with 151 additions and 87 deletions
|
|
@ -30,7 +30,7 @@ let
|
|||
$env.SSH_AUTH_SOCK = ($env.SSH_AUTH_SOCK? | default (${gpgPkg}/bin/gpgconf --list-dirs agent-ssh-socket))
|
||||
'';
|
||||
|
||||
# mimic `gpgconf` output for use in `systemd` unit definitions.
|
||||
# mimic `gpgconf` output for use in the service definitions.
|
||||
# we cannot use `gpgconf` directly because it heavily depends on system
|
||||
# state, but we need the values at build time. original:
|
||||
# https://github.com/gpg/gnupg/blob/c6702d77d936b3e9d91b34d8fdee9599ab94ee1b/common/homedir.c#L672-L681
|
||||
|
|
@ -38,10 +38,14 @@ let
|
|||
let
|
||||
hash =
|
||||
substring 0 24 (hexStringToBase32 (builtins.hashString "sha1" homedir));
|
||||
in if homedir == options.programs.gpg.homedir.default then
|
||||
"%t/gnupg/${dir}"
|
||||
subdir = if homedir == options.programs.gpg.homedir.default then
|
||||
"${dir}"
|
||||
else
|
||||
"d.${hash}/${dir}";
|
||||
in if pkgs.stdenv.isDarwin then
|
||||
"/private/var/run/org.nix-community.home.gpg-agent/${subdir}"
|
||||
else
|
||||
"%t/gnupg/d.${hash}/${dir}";
|
||||
"%t/gnupg/${subdir}";
|
||||
|
||||
# Act like `xxd -r -p | base32` but with z-base-32 alphabet and no trailing padding.
|
||||
# Written in Nix for purity.
|
||||
|
|
@ -77,6 +81,32 @@ let
|
|||
};
|
||||
in hexString: (foldl' go initState (stringToCharacters hexString)).ret;
|
||||
|
||||
# Systemd socket unit generator.
|
||||
mkSocket = { desc, docs, stream, fdName }: {
|
||||
Unit = {
|
||||
Description = desc;
|
||||
Documentation = docs;
|
||||
};
|
||||
|
||||
Socket = {
|
||||
ListenStream = gpgconf "${stream}";
|
||||
FileDescriptorName = "${fdName}";
|
||||
Service = "gpg-agent.service";
|
||||
SocketMode = "0600";
|
||||
DirectoryMode = "0700";
|
||||
};
|
||||
|
||||
Install = { WantedBy = [ "sockets.target" ]; };
|
||||
};
|
||||
|
||||
# Launchd agent socket generator.
|
||||
mkAgentSock = name: {
|
||||
SockType = "stream";
|
||||
SockPathName = gpgconf name;
|
||||
SockPathMode =
|
||||
384; # Property lists don't support octal literals (0600 = 384).
|
||||
};
|
||||
|
||||
in {
|
||||
meta.maintainers = [ maintainers.rycee ];
|
||||
|
||||
|
|
@ -272,90 +302,74 @@ in {
|
|||
'') cfg.sshKeys;
|
||||
})
|
||||
|
||||
# The systemd units below are direct translations of the
|
||||
# descriptions in the
|
||||
#
|
||||
# ${gpgPkg}/share/doc/gnupg/examples/systemd-user
|
||||
#
|
||||
# directory.
|
||||
{
|
||||
assertions = [
|
||||
(hm.assertions.assertPlatform "services.gpg-agent" pkgs platforms.linux)
|
||||
];
|
||||
(mkMerge [
|
||||
(mkIf pkgs.stdenv.isLinux {
|
||||
systemd.user.services.gpg-agent = {
|
||||
Unit = {
|
||||
Description = "GnuPG cryptographic agent and passphrase cache";
|
||||
Documentation = "man:gpg-agent(1)";
|
||||
Requires = "gpg-agent.socket";
|
||||
After = "gpg-agent.socket";
|
||||
# This is a socket-activated service:
|
||||
RefuseManualStart = true;
|
||||
};
|
||||
|
||||
systemd.user.services.gpg-agent = {
|
||||
Unit = {
|
||||
Description = "GnuPG cryptographic agent and passphrase cache";
|
||||
Documentation = "man:gpg-agent(1)";
|
||||
Requires = "gpg-agent.socket";
|
||||
After = "gpg-agent.socket";
|
||||
# This is a socket-activated service:
|
||||
RefuseManualStart = true;
|
||||
Service = {
|
||||
ExecStart = "${gpgPkg}/bin/gpg-agent --supervised"
|
||||
+ optionalString cfg.verbose " --verbose";
|
||||
ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent";
|
||||
Environment = [ "GNUPGHOME=${homedir}" ];
|
||||
};
|
||||
};
|
||||
|
||||
Service = {
|
||||
ExecStart = "${gpgPkg}/bin/gpg-agent --supervised"
|
||||
+ optionalString cfg.verbose " --verbose";
|
||||
ExecReload = "${gpgPkg}/bin/gpgconf --reload gpg-agent";
|
||||
Environment = [ "GNUPGHOME=${homedir}" ];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.user.sockets.gpg-agent = {
|
||||
Unit = {
|
||||
Description = "GnuPG cryptographic agent and passphrase cache";
|
||||
Documentation = "man:gpg-agent(1)";
|
||||
systemd.user.sockets.gpg-agent = mkSocket {
|
||||
desc = "GnuPG cryptographic agent and passphrase cache";
|
||||
docs = "man:gpg-agent(1)";
|
||||
stream = "S.gpg-agent";
|
||||
fdName = "std";
|
||||
};
|
||||
|
||||
Socket = {
|
||||
ListenStream = gpgconf "S.gpg-agent";
|
||||
FileDescriptorName = "std";
|
||||
SocketMode = "0600";
|
||||
DirectoryMode = "0700";
|
||||
systemd.user.sockets.gpg-agent-ssh = mkIf cfg.enableSshSupport
|
||||
(mkSocket ({
|
||||
desc = "GnuPG cryptographic agent (ssh-agent emulation)";
|
||||
docs =
|
||||
"man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)";
|
||||
stream = "S.gpg-agent.ssh";
|
||||
fdName = "ssh";
|
||||
}));
|
||||
|
||||
systemd.user.sockets.gpg-agent-extra = mkIf cfg.enableExtraSocket
|
||||
(mkSocket {
|
||||
desc =
|
||||
"GnuPG cryptographic agent and passphrase cache (restricted)";
|
||||
docs = "man:gpg-agent(1) man:ssh(1)";
|
||||
stream = "S.gpg-agent.extra";
|
||||
fdName = "extra";
|
||||
});
|
||||
})
|
||||
|
||||
(mkIf pkgs.stdenv.isDarwin {
|
||||
launchd.agents.gpg-agent = {
|
||||
enable = true;
|
||||
config = {
|
||||
ProgramArguments = [ "${gpgPkg}/bin/gpg-agent" "--supervised" ]
|
||||
++ optional cfg.verbose "--verbose";
|
||||
EnvironmentVariables = { GNUPGHOME = homedir; };
|
||||
KeepAlive = {
|
||||
Crashed = true;
|
||||
SuccessfulExit = false;
|
||||
};
|
||||
ProcessType = "Background";
|
||||
RunAtLoad = cfg.enableSshSupport;
|
||||
Sockets = {
|
||||
Agent = mkAgentSock "S.gpg-agent";
|
||||
Ssh = mkIf cfg.enableSshSupport (mkAgentSock "S.gpg-agent.ssh");
|
||||
Extra =
|
||||
mkIf cfg.enableExtraSocket (mkAgentSock "S.gpg-agent.extra");
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Install = { WantedBy = [ "sockets.target" ]; };
|
||||
};
|
||||
}
|
||||
|
||||
(mkIf cfg.enableSshSupport {
|
||||
systemd.user.sockets.gpg-agent-ssh = {
|
||||
Unit = {
|
||||
Description = "GnuPG cryptographic agent (ssh-agent emulation)";
|
||||
Documentation =
|
||||
"man:gpg-agent(1) man:ssh-add(1) man:ssh-agent(1) man:ssh(1)";
|
||||
};
|
||||
|
||||
Socket = {
|
||||
ListenStream = gpgconf "S.gpg-agent.ssh";
|
||||
FileDescriptorName = "ssh";
|
||||
Service = "gpg-agent.service";
|
||||
SocketMode = "0600";
|
||||
DirectoryMode = "0700";
|
||||
};
|
||||
|
||||
Install = { WantedBy = [ "sockets.target" ]; };
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf cfg.enableExtraSocket {
|
||||
systemd.user.sockets.gpg-agent-extra = {
|
||||
Unit = {
|
||||
Description =
|
||||
"GnuPG cryptographic agent and passphrase cache (restricted)";
|
||||
Documentation = "man:gpg-agent(1) man:ssh(1)";
|
||||
};
|
||||
|
||||
Socket = {
|
||||
ListenStream = gpgconf "S.gpg-agent.extra";
|
||||
FileDescriptorName = "extra";
|
||||
Service = "gpg-agent.service";
|
||||
SocketMode = "0600";
|
||||
DirectoryMode = "0700";
|
||||
};
|
||||
|
||||
Install = { WantedBy = [ "sockets.target" ]; };
|
||||
};
|
||||
})
|
||||
})
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue