Configure ssh with multiple deploy keys for multiple git repositories
Oct. 2, 2019
Recently I had to set up a server in which developers had access to multiple git repositories in their home directories. Here is how I went about it.
First and foremost, to access GitHub you must be authorized for private repositories. This could mean SSH keys, or authenticating with a username and password. I wanted to avoid the developers being prompted continuously, so I used keys. Also, since I can not take everyone's private key and just drop it in their home directories, I had to think of a different way to go about this. I could not use the developer's personal private key for a couple main reasons.
- Access to developer accounts is too open. I don’t want access to their personal GitHub accounts, and they don’t want me to have it either. Telling the developers to generate another key pair and to give me the private key and upload their public to github as an alternate account key pair was out of the question.
- Assuming it wasn’t an issue to use a key pair for a developer and their account, it would be an effort to get the private key from every developer and keep track of the file.
After a little research the best option emerged - using deploy keys! Deploy keys are SSH key pairs that apply to a single repository. Actually setting this up took a bit of time (it didn’t help getting conflicting sources of information online), but it is pretty simple. This gist here was by far the most helpful source.
There are three main steps.
Create the Deploy Key and Put it on GitHub
Everyone and their mother’s have likely created SSH keys before using this guide. Go ahead and generate an SSH key pair that can be used for the repository.
Navigate to GitHub repository > settings > Deploy Keys and click "Add Deploy Key".
Paste in the public key in the text area labeled “key” and give the public key a descriptive title so you can recognize it in the future.
Now test your private key files ability to access the repository
ssh -i /path/to/.ssh/keyfile git@github.com
in my example:
(base) nick {~/.ssh}$ ssh -i haskell_ping-dk haskell_ping.github.com PTY allocation request failed on channel 0 Hi nick-brady! You've successfully authenticated, but GitHub does not provide shell access. Connection to github.com closed.
Note, only grant write access if needed (pushing code back up to origin). Also, put the private key (does not have the .pub
extension) into the SSH directory of the user. I.e. ~/.ssh/
.
Configure SSH config
The SSH config needs to be configured so that each repo is listed as separate host. Using subdomains of github.com can accomplish this. This is done so that when the SSH connections are started by git, that the config can use the correct file. I keep all of my private keys of the deploy keys in the ~.ssh directory with a naming convention to keep it organized - I.e. ${reponame}-dk
. Where “-dk
” signifies “deploy key”.
(base) nick {~/.ssh}$ cat config Host haskell-ping.github.com User git Hostname github.com IdentityFile ~/.ssh/haskell_ping-dk UserKnownHostsFile ~/.ssh/known_hosts Host repo2.github.com User git Hostname github.com IdentityFile ~/.ssh/repo2-dk UserKnownHostsFile ~/.ssh/known_hosts
This file is configured for haskell-ping
and another repository repo2
.
My tree structure inside my user directory now looks like this:
.ssh/ ├── authorized_keys ├── config ├── haskell_ping-dk ├── known_hosts └── repo2-dk
Update git config
In order for the config file to actually do anything, we need to update our git config for each repository so that the connection, when created, will use the subdomain we configured in our SSH config file.
The file being updated is ${REPO_DIR}/.git/config
.
Here is an example file for mine after being updated to work with the SSH config above.
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] url = git@haskell-ping.github.com:nick-brady/haskell-ping.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master
You can edit this file manually, or by using the git command. I prefer to use the git cli to modify the file. You can do this with
git remote set-url origin git@{{ repository name }}.github.com:{{ repo name_space }}/{{ repository name }}.git
… which in my example for haskell-ping
becomes
git remote set-url origin git@haskell-ping.github.com:nick-brady/haskell-ping.git
You should now be able to use the command line from each repository you have configured!