Setting SSH_AUTH_SOCK in systemd user unit file

I want to set SSH_AUTH_SOCK in a user unit file1, but I’m not sure how I can get the value for a particular session.

By running env | grep SSH_AUTH_SOCK and consulting man ssh-agent I see that it is set to: /tmp/ssh-<random>/agent.<ppid>, but how can I determine this from a user init file or an environment file?

Edit: I accepted the import-environment response as the solution, because that does the job I had originally asked about rather elegantly, unfortunately because of timing it doesn’t quite have the desired effect. I have temporarily worked around it by adding a delay with ExecStartPre=....


1 I want to share the ssh-agent used by my session with emacs --daemon

1 Like

I think the standard way is to spew it into a file when you start ssh-agent so that everything you need can access it from there. I used to do this too before I made some tweaks (and now I can’t remember what tweaks I made :smiley: )

I’m not starting ssh-agent myself. It’s being started by my desktop environment (I use XFCE, so xfce4-session). Does XFCE write this information somewhere?

Another idea would be to set it to a symlink (that is non-existent initially), but during my XFCE startup, I can create that link and point it to $SSH_AUTH_SOCK.

Check out systemctl --user import-environment SSH_AUTH_SOCK. This could potentially be run as a separate user unit on login or put into .bashrc or .profile someplace where it would run after ssh-agent is started.

I thought I used it someplace, but for the life of me I can’t find it! So no guarantees!

3 Likes

This almost worked :frowning: I put the import-environment in my ~/.bash_profile. It works as intended, but it’s too late in the process. Emacs is already up and running and doesn’t pickup the change. If I restart the emacs unit, it can see the updated environment.

I guess I have to add a dependency in the unit so that it waits for the profile file to be sourced. Any idea what that might be? Currently my unit file looks like this:

[Unit]
Description=Emacs server
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/

[Service]
Type=forking

StandardOutput=file:/tmp/emacs%U.log
StandardError=inherit

ExecStart=emacs --daemon
ExecStop=emacsclient --eval "(save-some-buffers t)" --eval "(kill-emacs)"
Restart=on-failure

[Install]
WantedBy=default.target
1 Like

Under unit you could try adding (depending on how you’re setup)
After=graphical.target

I don’t actually know how to make sure .profile is sourced before the Emacs service starts.

I was looking at my own setup and realized that I use gpg-agent to manage my SSH keys. This bypasses your issue because the gpg socket is fixed so I can use the environment variable directly in my user service files:

[Unit]
Description=AutoSSH tunnel for Syncthing

[Service]
RestartSec=5
Restart=always
Environment="AUTOSSH_GATETIME=0"
Environment="SSH_AUTH_SOCK=%t/gnupg/S.gpg-agent.ssh"
ExecStart=/usr/bin/autossh -M 0 -N syncthing

[Install]
WantedBy=default.target

Another option would be to see if ssh-agent is started as a user service, in which case you could add it as a dependency to your emacs service. Or, you can disable whatever is launching ssh-agent and then create your own user service to start it.

When I was using i3, I had to figure out how disable it from starting from /etc/X11/xinit/xinitrc-common when X was started.

Anyways, hopefully that helps! Let us know how you solve it.

Unfortunately, that didn’t work either. I think that’s because it’s already satisfied when the login manager is running (lightdm for me).

Unfortunately I don’t have control over that. I am using XFCE. The XFCE session starts everything when I login.

$ ps uf -p ${SSH_AUTH_SOCK##*.} -p $SSH_AGENT_PID 
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
user        1201  0.0  0.1 519220 27700 ?        Ssl  01:14   0:00 xfce4-session
user        1325  0.0  0.0   6132   460 ?        Ss   01:14   0:00  \_ /usr/bin/ssh-agent /bin/sh -c exec -l /bin/bash -c "startxfce4"

Try the solution here to disable ssh-agent and then start your own ssh-agent with a user service.

That just inverts the problem, then I would need to ensure I export SSH_AGENT_PID and SSH_AUTH_SOCK from my ssh-agent unit, and source in my ~/.bash_profile. I think I’ll workaround for now by just adding a delay in my emacs unit. I tried with 15 seconds, that worked fine. It’s a bit annoying if I have to restart emacs, but that rarely happens.

In the meantime I’ll search around how to do this properly, but I have the feeling it’s not possible since it seems the user units run in a separate user-$UID.slice, whereas the desktop is under it’s own session-<n>.scope. Thanks a lot everyone for helping me patiently :slight_smile:

you could also try the solution posted here

I guess you are referring to the keychain solution? If I’m not mistaken that also inverts the problem, I would need to start my own ssh-agent from a unit using keychain, and then source the dump from my ~/.bash_profile. I’m hesitant to manage my own ssh-agent because the way XFCE does it has worked for me for a very long time.

Iwas referring to, the second solution adding an ExecStartPre to set the environment,

ExecStartPre=/bin/bash -c "systemctl --user set-environment SSH_AUTH_SOCK=$(find /tmp/ -type s -name agent.* 2> /dev/null | grep -o '/tmp/ssh-.*/agent.*')"

You could also do something just looking for the variable to be set:

ExecStartPre=/usr/bin/bash -c "/usr/bin/systemctl --user show-environment | /usr/bin/grep SSH_AUTH_SOCK" 

You might need to add a RestartSec so it not restarting too quickly.

1 Like

This is way too roundabout for my taste. Also, I think the bash invocation might require a --login, otherwise it won’t source the profile file. In any case, thanks for pointing it out to me. If I get annoyed with my current work around, I’ll give this a try.