Skip to content
SSH keys you only unlock once

SSH keys you only unlock once

September 26, 2026·
Homelab Central
·4 min read· #ssh#security#macos#ubuntu#zsh
ssh-keygen -t ed25519

Create 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_github

Point each host at one key

~/.ssh/config
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_homelab

AddKeysToAgent 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_github

Prompts 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:

~/.zshrc
if [[ -n $SSH_AUTH_SOCK ]] && ! ssh-add -l >/dev/null 2>&1; then
  ssh-add -q --apple-load-keychain 2>/dev/null
fi

Both 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.pub

Paste 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.com

Optionally, add it to another host

ssh-copy-id -i ~/.ssh/id_ed25519_homelab.pub you@10.0.0.12

Pass -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

SymptomCause
Permission denied (publickey)Nothing in the agent, or the wrong IdentityFile. Check ssh-add -l, then ssh -v
Too many authentication failuresIdentitiesOnly yes missing
Bad configuration option: usekeychainmacOS-only option on Linux. Needs IgnoreUnknown UseKeychain
unknown option -- apple-use-keychainHomebrew’s OpenSSH is ahead of Apple’s on PATH
Prompts again after a rebootPassphrase was added with plain ssh-add, which is session-only
This post is licensed under CC BY 4.0 by the author.
Last updated on