Add SSH key to agent at login using KWallet

Hey everyone,

Goal
I’m a new NixOS user and my goal is to add my SSH key automatically to the SSH-agent using the KWallet at login time so that I just enter my passphrase at the first login after boot, and afterwards can just use it freely. I’m trying to use KWallet for this, as I think using just ssh-agent for this would mean one starts a new ssh-agent every time you login after a suspend session as well, if I understand correctly. See link and more specifically the last paragraph below the header ’ ssh-key with passphrase, with ssh-agent’ in the first answer.
I managed to get this working using this link on a different machine with debian, but now I’m trying to replicate the behaviour on this NixOS machine.

Problems
However, I’m running into 2 problems:

  1. I can’t seem to get the ssh-agent to be KWallet / can’t seem to set ssh.askPassword to ksshaskpass successfully in my configuration.nix → If I try to set it, it still will just ask me in the console for the passphrase.
  2. I can’t seem to get the script to run at login time, I think, because nothing happens.

What I’ve tried:
I’ve added ksshaskpass to systemPackages and set programs to the following:

programs = {
  ssh.startAgent = true;
  ssh.askPassword = pkgs.lib.mkForce "${pkgs.ksshaskpass.out}/bin/ksshaskpass";
};

and finally a systemd service to perform the automatic adding of the SSH keys at login (I have no reason to believe this last part works either, but the ksshaskpass also doesn’t seem to work when I use it in a regular terminal) :

systemd.user.services.add_ssh_keys = {
  script = ''
    ssh-add $HOME/.ssh/<key> # where <key> is of course replaced by the actual key.
  '';
  wantedBy = [ "multi-user.target" ];  #starts after login
};

Before, I tried a different way to run the script at startup, using programs.bash.loginShellInit, but this way every terminal that one would start also somehow runs the script.

Would you guys have an idea what could be wrong here? Cheers in advance!

More info
I’m running NixOS 23.05, with the unstable channel and home-manager installed (got git configured there) and with KDE Plasma installed with sddm and X11.

Other resources:
On ssh-agent
On ksshaskpass (see last messages)

6 Likes

Thanks @tobiasvandriessel for a very detailed write up, it matches my current situation as well :smiley:

I think I solved part of the puzzle, ksshaskpass seemingly non-working. It seems that the default behavior for ssh agent is to only use askPassword if no tty is present. That is, it prompts you in console because you launch it from console. This is controlled by SSH_ASKPASS_REQUIRE=never|force|prefer environment variable.

So, I added

  environment = {
    sessionVariables = {
      SSH_ASKPASS_REQUIRE="prefer";
    };
  };

to my configuration to solve this particular issue. Not sure if there’s some more specific nixos option here.

4 Likes

Big help from both of you, thanks!

While this does get me close, notably using ssh directly does not need a password. Ssh via git (ie git fetch, however, still asked for a password. Running ssh-add manually solved that across all terminals, but i struggled to automate that with the service, as provided at least.

To contribute, i did at least make some progress on a couple points. Keep in mind there’s probably many things wrong with this, as this was primarily trial and error.

  systemd.user.services.add_ssh_keys = {
    script = ''
      eval `${pkgs.openssh}/bin/ssh-agent -s`
      export SSH_ASKPASS="${pkgs.ksshaskpass}/bin/ksshaskpass"
      export SSH_ASKPASS_REQUIRE="prefer"
      ${pkgs.openssh}/bin/ssh-add $HOME/.ssh/key
    '';
    wantedBy = [ "default.target" ];
  };

Notably, i found that multi-user.target wasn’t actually running this at all for me. default.target seemed to be the only thing that actually ran it.

Also, when i did get it to run i noticed that ssh-add was failing. Adding ${pkgs.openssh}/bin/ssh-add solved that. Next i noticed that ssh-add was failing to connect to an agent, so i tried starting the agent, and then it started asking for a pass over the tty, odd since it doesn’t normally. So setting SSH_ASKPASS and SSH_ASKPASS_REQUIRE were test hacks to explore that idea.

All together this got me to have KWallet automatically open at login asking for a pass, which… kinda isn’t what i want. I imagine the context of running this as a service might be difficult? Or i’m just doing it very ignorantly (probably that).

Alas i give up for now. This post has got it mostly working so i can just run ssh-add manually once at login and i’m set. I bet i could also put this in my shell for ease.

Appreciate the post, and good luck to future googlers.

1 Like

Thanks @matklad @yak for your further investigations,

FYI: After posting this and not getting anywhere, I switched to Gnome and later to just using the 1Password SSH agent. So, I’ve not fixed the problem, but rather just switched to a different approach.

Cheers.

You want to do wantedBy = [ "graphical-session.target" ]; and probably after = [ "kwin_wayland.service" ]; (or something like that) in order for it to be pulled in late enough. multi-user.target is a system-level target, not user-level and default.target is too early for kwallet to be running.