MANAGING MULTIPLE DEPLOY KEYS FROM A SINGLE VPS INSTANCE

Mona Moxie
Coding Tips and Tutorials
5 min readMay 16, 2021

--

I recently had this challenge while working on a project, the ability to use multiple deploy keys (all pointing to different repositories) from a single VPS instance.

I had alternatives however, with things like automatic deployment from any of the cloud providers, but for this use case, I wanted it done manually.

Before I explain how to fix this, let me give you a hint on a practical example where this may come in handy.

USE CASE

Let’s say you have two projects on a DigitalOcean droplet, called project1 and project 2, each sitting on a git repository, and configured to run on multiple hosts via Nginx or Apache’s virtual hosts.

Also, project1 is sitting on the root domain, project1.com, while project two is sitting on a sub domain, project2.project1.com. Assume GitHub to be the remote repositories for these projects.

What you want is simple; to develop your app locally, either on project1 or project2, and push to their respective remote repos. After which, you intend to ssh into your VPS instance, cd into any of the project directory and pull from it’s associated remote repo.

If you are already familiar with this process, you know the normal flow will be to generate a key pair (private and public), go to the settings section of the remote repo, and paste the public key into the Deploy Keys section. But then, the challenge I had was when I ran the procedure for project1, it works. And by this, I mean it works perfectly.

But when I ran the same procedure for project 2, pasted it’s own key into the Deploy keys section of it’s repo, ssh back to the project terminal to pull, it told me permission denied (public key).

And as funny as this may sound, when I cd back to project1 to pull, that failed as well. With this, I was back to square 1, none of my deploy keys were working anymore. The keys were correct, no changes whatsoever, but git could no longer pull or sync with their respective repos.

The reason for this is in the repo’s configuration, and the default way it was designed to sync with remote repos.

To fix this, I will break it down into a series of steps, starting from the very beginning. Some patterns may look different, but just follow and compare with your steps, then make necessary adjustments if required.

  1. Generate your SSH key.

But first, cd into your ssh directory (P.S: The directory for this may differ depending on your OS or OS distribution), then create your ssh keys.

cd ~/.ssh

ssh-keygen -t rsa -b 4096 -C “youremail@email.com”

You will get a prompt to enter the name for the file. In my case, I like to specify a name other than id_rsa for the file. So I may do something like this:

~/.ssh/project1_github

Step 2. Add the newly created keys to the ssh-agent

eval “$(ssh-agent -s)”

ssh-add ~/.ssh/project1_github

Step 3. Copy the content of the public key to Github

cat project1_github.pub

Carefully highlight and copy the content, or you can use xclip or any command line tool for copying the content to the clipboard.

Step 4. Paste content on GitHub

Navigate to the repository on GitHub, Settings, Deploy Keys, and click on Add deploy key.

Enter a name, it could be anything, DigitalOcean, Heroku, AWS etc. And paste the copied content into the Key field.

Step 5. Clone repository

Where to clone into would depend on which OS you are using, the server and even the settings. I will be cloning mine into the /var/www directory.

cd /var/www

git clone git@github.com:YourGitHubUsername/project1.git

cd project1

Step 6. Edit the config file of the repo

vim .git/config

Under [remote “origin”] section, comment or delete the url value. And I will use my new url value, save and close vim.

url = "ssh://git@project1/YourGitHubUsername/project1.git"

Step 7. CD into the .ssh directory and create, or update the config file

vim ~/.ssh/config

Paste the lines below into the file, updating the username or project name where necessary

Host project1
HostName github.com
User git
IdentityFile ~/.ssh/project1_github
IdentitiesOnly yes

save and exit vim.

In the line of code above, the Host is an alias. By default, what should be there would be github.com. This is why when you do an SSH test to github, you normally use

ssh -T git@github.com

where git is the user, and github.com is the alias for the config.

The issue I had when I tested was that I had 2 deploy keys pointing to 2 different remote repos, but was testing my connection with an alias that was also used by both repos, since github.com is always the default alias. But with the above config settings, we’ve just done a re-wiring.

If everything worked as described, when you test your connection with

ssh -T git@project1

it should work.

This is because you’ve not only changed the alias, but you’ve also specified the private key to be used to connect with this alias, hence the IdentityFile that was specified.

If you get an error regarding access or permission to the config file in .ssh/config, try adding the necessary permissions to the file, and see if that solves it.

sudo chown $USER ~/.ssh/config

sudo chmod 644 ~/.ssh/config

To connect for project2, repeat the above processes (from 1–7). The main solution is at step 6 and 7. If you already have an existing repo on your VPS instance, you may as well just skip to that.

Now, you can test your connections to both repos and they should work fine.

ssh -T git@project1

ssh -T git@project2

And when you cd into any of the project directories, either on /var/www/project1 OR /var/www/project2, and run a git pull, they will each pull from their remote repos without conflict, by using their respective private keys and aliases.

--

--