Ssh – How to organise SSH keys

sshssh-agent

I've been creating multiple SSH keys in Debian for different accounts (namely Digital Ocean, GitHub, and Bitbucket), but it's getting messy very quickly.

Listing the contents in my .ssh folder, I get:

digOcn digOcn.pub github github.pub id_rsa id_rsa.pub

(I use the id_rsa key for Bitbucket.)

I do the eval 'ssh-agent -s' thing, and then "add" the keys like so:

  • ssh-add ~/.ssh/github (and then entering passphrase)

  • ssh-add ~/.ssh/id_rsa (and then entering passphrase)

  • ssh-add ~/.ssh/digOcn (When I try to add digOcn, it says "Permission denied". I don't try sudo to avoid messing something up and also because the other keys didn't require sudo.)

Here's the confusing part: performing ssh-add -l gives me this:

2048 so:me:nu:mb:er:s0:an:d9:le:tt:er:s0 /home/USER/.ssh/id_rsa (RSA)
2048 so:me:nu:mb:er:s0:an:d9:le:tt:er:s0 /home/USER/.ssh/github (RSA)
2048 so:me:nu:mb:er:s0:an:d9:le:tt:er:s0 github (RSA)
2048 so:me:nu:mb:er:s0:an:d9:le:tt:er:s0 USER@COMPUTER_NAME (RSA)

Yes, I have added SSH keys in the past, but I can't retrace what I've done. That's probably why there is both /home/USER/.ssh/github and github.


What have I done wrong? How should I be organising my SSH keys?

Best Answer

First, there is nothing wrong with using different keys for different accounts. This is pretty much overkill for interactive shells, but there are legitimate reasons for doing it when you're dealing with other, non-interactive services. For example a few years ago GitHub started allowing stronger SSH keys, while Bitbucket insisted on using weaker ones for a while longer. The right action at the time was to use different keys for accessing GitHub and Bitbucket.

Another example is rsync. If you're using rsync for, say, deploying files to a web server then you probably want dedicated SSH keys for it. These allow you to set different permissions than you'd normally use with your interactive account.

Back to your question about managing multiple keys: SSH lets you set different options for different destinations. In order to do that you need to edit a file ~/.ssh/config like this:

Host  bitbucket.org
    User                    hg
    IdentitiesOnly          yes
    IdentityFile            /home/user/.ssh/bitbucket

Host  github.com  gist.github.com
    User                    git
    IdentitiesOnly          yes
    IdentityFile            /home/user/.ssh/github

The file ~/.ssh/config should have permissions 0600 (I don't remember right now if that's enforced by SSH or not, but it certainly doesn't hurt).

You can, of course, also use the same mechanism for interactive shells, so set things like remote username (if different from the local one), remote port, shorten the hostname, etc. E.g.:

Host  sm
    Hostname                sphygmomanometer.example.com
    User                    human
    Port                    2222

Then you can just run

ssh sm

instead of

ssh -p 2222 human@sphygmomanometer.example.com

Wildcards are also allowed:

Host *
    ControlPath             ~/.ssh/ctl-%u-%r-%h-%p
    ControlMaster           auto
    ControlPersist          5m

Read the manual for more details.

Last but not least: don't "do the eval 'ssh-agent -s' thing". Contrary to the popular belief, there are severe security implications to that. The right way to do it is like this:

ssh-agent /bin/bash
ssh-add

(then enter your key passwords when you're prompted). That's all, don't do it key by key, or any other way.

This runs a new shell in which your keys are loaded, and when you want to revoke access you just exit this shell. If you "do the eval 'ssh-agent -s' thing" then authentication agents are left running long after you log off, and they can (and eventually will) be used for unauthorized access.

Edit: Try this little experiment:

  1. eval $(ssh-agent -s)
  2. log off, or kill the terminal
  3. log in again, or open a new terminal
  4. pgrep ssh-agent

Nobody's killing these ssh-agents, they hang around until the next reboot, ready to be used by the latest malware.

Related Question