Snipe.Net Geeky, sweary things.

Using Multiple Github Deploy Keys for a Single User on a Single Linux Server

U

I’m a big fan of GitHub (and was a fan of Sourceforge back when it was what all the cool kids were using), but there’s one limitation that I’ve run into a few times that can be very frustrating, and that’s the inability to share deploy keys across multiple repos.

The challenge comes in when you’re trying to deploy two repositories on the same server using same user. For example, maybe I have a dedicated server where I have several virtualhosts set up, each their own website with their own codebase and their own repo.

If I want to use the same SSH user to deploy using git pull (or git clone on an initial deploy) more than one of those sites (and it’s certainly arguable as to whether you ever want to do that, but stay with me) via SSH user deployme, it’s going to look for /home/deployme/.ssh/id_rsa, which would be totally fine if GitHub allowed you to have one deploy key for multiple repos, but it doesn’t.

So you create a deploy key for Repo A, then create a deploy key for Repo B, the SSH key for Repo B one overwrites the SSH key for Repo A and you lose access to deploy Repo A. Bah! If you name your SSH keys differently for each repo, GitHub doesn’t see them, since they’re not located at /home/deployme/.ssh/id_rsa.

You could create a separate GitHub user just for your deployments, and that GitHub user’s key would be used instead of a deploy key. I kno lots of people who have done it this way, but I personally find this method uncomfortable, since it seems too easy to forget about that account when someone who has access to it leaves the company, etc. I like a level of traceability and accountability so I can quickly audit my access lists and feel confident that no one has access to stuff they shouldn’t.

Fortunately, the workaround here is very simple, using named SSH keys and an SSH config file.

First, create both SSH keys:

[code language=”bash”]ssh-keygen -t rsa -C “Deploy key for Repo A”
# Generating public/private rsa key pair.
# Enter file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter][/code]

Instead of hitting enter here as you usually might, enter a more specific keyfile name. For example, /home/deployme/.ssh/repo-a-rsa.

[code language=”bash”]Enter passphrase (empty for no passphrase): [Type a passphrase] # Enter same passphrase again: [Type passphrase again][/code]

Enter a password (or don’t – I’m not the boss of you). You should then see:

[code language=”bash”]Your identification has been saved in /home/deployme/.ssh/repo-a-rsa.
# Your public key has been saved in /home/deployme/.ssh/repo-a-rsa.pub.[/code]

Copy the contents of /home/deployme/.ssh/repo-a-rsa.pub and paste them into the Deploy Key section of your GitHub repo for Repo A.

Now do the same thing for Repo B.

[code language=”bash”]ssh-keygen -t rsa -C “Deploy key for Repo B”
# Generating public/private rsa key pair.
# Enter file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter] Your identification has been saved in /home/deployme/.ssh/repo-b-rsa.
# Your public key has been saved in /home/deployme/.ssh/repo-b-rsa.pub.
Enter passphrase (empty for no passphrase): [Type a passphrase] # Enter same passphrase again: [Type passphrase again] Your identification has been saved in /home/deployme/.ssh/repo-b-rsa.
# Your public key has been saved in /home/deployme/.ssh/repo-b-rsa.pub.[/code]

And add your Deploy Key on GitHub for Repo B.

Now you have two separate deploy keys for two separate repos, which should make GitHub happy – but it doesn’t, because when you try to deploy using git, it will default to using /home/deployme/.ssh/id_rsa, which won’t contain your valid deploy key data.

This is all solved via your SSH config file. As the deploying user:

vi ~/.ssh/config

This file probably doesn’t have anything in it, but either way, add this into the config file:

[code language=”bash”]Host repo-a-shortname github.com
Hostname github.com
IdentityFile /home/deployme/.ssh/repo-a-rsa
#User username-on-remote-machine

Host repo-b-shortname github.com
Hostname github.com
IdentityFile /home/deployme/.ssh/repo-b-rsa
#User username-on-remote-machine[/code]

I commented out the User option, since we don’t need it here, but it could be useful to you if the user on the remote machine would be different for each of these scenarios. It’s not needed for this example though.

That first line is similar to twiddling your /etc/hosts file – it lets you create a short, friendly name for the collection of settings you’re using in each block. This means that to ssh into the remote machine using my new SSH key, I would use:

ssh repo-a-shortname
or
ssh repo-b-shortname

To deploy using git, I would enter:

git clone git@repo-a-shortname
or
git clone git@repo-b-shortname

And that’s it.

About the author

snipe

I'm a tech nerd from NY/CA now living in Lisbon, Portugal. I run Grokability, Inc, and run several open source projects, including Snipe-IT Asset Management. Tweet at me @snipeyhead, skeet me at @snipe.lol, or read more...

By snipe
Snipe.Net Geeky, sweary things.

About Me

I'm a tech nerd from NY/CA now living in Lisbon, Portugal. I run Grokability, Inc, and run several open source projects, including Snipe-IT Asset Management. Tweet at me @snipeyhead, skeet me at @snipe.lol, or read more...

Get in Touch