i Mutiple `ssh` Identities · Dark Matter Industries

Mutiple `ssh` Identities

I was quickly setting up a Google Compute Engine (GCE) on the Google Cloud Platform (GCP), when, out of laziness I copied over my default ssh public key which I had created many months ago principally to ssh into a local Raspberry Pi. To make things more convenient for me back then I had opted not to use a passphrase when setting up that particular rsa key-pair; the logic being that the Pi was never to leave my local network and I had promised myself not to use that encryption key for any other purpose.

While that quickly got me into the GCE, my mind had registered what I had done, and although the risk of a breach was smaller than using a password login method, I still woke up in the middle of that night in cold sweat.

Never create an ssh keypair without a passphrase!

There is really no need to create an ssh identity with no passphrase: if you want to have the convenience of a connection without having to type in a passphrase all the time, there is an app for that. It’s part of the ssh suite and is called ssh-agent.

Once you launch ssh-agent, it runs as a daemon. Then all you need is to add your ssh identities to it, giving it your passphrase only once. The daemon will know you entered the right passphrase because the identity was accepted, and until it is killed, will allow passphrase-less ssh logins.

But first, about multiple identities.

The Many Me’s

I had, for a long time, thought that there was no need to have multiple ssh identities. After all, if one of the machines you ssh into is compromised and your public-key is exposed, no damage has been done. That is, after all, why we use public-keys.

Your private keys are safe as long as you leave it where it was created and leave the permissions (600) alone. Even root doesn’t have access to it.

But then I started creating VMs with multiple users. For instance on this blog the VM was created with my Google Account which gave it the first user. I then created another user specifically for the blogging operations, called something like “blogger”. This is good practice if you have public-facing services. So if my account gets hacked, at least only files in that account (in this case “blogger”) would be compromised.

At this point I needed more than one ssh identity.

I tie my identities to my username rather than machines or machine-username combinations. This way, I can use the same ssh identity across several machines as long as the usernames are the same.

Generate a new identity using1 :

$ ssh-keygen -t rsa -b 4096 -C "<username>"

The -C flag is a “comment” flag and is how the user (actually user@host) is transmitted in the public-key. If you use many host machines, it is a good idea to keep the user@host format otherwise a few months down, you’ll be looking at GCP ssh metadata and wondering which one belongs to which of your many daily-drivers.

ssh-keygen will ask where you want to save the key-pair. The way I do it is to keep the id_rsa and add the username after it. Hence for “blogger” it’s id_rsa_blogger, and I leave all my identities in ~/.ssh/. Make sure your passphrase is unique for each identity.

Now to ssh to your VM:

$ ssh -i ~/.ssh/id_rsa_blogger blogger@12.13.15.17

The -i option is of course how you chose which identity to use. You will be prompted for your passphrase.

To alias or not to alias

If you have to log into more than one server-identity combination, then you will have several variants of the above ssh command to type. With bash or zsh’s history search feature (bck-i-search) this is not a problem: you can recall the exact command with a few keystrokes.2 You could alias these commands, but there is a better way: you could set up an ssh config file to handle each machine-identity pair.

This file sits in ~/.ssh/ and is called, simply, config. If it does not exist, create it. The entries look like:

Host saturn
	Port 22
	hostname 12.14.15.12
	User bowman
	IdentityFile ~/.ssh/id_rsa_bowman

Host blog
	hostname 12.13.15.17
	User blogger
	IdentityFile ~/.ssh/id_rsa_blogger

et cetera. Now all you need is to invoke:

$ ssh blog

to open a connection to the machine, use the specified identity and user to sign in.

Single Sign On?

If you are like me, I don’t mind typing out my long passphrases but would jump at a method that saves me from doing it without compromising security. This is where the ssh-agent comes in.

The agent is a daemon that runs on your local machine where the ssh keys reside. It can remember identities that you add to it successfully. Identities are only added successfully if you key in the correct passphrase while adding it. Henceforth, when using that identity, the agent provides the trust element, telling the ssh server that you are kosher.

First you have to make sure that the agent is running. A simple way is to attempt to list the identities the agent might be holding. If it fails it means that the agent is not running:

% ssh-add -l
Could not open a connection to your authentication agent.

If it is not running, here’s how to start it. Type:

$ ssh-agent 

If the agent is not running you will get something like:

SSH_AUTH_SOCK=/tmp/ssh-5FhM8gsgL8Pp/agent.16567; export SSH_AUTH_SOCK;
SSH_AGENT_PID=16567; export SSH_AGENT_PID;
echo Agent pid 16567;

Believe it or not, that long series of expressions is the script that you need to get the daemon running! There are a couple of ways to do this. One way is to copy that output into a file and source it:

$ ssh-agent > ssh-agent.sh
$ source ssh-agent.sh

Note that the ssh-agent expressions above are sh-based shell specific. This is the default when ssh-agent is used in a sh-based shell such as bash. If you used the command in a csh-like environment, it will adjust to use setenv instead. This is the same as passing a -c option to ssh-agent

Or, a much simpler way is to just type the following:

$ eval "$(ssh-agent)"

eval is a builtin that constructs a command from the arguments presented to it (exactly what we needed to do to the above expression spouted into stdout from typing ssh-agent) and executes it.

Once the agent is running, add identities to it simply using:

$ ssh-add ~/.ssh/id_rsa_blogger

The agent will ask for the passphrase. Once added, you have performed your Single Sign On. From now onwards, whenever you use that identity, you will not be asked for your passphrase. This is until the agent process is killed.


  1. My ssh defaults to RSA and 3072 bits. I just make it a habit to specify both so that it’s in muscle memory. I could of course, change the ssh_config file. ↩︎

  2. I will write about how I use zsh’s history feature soon. ↩︎