Skip to content

Instantly share code, notes, and snippets.

@echo-dave
Last active March 18, 2024 19:43
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save echo-dave/0d1ee6951c4e3bf00d738e84868e7d59 to your computer and use it in GitHub Desktop.
Save echo-dave/0d1ee6951c4e3bf00d738e84868e7d59 to your computer and use it in GitHub Desktop.
Mac OS: Load SSH keys on login / restart

Help my SSH keys are unavailable after restart

I'm still not sure what but on both my systems my keys just don't get loaded back into the ssh-agent on restarts and new login sessions. I got annoyed enough at it that I jumped through the hoops of putting ssh-add into a script and writting a property list file to load as a launchagent to fix it.

Add SSH Keys

If you haven't done so already you can use the well written gub hub instructions for generating ssh keys. Once you get them generated you'll add them with ssh-add -K <sshkey> where sshkey is the file path/name. Keys are stored by default in your ~/.ssh folder

Update

Note that you may need to use ssh-add --apple-use-keychain in Big Sur onward instead of ssh-add -K. I discovered the issue in Montery after skipping Big Sur.

Manual reloading SSH keys

The manual method (assuming your keys were stored into the Mac OS Keychain) is to open up Terminal and use
Prior to Big Sur:
ssh-add -A
Big Sur and on (discovered the issue with Monterey specifically and skipped Big Sur):
ssh-add --apple-load-keychain
to load all known keys

Auto load SSH keys after restart - plist file

To automate loading keys we need to write a basic property list file to save to ~/Library/LaunchAgents/ [addssh.plist] in my case:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http$
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>addssh</string>
        <key>Program</key>
        <string>/Users/YOURNAME/Library/Scripts/sshadd</string>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <false/>
        <key>StandardErrorPath</key>
        <string>/var/log/addssh/addssh.log</string>
        <key>StandardOutPath</key>
        <string>/var/log/addssh/addssh.log</string>
</dict>
</plist>

Noteably you'll need to change YOURNAME to your home directory name and also either make the log folder or remove the logging lines. If it can't write the log files due to missing folder or permissions it won't load the keys and fail silently.

The script

I couldn't get it to work without putting ssh-add it into a script which looks like the below. Make sure it goes into your ~/Library/scripts directory or change the reference above.

#!/bin/bash
ssh-add -A

Loading as an agent

Be sure to make your script executable with chmod 750 sshadd.
launchctl load -w ~/Library/LaunchAgents/addssh.plist

@rbradcurtis
Copy link

I seem to get the same results from adding

ssh-add -A
or
ssh-add --apple-load-keychain

to my ~/.zshrc

What's the advantage to the .plist route?

@tekumara
Copy link

@rbradcurtis the .plist file specifies a launch agent that will run on startup

@tekumara
Copy link

@echo-dave without a separate script file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http$
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>addssh</string>
	<key>ProgramArguments</key>
	<array>
		<string>/bin/bash</string>
		<string>-c</string>
		<string>ssh-add --apple-load-keychain</string>
	</array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <false/>
        <key>StandardErrorPath</key>
        <string>/var/log/addssh/addssh.log</string>
        <key>StandardOutPath</key>
        <string>/var/log/addssh/addssh.log</string>
</dict>
</plist>

@sprak3000
Copy link

The solution from @tekumara works, but you have to ensure the log paths exist and are write-able by the user running the program on startup. I think this is root, but I omitted them entirely. Didn't seem necessary to use them.

@bennetrr
Copy link

What's the advantage to the .plist route?

At least for me, writing the command in the zshrc file executes it everytime I open a console, and as the command takes a few seconds to run, I cannot use my shell immediately when I open it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment