Though it is generally the case and is considered a good practice to have only one public-private key pair per device, sometimes you end up using more than one key. Like, for example, you might use one SSH key pair for your personal projects and you might use a different key for accessing your corporates' private repositories. On top of that, you might be using a different key for accessing a client's server.
Managing SSH keys can become cumbersome as soon as you need to use a second key. Traditionally, you would use
to add your keys to
ssh-agent, typing in the password for each key if required. The problem is that you would need
to do this every time you restart your computer since
ssh-agent will restart and you will have to add and type in the
password for each key all over again.
The solution is to automate adding keys, store keys, and to specify which key to use when accessing certain servers by creating a configuration file specifying our customizations for SSH to use automatically.
SSH Config is a per-user configuration file for SSH communication.
Create a new file typically stored at
~/.ssh/config. Since this config file is new, you might need to do
chmod 600 ~/.ssh/config.
On Linux and macOS, verify that the permissions on your IdentityFile are 400. SSH will reject, in a not explicit manner, SSH keys that are too readable. It will just look like a credential rejection. The solution, in this case, is:
chmod 400 ~/.ssh/id_rsa
Anyways, the first thing to solve using this
config is to avoid having to add custom-named SSH keys using
ssh-add. Assuming your private key is named
~/.ssh/id_rsa, add the following to the
Host github.com HostName github.com User git # GitHub username IdentityFile ~/.ssh/id_rsa IdentitiesOnly yes AddKeysToAgent yes
It is important that the base URI of
Host github.com in
config and the base URI of the repository that you want
to clone and work with match. But, it is also possible to have a custom hostname:
Host github-personal HostName github.com User github-personal-user # GitHub username IdentityFile ~/.ssh/id_rsa IdentitiesOnly yes AddKeysToAgent yes
With this setting now you can say
git clone git@github-personal:github-account/interesting-project.git. If you had already cloned the repository, you can change the remote url, if you want, by:
git remote set-url origin git@github-personal:github-account/interesting-project.git firstname.lastname@example.org:some-github-user/interesting-project.git
Next, to add another account do:
Host github-corporate HostName github.com User github-corporate-user # GitHub username IdentityFile ~/.ssh/id_ed25519 AddKeysToAgent yes IdentitiesOnly yes
The Ed25519 was introduced on OpenSSH version 6.5 and is now the recommended way to generate ssh key pair. This is EdDSA implementation using the Twisted Edwards curve. It uses elliptic curve cryptography that offers better security with faster performance compared to DSA or ECDSA. Today, the RSA is the most widely used public-key algorithm for SSH keys. But compared to Ed25519, it's slower and even considered not safe if it's generated with a key smaller than 2048-bit length.
The Ed25519 public-key is compact, contains 68 characters compared to RSA 3072 that has 544 characters. Generating the key is also almost as fast as the signing process. It's also fast to perform batch signature verification with Ed25519. It is built to be collision resilience. Hash-function collision won't break the system.
$ ssh-keygen -t ed25519 -C "email@example.com"
This creates a new ssh key, using the provided email as a label. If your system doesn't support the Ed25519 algorithm, use:
ssh-keygen -t rsa -b 4096 -C "firstname.lastname@example.org"
Getting back to the task in hand, now you can use
git clone git@github-corporate:company/project.git.
Per repository settings
It turns out you can also define repository-specific keys overriding the configuration in
~/.ssh/config file. There
are, at least, two ways to do this.
One, using the GIT_SSH_COMMAND. From Git version 2.3.0, you can use the environment variable GIT_SSH_COMMAND like this:
GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa" git clone git@github-corporate:company/project.git
Note that -i can sometimes be overridden by your config file, in which case, you should give SSH an empty config file, like this:
GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa -F /dev/null" git clone git@github-corporate:company/project.git
Second, via core.sshCommand. From Git version 2.10.0, you can configure this per repo or globally, so you don't have to set the environment variable any more!
git config core.sshCommand "ssh -i ~/.ssh/id_rsa -F /dev/null" git pull git push