SSH keys you only unlock once
ssh-keygen -t ed25519Create a key with a passphrase, let the machine’s keychain remember it, and never type it again.
A key with no passphrase is a password in a file. A key with one asks on every push. The agent plus the login keychain fixes both: the passphrase is stored encrypted, unlocked when you log in, and typed once.
Create the key
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_github -C "you@laptop"Name it after what it is for. To add a passphrase to a key that has none, same key, nothing on any server changes:
ssh-keygen -p -a 100 -f ~/.ssh/id_ed25519_githubPoint each host at one key
Host *
IgnoreUnknown UseKeychain
AddKeysToAgent yes
UseKeychain yes
IdentitiesOnly yes
Host github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
Host nas
HostName 10.0.0.12
User admin
IdentityFile ~/.ssh/id_ed25519_homelabAddKeysToAgent loads the key on first use. UseKeychain is macOS only, and
IgnoreUnknown is what stops Linux rejecting the whole file over it.
IdentitiesOnly yes is the line people skip. Without it ssh offers every key in
the agent, and a server with the default MaxAuthTries 6 cuts you off with
Too many authentication failures before reaching the right one.Store the passphrase
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_githubPrompts once, then writes the passphrase to the login keychain. -K is the old
name for the same flag.
Wire it into the shell
Optional — the config above already loads the key on first use. This fills the agent up front, and never prompts:
if [[ -n $SSH_AUTH_SOCK ]] && ! ssh-add -l >/dev/null 2>&1; then
ssh-add -q --apple-load-keychain 2>/dev/null
fiBoth guards earn their place. ssh-add -l returns non-zero only when the agent
is empty, so the key is added once and every later shell skips the block —
without it, an unguarded ssh-add prompts in every new terminal. The -z test
on SSH_AUTH_SOCK stops a forwarded agent being thrown away when you SSH into
the machine.
Add the key to GitHub
Copy the public half — never the file without .pub:
pbcopy < ~/.ssh/id_ed25519_github.pubPaste it at github.com/settings/keys, or from the CLI:
gh ssh-key add ~/.ssh/id_ed25519_github.pub --title "laptop"GitLab is Settings → SSH Keys, Bitbucket Personal settings → SSH keys, and both take the same file. Test it:
ssh -T git@github.comOptionally, add it to another host
ssh-copy-id -i ~/.ssh/id_ed25519_homelab.pub you@10.0.0.12Pass -i explicitly, or it copies every key the agent holds. Without
ssh-copy-id:
cat ~/.ssh/id_ed25519_homelab.pub | ssh you@10.0.0.12 \
'install -d -m 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'Those permissions matter — sshd ignores authorized_keys if it is
group-writable, and says nothing about why.
When it does not work
| Symptom | Cause |
|---|---|
Permission denied (publickey) | Nothing in the agent, or the wrong IdentityFile. Check ssh-add -l, then ssh -v |
Too many authentication failures | IdentitiesOnly yes missing |
Bad configuration option: usekeychain | macOS-only option on Linux. Needs IgnoreUnknown UseKeychain |
unknown option -- apple-use-keychain | Homebrew’s OpenSSH is ahead of Apple’s on PATH |
| Prompts again after a reboot | Passphrase was added with plain ssh-add, which is session-only |