{ config, lib, pkgs, ... }: let inherit (lib) mkIf; cfg = config.services.yubikey-agent; in { meta.maintainers = [ lib.maintainers.cmacrae ]; options.services.yubikey-agent = { enable = lib.mkEnableOption "Seamless ssh-agent for YubiKeys"; package = lib.mkOption { type = lib.types.package; default = pkgs.yubikey-agent; defaultText = lib.literalExpression "pkgs.yubikey-agent"; description = "The yubikey-agent package to use."; }; }; config = mkIf cfg.enable (lib.mkMerge [ { home.packages = [ cfg.package ]; } (mkIf pkgs.stdenv.isLinux { systemd.user.services.yubikey-agent = { Unit = { Description = "Seamless ssh-agent for YubiKeys"; Documentation = "https://github.com/FiloSottile/yubikey-agent"; Requires = "yubikey-agent.socket"; After = "yubikey-agent.socket"; RefuseManualStart = true; }; Service = { ExecStart = "${cfg.package}/bin/yubikey-agent -l %t/yubikey-agent/yubikey-agent.sock"; Type = "simple"; # /run/user/$UID for the socket ReadWritePaths = [ "%t" ]; }; }; systemd.user.sockets.yubikey-agent = { Unit = { Description = "Unix domain socket for Yubikey SSH agent"; Documentation = "https://github.com/FiloSottile/yubikey-agent"; }; Socket = { ListenStream = "%t/yubikey-agent/yubikey-agent.sock"; RuntimeDirectory = "yubikey-agent"; SocketMode = "0600"; DirectoryMode = "0700"; }; Install = { WantedBy = [ "sockets.target" ]; }; }; home.sessionVariables = { SSH_AUTH_SOCK = "\${XDG_RUNTIME_DIR:-/run/user/$UID}/yubikey-agent/yubikey-agent.sock"; }; }) (mkIf pkgs.stdenv.isDarwin { launchd.agents.yubikey-agent = { enable = true; config = { ProgramArguments = [ "${cfg.package}/bin/yubikey-agent" "-l" "/tmp/yubikey-agent.sock" ]; KeepAlive = { Crashed = true; SuccessfulExit = false; }; ProcessType = "Background"; Sockets = { Listener = { SockPathName = "/tmp/yubikey-agent.sock"; SockPathMode = 384; # 0600 in decimal }; }; }; }; home.sessionVariables = { SSH_AUTH_SOCK = "/tmp/yubikey-agent.sock"; }; }) ]); }