Red Green Repeat Adventures of a Spec Driven Junkie

Specifying Different SSH key for git

With my recent articles on creating multiple vagarant virtual machines, I noticed connecting to virtual machines using command: vagarant ssh, was taking longer and failing frequently.

Most annoyingly, my blogging virtual machine was inaccessible, which is fine because the data and operating system are separate and I recreated the system, while traveling on the train of all places!

With a new system, I added back the SSH key to post blog articles and all of the sudden, the blogging virtual machine is inaccessible again.

What gives?!

A Better Solution

Instead of destroying and rebuilding again, I decided to find another way to use git without replacing the SSH keys, since that is what vagrant ssh was failing on and if I am actively changing SSH keys, it’s probably the most likely issue.

There are solutions to this issue, the one I have chosen this time is to use git’s GIT_SSH_COMMAND setting to provide another SSH key.

Other solutions use ssh-add or configuring the SSH configuration file that I have explored as well in the past. This is a valid solution and can work for other scenarios, but can never get ssh-add to work reliably with different keys and accounts. I just feel a bit lost with all of these security configurations, so I prefer a more manual but straight-forward method.

Requirements

If you would like to follow along, or understand my setup, these are the requirements:

  • SSH version 2.17.0 or newer
  • multiple github.com accounts with different credentials, i.e. work and personal.
  • SSH key that is password protected! - Less of a requirement but good security practice!

Solution: GIT_SSH_COMMAND

I solved my problem by prepending a: GIT_SSH_COMMAND= to my git command. I will go over the technique, then discuss its benefits.

Configuring GIT_SSH_COMMAND

When configuring the environment variable: GIT_SSH_COMMAND, git will use this SSH key instead of the default one in ~/.ssh/id_rsa.

To configure this variable, the value is basically a valid SSH command, for example, being able to SSH login to a server.

In this case, the configuration requires a different SSH key, so use the -i flag.

$ ssh -i /path/to/private/key <username>@<server address>

For github, there is no server to log into, so specifying the SSH key is sufficient:

$ ssh -i /path/to/private/key

This is the basis of the GIT_SSH_COMMAND option, to use the option, prepend the option with the above SSH command to any git command:

$ GIT_SSH_COMMAND="ssh -i /path/to/private/ssh/key" git <command>

This configures git to use a different SSH key than the default one in ~/.ssh/id_rsa.

Benefits of Approach

The main reasons why I chose this appraoch is to allow my virtual machines to access github but without copying SSH keys into the virtual machine and/or reconfiguring github for new SSH keys each time.

This avoids creating a new SSH key in the virtual machine, which may conflict with vagrant ssh. The jury is still out on this, but losing access to a virtual machine on your own computer is a bit silly if you ask me. ^_^;

Another benefit of this solution is one can cleanly manage multiple SSH keys for different accounts without tricky SSH configurations and ssh-add commands.

The number of times where I have pushed to the repository with unintended credentials… I prefer to have the SSH key with the project instead of having all the SSH key in the ~/.ssh directory.

Demerits of Approach

By adding GIT_SSH_COMMAND, you need to add this option every time you want to use a git command, well, most notably git push and git fetch since those are the only commands that require identity credentials.

One way to overcome this annoyance is to use configure git using command:

git config add core.sshCommand="ssh -i /path/to/private/ssh/key"

documentation

But I haven’t got this to work. :-/ (on 2.7.4 at least!)

This option only appears from git version 2.17.0 or newer! The misleading thing about git config is that I can add unsupported options and there will be no errors raised.

Update git

This is one of the first times I had to update git to a version to get a feature that is not in the system’s default git.

$ sudo add-apt-repository ppa:git-core/ppa -y
$ sudo apt-get update
$ sudo apt-get install git -y
$ git --version

After updating git, to check command configuration, use: git config -l:

$ git config -l
push.default=simple
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
core.sshcommand=ssh -i /path/to/id_rsa
remote.origin.url=git@github.com:...git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
user.email=user@domain.com
user.name=First Last
branch.fix_http_status_999.remote=origin
branch.fix_http_status_999.merge=refs/heads/fix_http_status_999

And Voila!

Non-git Update Solution

If you can’t update git on your system, a quick way to add GIT_SSH_COMMAND to reduce this annoyance is to make bash aliases for git in your .bashrc file:

alias git2="GIT_SSH_COMMAND='ssh -i /path/to/private/ssh/key'"

This will work in a pinch. ;-)

Conclusion

Using GIT_SSH_COMMAND to manage SSH keys for github adds another level of complexity when working with git, but I find this to my preferred solution when I do not want to spend time tinkering with SSH configurations. I know where the key is and I can keep things simple.

Ideally, upgrading git to a version that is newer than 2.17 so it supports the GIT_SSH_COMMAND option.

Another option is to have an alias in .bashrc, which will work in any system.

Finally, manually prepending the option GIT_SSH_COMMAND="ssh -i ..." each time is not a deal breaker since only git fetch and git push require an SSH key.

In either case, these are all valid options to solve this problem.