See also the GitHub SSH Key Guide.
Generate your key:
ed25519 keys
These are a new type of key that is shorter but harder to crack that the older RSA format. Older machines might not understand them though, so you might want to generate an RSA key as a backup.
Copying these keys is much nicer, so worth using them where possible.
ssh-keygen -t ed25519 -C "<your email address>"
You can leave the password field blank, but I recommend setting one (you can save it in your OS Keychain, see below).
This will generate two files. The public key is at ~/.ssh/id_rsa.pub
. This is
what you share with other people. You should never give anyone else your private
key, which is ~/.ssh/id_rsa
.
Your public key will look like this, don't worry, it's still secure enough.
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDsiCLI9WWTrSd4MDUpSM35f44HPKYaV96e8WGyjgDzQ gib@fahn.co
RSA Keys
ssh-keygen -t rsa -b 4096 -C "<your email address>"
Add your key to the ssh keychain
Run ssh-add
with the path to the private key you created, then enter your password.
ssh-add ~/.ssh/id_rsa
Add your public key to GitHub
Copy the public key to your clipboard, and then paste it into any site.
macOS:
cat ~/.ssh/id_rsa.pub | pbcopy
open https://github.com/settings/keys
Linux:
cat ~/.ssh/id_rsa.pub | xclip -selection clipboard
xdg-open https://github.com/settings/keys
Now paste in the key that the previous command copied to your keyboard.
Repeat for any other site that needs your ssh keys (like Gitlab, GitHub Enterprise, or Bitbucket).
Put your public key on remote machines
If you want to ssh into machines, it's much easier to authenticate via key rather than via password. To set up your account on that machine for remote access do:
# ssh-copy-id takes the same arguments as ssh, including `-i ~/.ssh/other_key`
# in case you chose a different name.
# <machine> can be a hostname (foo.bar.com) or an IP address.
ssh-copy-id <remoteuser>@<machine>
This just appends your id_rsa.pub
to the ~/.ssh/authorized_keys
file on the
remote machine. You can paste it in manually if you want.
Troubleshooting
If you run ssh <remoteuser>@<machine>
, you should now connect without having
to type your password (if <remoteuser>
equals the output of uname
, then you
can omit the <remoteuser>@
part).
If it doesn't work:
Make sure permissions are set directly on both local and remote machines. Try running the following on both machines:
# Only you should be able to write to your home directory.
chmod go-w ~
# No-one else should be able to write to anything in ~/.ssh.
chmod -R go-w ~/.ssh
# No-one else should be able to read your private keys.
chmod go-r ~/.ssh/*
# Optionally allow others to see your public key and config:
chmod go+r ~/.ssh/*.pub ~/.ssh/config
If you get a password prompt, try manually specifying the path to the private
key with ssh -i ~/.ssh/id_rsa <remoteuser>@<machine>
. Make sure you're using
the right remote username (and that you can ping <machine>
).
If you don't get a password prompt you probably can't access the machine.
Optimising
Setting up an ssh config
So now you can be lazy and not type your password. But machine names are long and annoying, and often you have a different username, or a different private key, and typing it all is a drag.
Say you have a group of machines you frequently ssh into called
foo1-bar.xxx.com
, foo2-bar.xxx.com
etc. You might have a different username
on those machines too. Instead of typing ssh remoteuser@foo1-bar.xxx.com
every
time, you can just add this to your ssh config:
Host 1 2 3 4 5 6 7 8 9
# %h gets replaced with the Host string above.
HostName foo%h-bar.xxx.com
User remoteuser
And now you just type ssh 1
, ssh 2
etc.
Now you find that you keep getting pesky messages every time you connect to a new machine asking if you want to add the RSA key to the trusted list, and you have to type yes.
Or you find that some machines close the connection if you don't type anything for a couple of minutes.
Or you want to set a default key for all machines that isn't ~/.ssh/id_rsa
.
You just add this to the beginning of your ssh config:
# Defaults for all hosts
Host *
# Consider getting a shiny modern key.
IdentityFile ~/.ssh/id_ed25519
# Backup key for older machines (ssh tries each one).
IdentityFile ~/.ssh/id_rsa
# Automatically accepts the "do you accept this RSA key" prompt.
StrictHostKeyChecking=no
# Don't close the connection if you are idle for a while.
ServerAliveInterval 120
# Use a different default user for sshing.
User gib
# Tells ssh to ignore the following option if ssh is too old to understand it.
IgnoreUnknown AddKeysToAgent
# Automatically run the ssh-add command if it's not already in the ssh keyring.
AddKeysToAgent yes
These generic rules can be overwritten by more specific ones you define below.
Aliases
I have alias s=ssh
in my dotfiles.
Check out the ssh and ssh-config man pages for more useful stuff.