Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

Generate an SSH Key on macOS: Terminal, Keychain, and 1Password

Sean

Platform Writer

Jul 05, 2026
6 min read

Generating an SSH key on macOS is ssh-keygen -t ed25519 from Terminal, with the passphrase stored in the macOS Keychain so subsequent SSH sessions unlock the key automatically. The .pub file lands in ~/.ssh/id_ed25519.pub and is the file the team uploads to GitHub, GitLab, or any server that needs to recognize the new key. The team that uses 1Password’s SSH agent has the same outcome with no Keychain prompt - 1Password stores the key encrypted and unlocks it on Touch ID.

Generate an SSH Key on macOS: Terminal, Keychain, and 1Password

Table of contents

The Terminal command

Open Terminal (Applications -> Utilities -> Terminal, or Cmd-Space then Terminal) and run:

ssh-keygen -t ed25519 -C "[email protected]"

The -t ed25519 flag picks the modern default. The -C flag sets a comment so the team can identify the key later (this shows up in authorized_keys and on GitHub as the key label).

Press Enter to accept the default path (/Users/you/.ssh/id_ed25519). The passphrase prompt is what makes the key secure - a stolen key file without a passphrase is the same as a stolen password. The team that uses a passphrase on dev keys has the right default. The team that skips the passphrase has a key that works but is one stolen laptop away from being abused.

ssh-keygen ships with macOS - no install needed. The team that wants the most current version installs via Homebrew’s openssh formula, but the system one is fine for 99% of use cases.

Storing the passphrase in Keychain

After generating the key, add this line to ~/.ssh/config:

Host *
    AddKeysToAgent yes
    UseKeychain yes
    IdentityFile ~/.ssh/id_ed25519

That config tells the SSH agent to:

  • Add the key to the agent when first used (AddKeysToAgent yes).
  • Use the macOS Keychain to store the passphrase (UseKeychain yes).
  • Default to the ed25519 key.

The team that has this config in place unlocks the key once after login (Touch ID prompts if 1Password is set up, otherwise a Keychain dialog) and never sees the passphrase prompt again until reboot. The team without this config sees the passphrase prompt every time the agent restarts.

To load the key into the agent explicitly:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

The --apple-use-keychain flag is the macOS-native version. The team that uses ssh-add -K (the older syntax) is on an old macOS.

Copying the public key

The next step is getting the .pub file to the server. From the macOS side:

pbcopy < ~/.ssh/id_ed25519.pub

pbcopy is the macOS clipboard helper. The public key is now in the clipboard - paste it into GitHub’s New SSH key form, or onto the server’s authorized_keys with cat >> ~/.ssh/authorized_keys.

For installing on a remote server directly:

ssh-copy-id user@server

ssh-copy-id is the standard helper that reads the local .pub, prompts for the server password one last time, and appends to authorized_keys. The team that uses this command avoids the manual cat | ssh pipeline.

The 1Password SSH agent

The team that uses 1Password has an alternative: the 1Password SSH agent stores keys encrypted in the 1Password vault, and the SSH client asks 1Password to unlock them on demand via Touch ID.

Setup:

  1. In 1Password, save the new SSH key as an SSH Key item (or import the existing id_ed25519).
  2. Enable the SSH agent: 1Password -> Settings -> Developer -> SSH Agent -> Allow agent to be used by SSH clients.
  3. Add to ~/.ssh/config:
Host *
    IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

The team that uses 1Password for everything else has no reason to manage a separate SSH keychain - the same Touch ID that unlocks 1Password unlocks the SSH key. The team that prefers a fully self-managed workflow uses the system Keychain path above.

Troubleshooting

Permission denied (publickey) after the key is generated and copied usually means one of:

  • The server’s ~/.ssh/authorized_keys permissions are too open. Server-side fix: chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys.
  • The server’s sshd_config has PubkeyAuthentication no. The team that manages the server needs PubkeyAuthentication yes and a sudo systemctl reload sshd.
  • The client is sending the wrong key. ssh -v user@server shows which keys are tried. The team that has multiple id_* files uses ~/.ssh/config with IdentityFile to pick the right one per host.

Could not open a connection to your authentication agent. means ssh-agent is not running. eval $(ssh-agent -s) starts one. The team that adds ssh-agent to ~/.zshrc or ~/.bash_profile (depending on shell) has it start at login.

FAQ

Where does macOS save the SSH key by default?

/Users/<you>/.ssh/id_ed25519. The .ssh directory is created if it does not exist. The team that has a different home directory (rare on macOS) passes -f to ssh-keygen with the desired path.

How do I add the key to the SSH agent?

ssh-add --apple-use-keychain ~/.ssh/id_ed25519. The agent then unlocks the key with Touch ID or the Keychain prompt on subsequent SSH connections. The team that wants the agent to start at login adds ssh-add --apple-use-keychain ~/.ssh/id_ed25519 to ~/.zshrc (for zsh, default on Catalina+) or ~/.bash_profile (older bash default).

Can I use the same key for GitHub and personal servers?

Yes. The key has no concept of which service it is for - it is just a public/private pair. The team that uses one key per service has better blast-radius control, but a single key works fine for most people.

What if I lose my passphrase?

Generate a new key. There is no recovery for SSH key passphrases - the file is encrypted with the passphrase as the only way to decrypt it. The team that stores the passphrase in a password manager (1Password, Bitwarden, Keychain) does not lose it. The team that uses a memorable phrase they remember is also fine.

Does macOS have an SSH agent by default?

Yes, ssh-agent is built in. The team that wants it to start automatically adds eval $(ssh-agent -s) to their shell profile. The team that uses 1Password’s SSH agent does not need the system one running - 1Password takes over the socket path.

If you are sizing the infrastructure for the kind of project this post covers, the RunxBuild hosting calculator is the right place to model the line items. The compute, the memory, the storage, the bandwidth, the database - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers. The RunxBuild dashboard is where the team sees the actual usage in one place.

Useful related references:

#ssh#macos#keygen#dev-infra