The following will show you how you can modify the startup options of the SSH agent supplied by MacOS in a non-invasive way. This can be useful for doing things like setting a key lifetime, which can then be used with AddKeysToAgent
in your ~/.ssh/config
to automate the timing out of saved keys. This ensures that your passphrase is re-asked for periodically without having to shutdown, re-log, or having it actually persisted in keychain, the latter being almost as bad as having no passphrase at all, given that simply being logged in is generally enough to then use the key.
This method does not modify the system-installed SSH agent service (com.openssh.ssh-agent
), but rather duplicates its functionality into a user-installed launch agent where we can then modify the options. Modifying the system-installed service is becoming increasingly harder to do; SIP generally protects the files you need to modify, in addition to certain system volumes being mounted read-only now. This is generally a good thing for application and system security and should not be messed with if you don't have to. Additionally, the Homebrew openssh
package has issues in that you possibly lose out in the modifications that Apple has made to allow the SSH agent to work seamlessly with socket activation - YMMV, but I have had issues getting it to work as it seems to expect to have access to create the socket, causing conflicts when attempting to start the agent.
mkdir ~/Library/LaunchAgents
cp /System/Library/LaunchAgents/com.openssh.ssh-agent.plist ~/Library/LaunchAgents/com.openssh.ssh-agent-local.plist
After you do this, open the file with your favorite text editor of choice and replace:
com.openssh.ssh-agent
withcom.openssh.ssh-agent-local
SSH_AUTH_SOCK
withSSH_AUTH_SOCK_LOCAL
Then, add in some options you want for the local agent (as additional string
tags in the ProgramArguments
array). A good example is -t 14400
to time out loaded keys after 4 hours.
Here's a copy of the modified plist file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.openssh.ssh-agent-local</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/ssh-agent</string>
<string>-l</string>
<string>-t</string>
<string>14400</string>
</array>
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>SecureSocketWithKey</key>
<string>SSH_AUTH_SOCK_LOCAL</string>
</dict>
</dict>
<key>EnableTransactions</key>
<true/>
</dict>
</plist>
Next, add this to your shell profie (ie: .zprofile
or .bash_profile
):
if [ -n "${SSH_AUTH_SOCK_LOCAL}" ]; then
export SSH_AUTH_SOCK="${SSH_AUTH_SOCK_LOCAL}"
fi
Note
Make sure you have updated your SSH config before you do this by adding
AddKeysToAgent yes
to your~/.ssh/config
.
Finally, log out and back in (or reboot). launchd will load the service automatically - no need to use launchctl load
, etc.
To test, simply run ssh-add -l
. This will activate your locally registered com.openssh.ssh-agent-local
without activating the system one as your shell will have detected and copied the socket listner location from SSH_AUTH_SOCK_LOCAL
to SSH_AUTH_SOCK
.
You can verify this by running ps aux | grep ssh-agent
. The only running instance you should see is /usr/bin/ssh-agent -l -t 14400
. Additionally, launchctl list | grep ssh-agent
should show a PID for com.openssh.ssh-agent-local
and not com.openssh.ssh-agent
:
$ launchctl list | grep ssh-agent
- 0 com.openssh.ssh-agent
12345 0 com.openssh.ssh-agent-local
This does not solve the problem for graphical applications unless they parse your shell configuration and read exported environment variables from there.
What we really need is a means of extending or replacing system-installed launch agents on a per-user basis.