The guide on Connecting to GitHub with SSH is pretty good. But I don’t like executing commands, like from these steps to generate a new SSH key, without understanding what they actually do.

Working with SSH keys seems to be one of those things I have done just rarely enough to forget most of it between each time. I decided to never let managing SSH keys trip me up again — by dusting off my notes, reading up some more, and turning them into this blog post.

An algorithm generates a key pair 🖇

Public-key cryptography is a cryptographic system that uses pairs of keys. Each pair consists of a public key (which may be known to others) and a private key (which may not be known by anyone except the owner)

There are also others! GitHub is making changes to protocol security these days that might affect you if your SSH keys were generated a long time ago.

Get to know my .ssh directory 🕵🏻‍♀️

Many guides seem to train me to fire off commands without learning which files are created or edited. “Simply run xyz to auto config, and don’t you worry about what it does on your laptop.” A habit I find never stops giving, is to poke around files and directories more, both before and after executing these types of commands. Makes it easier for me to understand what is what — and then how to debug like a badass when some day a thing doesn’t work as expected.

# List directory contents
ls -la ~/.ssh

This may tell me there is No such file or directory — or show me what the directory contains, including when the files were created. A typical list might have these files:

  • config is my user configuration file for ssh
  • id_ed25519 is the private key that I need to keep super secret
  • is the public key to be shared (for example with GitHub)
  • known_hosts keeps track of the public key for hosts my laptop connects to with ssh

We can inspect those files 😸

We can totally cat them all and see what they look like. If you thought (like I did) that especially the private key must be a very special type of mysterious file (I mean, look at it, no file-ending!) and therefore best left untouched, it can be kinda underwhelming to see the content.

# Change directory, then view the private key
cd .ssh && cat id_ed25519
# View any other files too, do it do it do it
cat config
cat known_hosts

Now that I know which files I have and what they look like, none of this upcoming keygen business is mysterious. Maybe I want to replace a pair? Set up the first pair on a new device? Set up multiple keys for different purposes? Edit the config? No problem, we got this.

Generate a new key pair 🔑

# Generate a public/private key pair
ssh-keygen -t ed25519 -C ""

This is the recommended command from GitHub, and we are going to break it apart:

  • ssh-keygen is a standard cli tool — I can run man ssh-keygen for the full manual
  • -t ed25519 will specify type of key (which algorithm)
  • alternatively -t rsa -b 4096 that creates type RSA with 4096 bits
  • -C "whatever" provides a comment

The email in that command is a comment that can be anything. It can even be changed on existing keys if I used the wrong email. The convention is to identify the public key with an email, so that when the public key is shared, it will not be an anonymous key belonging to who knows who’s device.

Specify file name with intended use

Tool asks where to save the file and suggests /Users/name/.ssh/id_ed25519 While it’s possible to accept with a quick enter, let’s customize instead. I will use the same path as the suggestion, but opt for a more specific file name that includes algorithm and where I plan to use the key pair:


Secure with passphrase

Enter passphrase? Yes, of course. Generate a long password in my password manager, and also save it there under “SSH key passphrase personal laptop / for github” or similar. (Gotta save the passphrase! I don’t think I need to save the fingerprint or randomart image that is output in the terminal.)

Repeat for any other places that request my public key

And if I now list directory contents of my .ssh, it might look like this:


Config my key collection ⚙️

Multiple keys will need a ~/.ssh/config looking something like this:

  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519_for_github

Host something.else
	// other settings for this key
  IdentityFile ~/.ssh/id_ed25519_for_something

I used a passphrase, but I don’t want to reenter it every time I use my keys (like when pushing to GitHub). But I can ssh-add my key to an ssh-agent.

ssh-agent is a program to hold private keys used for public key authentication. Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using ssh.

# Start the ssh-agent in the background
eval "$(ssh-agent -s)"

ssh-add adds private key identities to the authentication agent, ssh-agent

# Add private key to the ssh-agent
ssh-add -K ~/.ssh/id_ed25519_for_github
  • Will first ask for the passphrase
  • And should then output Identity added
  • Repeat for the other key!

The -K in that command is an option to “Load resident keys from a FIDO authenticator” 🤷🏻‍♀️🤷🏻‍♀️🤷🏻‍♀️
Other commands to play around with or know about:

#  Lists all identities currently represented by the agent
ssh-add -l

# Deletes all identities from the agent
ssh-add -D

They don’t list or delete any keys I have generated, this is only what is added to the authentication agent. Who’s job is to save me from using the passphrase each time I push to GitHub.

Give away the new public keys 🎁

  • Add one to my GitHub Account Settings
  • Add another to that work thing that needs a key

Test connection 📞

ssh -T

I can see from man ssh that -T option will “Disable pseudo-terminal allocation.” 🤷🏻‍♀️🤷🏻‍♀️🤷🏻‍♀️
“Sure you want to connect?” Verify with GitHub’s public key fingerprint 👍

If I don’t already have a known_hosts file already, this will create one. It will also add the public key for hosts my laptop connects to with ssh. Which I learnt because I poke around files and directories, both before and after executing these types of commands.

And if something goes wrong, there is an excellent guide to Troubleshooting SSH — a guide which now is more straight forward for me to parse than before.