Copy SSH key to clipboard on Mac (and generate a new one)

To copy your public SSH key to the clipboard on a Mac, run this in Terminal:

pbcopy < ~/.ssh/id_ed25519.pub

The command prints nothing. Paste the key with Cmd+V into GitHub, GitLab or a server panel.

Keys made with the 2017 version of this post, or with a bare ssh-keygen before OpenSSH 9.5 (2023), are RSA:

pbcopy < ~/.ssh/id_rsa.pub

If zsh answers no such file or directory, you don't have that key yet. Generate one (below).

Checked with OpenSSH 10 (macOS 26.1 ships 10.0p2) and an Ubuntu 26.04 server.

Copy the public key, not the private one

ls ~/.ssh

Each key is two files. id_ed25519 is the private key: it never leaves your Mac. id_ed25519.pub is the public key, safe to share. It's one line:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... you@example.com

If your clipboard starts with -----BEGIN OPENSSH PRIVATE KEY----- or, for an old RSA key, -----BEGIN RSA PRIVATE KEY-----, you copied the private key. Don't paste it anywhere.

Without pbcopy: run cat ~/.ssh/id_ed25519.pub, select the line from ssh- to the end and press Cmd+C.

Generate a new SSH key on Mac

ssh-keygen -t ed25519 -C "you@example.com"

Press Enter to save to the default ~/.ssh/id_ed25519, then type a passphrase twice (more below). ssh-keygen creates ~/.ssh if needed, with mode 700 for the folder and 600 for the private key. Then copy the key with pbcopy.

-C adds a comment to the end of the key, so you can tell keys apart in a server's authorized_keys and in ssh-add -l. Without it the comment is user@hostname.

Since OpenSSH 9.5 a bare ssh-keygen makes Ed25519 too. I keep -t ed25519 so older systems give the same key.

If it says id_ed25519 already exists and asks Overwrite (y/n)?, answer n. Overwriting deletes the old key, and every server that trusted it stops letting you in.

Passphrase and macOS Keychain

The passphrase encrypts the private key, so a copied file is useless without it. To stop typing it on every connection, store it in Keychain:

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

And add to ~/.ssh/config (create it if missing):

Host *
  AddKeysToAgent yes
  UseKeychain yes

UseKeychain makes ssh read the passphrase from Keychain and save it there once you type it correctly. AddKeysToAgent loads the key into ssh-agent on first use, so after a reboot you don't run ssh-add again.

Older guides use ssh-add -K. On macOS 26.1 it still works with a warning, and the man page says future releases will drop it.

To check the passphrase, run ssh-keygen -y -f ~/.ssh/id_ed25519. The right one prints the public key, a wrong one gives incorrect passphrase supplied to decrypt private key. The same command restores a deleted .pub:

ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub

ssh-keygen -p -f ~/.ssh/id_ed25519 adds or changes the passphrase.

If you share ~/.ssh/config with Linux machines, ssh there stops with Bad configuration option: usekeychain. Make this the first line of the file:

IgnoreUnknown UseKeychain

RSA key for old servers

Ed25519 arrived in OpenSSH 6.5 in January 2014. If an older server rejects your key, make an RSA one:

ssh-keygen -t rsa -b 4096 -C "you@example.com"

It goes to ~/.ssh/id_rsa. Without -b you get 3072 bits. An RSA key you already have still works with current servers.

With an old server the key alone isn't enough. Servers older than OpenSSH 7.2 (2016) accept an RSA key only with a SHA-1 signature (ssh-rsa), and since OpenSSH 8.8 (2021) ssh doesn't sign that way by default. ssh then skips the key and asks for a password or answers Permission denied (publickey). The cause shows only in ssh -v: no mutual signature algorithm. Allow SHA-1 for that one server in ~/.ssh/config, with the address you type after @ in place of the example:

Host oldserver.example.com
  PubkeyAcceptedAlgorithms +ssh-rsa
  HostKeyAlgorithms +ssh-rsa

HostKeyAlgorithms matters if the server has only an RSA host key: without it ssh stops before login with no matching host key type found. Their offer: ssh-rsa. ssh-copy-id reads these lines too. Don't put them under Host *: OpenSSH turned SHA-1 off because collision attacks on it became practical.

Copy SSH key to a server with ssh-copy-id

macOS has ssh-copy-id built in:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

It logs in once, usually with your password, and appends the key to ~/.ssh/authorized_keys, creating the folder and file with modes 700 and 600. On success it prints Number of key(s) added: 1.

Keep -i. Without it ssh-copy-id takes keys from ssh-agent or the newest ~/.ssh/id*.pub, which may be the wrong key.

ssh-copy-id needs a way in: a password or another key the server already accepts. If you have neither, enable passwords for a while or add the key from the server side (below).

Add the key to authorized_keys by hand

The same without ssh-copy-id, one line from the Mac:

cat ~/.ssh/id_ed25519.pub | ssh user@server 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && { echo; cat; } >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'

If SSH doesn't let you in at all, open a shell on the server another way (your host's web console, say). Log in as the user you'll connect as and add the key, with yours in place of the example:

mkdir -p ~/.ssh
echo >> ~/.ssh/authorized_keys
echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... you@example.com' >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Use >>: a single > overwrites the file and deletes other keys. The empty echo adds a line break: if the file's last line has none, the new key sticks to it and doesn't work. sshd skips empty lines.

Adding a key for another user with sudo is covered in how to create an admin user.

Add SSH key to GitHub

  1. pbcopy < ~/.ssh/id_ed25519.pub
  2. On GitHub: profile picture → Settings → SSH and GPG keys → New SSH key.
  3. Title: your Mac's name. Key type: authentication. Paste into Key, click Add SSH key.

Or with GitHub CLI:

gh ssh-key add ~/.ssh/id_ed25519.pub --title "MacBook Air"

If gh replies that it needs the admin:public_key scope, run gh auth refresh -h github.com -s admin:public_key and repeat the command.

Check the connection:

ssh -T git@github.com

The first time, ssh shows GitHub's fingerprint. If it's SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU, type yes. Hi username! You've successfully authenticated means it works. Permission denied (publickey) means GitHub doesn't know this key.

If git push still asks for a username or token, the remote uses HTTPS. Switch it:

git remote set-url origin git@github.com:user/repo.git

Creating a repo and the first push are covered in Git configuration and first push.

Common errors

  • zsh: no such file or directory: /Users/you/.ssh/id_ed25519.pub: no key with that name. ls ~/.ssh shows what you have. If there's id_rsa.pub, copy that, if nothing, generate a key.
  • Permissions 0644 for '/Users/you/.ssh/id_ed25519' are too open and This private key will be ignored: other users can read the private key, so ssh refuses it. Run chmod 700 ~/.ssh and chmod 600 ~/.ssh/id_ed25519.
  • Permission denied (publickey) from a server: the key isn't in that user's authorized_keys, or sshd ignores the file. If ~/.ssh or authorized_keys is writable by everyone (777, 666), sshd logs Authentication refused: bad ownership or modes. ssh -v user@server shows which keys your Mac offers.
  • Passphrase asked every time: set up Keychain as above.
I do product consulting, build MVPs and teach people to build products themselves. Work with me →