Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gubatron/d96594d982c5043be6d4 to your computer and use it in GitHub Desktop.
Save gubatron/d96594d982c5043be6d4 to your computer and use it in GitHub Desktop.
How to configure multiple deploy keys for different private github repositories on the same computer without using ssh-agent

How to configure multiple deploy keys for different private github repositories on the same computer without using ssh-agent

Let's say alice is a github.com user, with 2 or more private repositories repoN. For this example we'll work with just two repositories named repo1 and repo2

https://github.com/alice/repo1

https://github.com/alice/repo2

You need to be to pull from these repositories without entering a passwords probably on a server, or on multiple servers. You want to perform git pull origin master for example, and you want this to happen without asking for a password.

You don't like dealing with ssh-agent, you have discovered (or you're discovering now) about ~/.ssh/config a file that let's your ssh client know what private key to use depending on Hostname and username, with a simple configuration entry that looks like this:

Host github.com
  HostName github.com
  User git
  IdentityFile /home/alice/.ssh/alice_github.id_rsa
  IdentitiesOnly yes

So you went ahead and created your (alice_github.id_rsa, alice_github.id_rsa.pub) keypair, you then also went to your repository's .git/config file and you modified the url of your remote origin to be something like this:

[remote "origin"]
        url = "ssh://git@github.com:alice/repo1.git"

And finally you went to the repository Settings > Deploy keys section and added the contents of alice_github.id_rsa.pub

At this point you could do your git pull origin master without entering a password without issue.

but what about the second repository?

So your instinct will be to grab that key and add it to repo2's Deploy keys, but github.com will error out and tell you that the key is already being used.

Now you go and generate another key (using ssh-keygen -t rsa -C "alice@alice.com" without passwords of course), and so that this doesn't become a mess, you will now name your keys like this:

  • repo1 keypair: (repo1.alice_github.id_rsa, repo1.alice_github.id_rsa.pub)
  • repo2 keypair: (repo2.alice_github.id_rsa, repo2.alice_github.id_rsa.pub)

You will now put the new public key on repo2's Deploy keys configuration at github.com, but now you have an ssh problem to deal with.

How can ssh tell which key to use if the repositories are hosted on the same github.com domain?

Your .ssh/config file points to github.com and it doesn't know which key to use when it's time to do the pull.

So I found a trick with github.com. You can tell your ssh client that each repository lives in a different github.com subdomain, in these cases, they will be repo1.github.com and repo2.github.com

So first thing is editing the .git/config files on your repo clones, so they look like this instead:

For repo1

[remote "origin"]
        url = "ssh://git@repo1.github.com:alice/repo1.git"

For repo2

[remote "origin"]
        url = "ssh://git@repo2.github.com:alice/repo2.git"

And then, on your .ssh/config file, now you will be able to enter a configuration for each subdomain :)

Host repo1.github.com
  HostName github.com
  User git
  IdentityFile /home/alice/.ssh/repo1.alice_github.id_rsa
  IdentitiesOnly yes

Host repo2.github.com
  HostName github.com
  User git
  IdentityFile /home/alice/.ssh/repo2.alice_github.id_rsa
  IdentitiesOnly yes

Now you are able to git pull origin master without entering any passwords from both repositories.

If you have multiple machines, you could copy the keys to each of the machines and reuse them, but I'd advise doing the leg work to generate 1 key per machine and repo. You will have a lot more keys to handle, but you will be less vulnerable if one gets compromised.

@vhermecz
Copy link

vhermecz commented Jun 8, 2020

I did not like the aliasing approach, and figured out there is a way to use multiple deploy keys in a less intrusive way via customizing GIT_SSH_COMMAND:
https://gist.github.com/vhermecz/4e2ae9468f2ff7532bf3f8155ac95c74

@FlorianBouron
Copy link

Didn't fully work for me, I needed to do extra steps, I wrote a gist on how I proceed if someone is interested: https://gist.github.com/FlorianBouron/208c77aff253fc178a4a0ad6639f1412

@zehuanli
Copy link

zehuanli commented Sep 23, 2020

Not sure is this something only related to me or not, but thought I might as well post it here if it helps anyone.

I had to change the url slightly in order to get it to work (putting : instead of /). It might have to do with the fact that the repository is under an Organization.

[remote "origin"]
        url = "ssh://git@repo1.github.com/alice/repo1.git" <-- original, doesn't work
        url = "ssh://git@repo1.github.com:alice/repo1.git" <-- works for me
                                         ^-- colon instead of slash

The second url is supposed to be the correct one. I guess it's a typo in the original post.

The following git remote commands also work:

git remote remove origin
git remote add origin git@repo1.github.com:alice/repo1.git

@floodico
Copy link

How to change hostname on github? I mean from git@github.com/alice/repo1.git to git@repo1.github.com/alice/repo1.git

@coezbek
Copy link

coezbek commented Dec 7, 2020

One key thing to realize with this approach is that the Host is just any type of string used by SSH for mapping, not a real subdomain on github.com. When you create the following .ssh/config:

Host mylittlepony
  HostName github.com
  User git
  IdentityFile /home/alice/.ssh/repo1.alice_github.id_rsa
  IdentitiesOnly yes

You can actually run:

git clone git@mylittlepony:alice/repo1.git

SSH will use the identifier mylittlepony and replace it with github.com (The HostName in the config)

@JSRossiter
Copy link

Not sure is this something only related to me or not, but thought I might as well post it here if it helps anyone.

I had to change the url slightly in order to get it to work (putting : instead of /). It might have to do with the fact that the repository is under an Organization.

[remote "origin"]
        url = "ssh://git@repo1.github.com/alice/repo1.git" <-- original, doesn't work
        url = "ssh://git@repo1.github.com:alice/repo1.git" <-- works for me
                                         ^-- colon instead of slash

The second url is supposed to be the correct one. I guess it's a typo in the original post.

The following git remote commands also work:

git remote remove origin
git remote add origin git@repo1.github.com:alice/repo1.git

The opposite was true for me, slash worked, colon did not

@fleetingbytes
Copy link

I'm struggling to make all of this work. With my repo logging_conf I have this:
In .git/config:

[remote "origin"]
	url = git@logging_conf.github.com:Nagidal/logging_conf.git
	; or I can use the ssh prefix, but then I need to change : to /
        ; url = ssh://git@logging_conf.github.com/Nagidal/logging_conf.git

then my .ssh/config:

Host logging_conf.github.com
    User git
    Preferredauthentications publickey
    IdentityFile ~/.ssh/github_deploy/logging_conf_deploy
    IdentitiesOnly yes
$ git push
ssh: connect to host logging_conf.github.com port 22: Connection timed out

@JSRossiter
Copy link

@Nagidal you need to have HostName github.com in your ssh/config

@fleetingbytes
Copy link

Thank you very much. I have completely overlooked that line. Now it works.

@SenkaWolf
Copy link

Are there any video tutorials on this method? I am trying to use multiple Github repos with one Plesk server however when I use the built-in git it always says 'key is already being used' when I try to add a second git. My brains just hurting trying to sort this out.

I see the .git config file but mines an https URL and looking at my file manager for Plesks .ssh folder I have id_rsa id_rsa.pub.

@nickcamel
Copy link

Give this guy a medal

@cvladan
Copy link

cvladan commented Apr 9, 2021

I did not like the aliasing approach, and figured out there is a way to use multiple deploy keys in a less intrusive way via customizing GIT_SSH_COMMAND:
https://gist.github.com/vhermecz/4e2ae9468f2ff7532bf3f8155ac95c74

Pay attention to @vhermecz solution as I believe it's the perfect one. It doesn't include editing of repository (.git/config) or editing of user's ssh configuration (~/.ssh/config).
Without any changes on repo or ssh config, by just providing ssh key files on specified places, everything works as it should in the first place.

Thanks, @vhermecz!

P.S. I sure hope it works on submodules; it should; as this is quite often my use case

@koo5
Copy link

koo5 commented Apr 28, 2021

P.S. I sure hope it works on submodules; it should; as this is quite often my use case

how could this work with submodules, if you want to do is just git clone <something>; which automatically gets the submodules too, in newer git versions, or you want to do git submodule update --init --recursive, or similar?
The only good solution seems to be to create a new github user for this purpose, or to switch to gitlab.

@cvladan
Copy link

cvladan commented May 11, 2021

P.S. I sure hope it works on submodules; it should; as this is quite often my use case

how could this work with submodules, if you want to do is just git clone <something>; which automatically gets the submodules too, in newer git versions, or you want to do git submodule update --init --recursive, or similar?
The only good solution seems to be to create a new github user for this purpose, or to switch to gitlab.

... submodules that are private repositories with different credentials from main repo, that is also private repo.

@koo5
Copy link

koo5 commented May 11, 2021

Not sure what you mean. At any case, github is dead-set on not supporting the only correct method, and instead pushing for bad workarounds. They even have a whole long docs page devoted to this brainwashing. I have to assume malice.

@raimondev
Copy link

Very userful! Thanks a bunch!

@simkimsia
Copy link

Thank you @cvladan for your shout at to @vhermecz solution.

I agree with your evaluation that it's better than fiddling with ssh config aliases.

Fiddling the ssh config aliases as excellently explained by @gubatron (and it's excellently explained!) would have been good enough for me. But the script method is slightly cleaner for me.

@gubatron
Copy link
Author

Crazy this gist has helped so many people since 2014, 8 years and counting.
(I still like my solution better than all the other scripts, still easier to understand and maintain)

@cristiancalara
Copy link

cristiancalara commented Feb 13, 2022

Hey guys

In the newer versions of git, there's a new configuration option - "core.sshCommand" https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresshCommand

As such, I think another approach (easier in my opinion) for handling the above would be to actually:

  1. Create a two new config files:
  • .ssh/config-alice-repo1
Host github.com
  IdentityFile /home/alice/.ssh/repo1.alice_github.id_rsa
  • .ssh/config-alice-repo2
Host github.com
 IdentityFile /home/alice/.ssh/repo2.alice_github.id_rsa
  1. When cloning the repo, set the core.sshCommand like this:
  • git -c core.sshCommand="ssh -F /home/ubuntu/.ssh/config-alice-repo1" clone ssh://git@github.com:alice/repo1.git
  • git -c core.sshCommand="ssh -F /home/ubuntu/.ssh/config-alice-repo2" clone ssh://git@github.com:alice/repo2.git

And that's it. Now, every time you'll do any git action, the proper ssh key / deploy key will be used.

If you already have a repo setup, you can modify the config using something like git config core.sshCommand "ssh -F /home/forge/.ssh/config-alice-repo1" (while in the repo1 folder).

@gubatron
Copy link
Author

Thank you for that update @cristiancalara

@alingse
Copy link

alingse commented Mar 1, 2022

hello everyone, I make a simple command tool to auto manage this, see https://github.com/alingse/git-ssh-key .
the command git-ssh-key your-repo-link will print the new rewrite alias repo link, auto will write to your ssh config
after add public key to your [private] repo, you can clone with the alias link

install

pip install git-ssh-key

example

$ git-ssh-key https://github.com/alingse/git-ssh-key.git
New repo address: git@github.com-f5851eb:alingse/git-ssh-key.git
New repo public rsa key: /Users/alingse/.ssh/github.com-f5851eb.id_rsa.pub


$ git clone git@github.com-f5851eb:alingse/git-ssh-key.git

( I haven't try it in Windows, but in Linux and Mac it works fine.

@hazardland
Copy link

hazardland commented Mar 28, 2022

hello everyone, I make a simple command tool to auto manage this, see https://github.com/alingse/git-ssh-key . the command git-ssh-key your-repo-link will print the new rewrite alias repo link, auto will write to your ssh config after add public key to your [private] repo, you can clone with the alias link

install

pip install git-ssh-key

example

$ git-ssh-key https://github.com/alingse/git-ssh-key.git
New repo address: git@github.com-f5851eb:alingse/git-ssh-key.git
New repo public rsa key: /Users/alingse/.ssh/github.com-f5851eb.id_rsa.pub


$ git clone git@github.com-f5851eb:alingse/git-ssh-key.git

( I haven't try it in Windows, but in Linux and Mac it works fine.

It worked, I was kind of sleepy and under deadline so I checked your code and risked to use it : D Hope build does not contain any backdoor

But on config file git clone says:

Bad owner or permissions on /home/ec2-user/.ssh/config

So to make it work it needs a quick fix:

chmod go-w ~/.ssh/config

Anyways thanks

@alingse
Copy link

alingse commented Mar 29, 2022

@hazardland aha, There is no backdoor, you can check the code in github (https://github.com/alingse/git-ssh-key and https://github.com/sorend/sshconf )
git-ssh-key only use https://github.com/sorend/sshconf to manage ssh config

So your git clone error message Bad owner or permissions is only because , /home/ec2-user/.ssh/config is not allow read

You can see some solution here
https://serverfault.com/questions/253313/ssh-returns-bad-owner-or-permissions-on-ssh-config
https://superuser.com/questions/348694/bad-owner-or-permissions-error-using-cygwins-ssh-exe

@hazardland
Copy link

@hazardland aha, There is no backdoor, you can check the code in github (https://github.com/alingse/git-ssh-key and https://github.com/sorend/sshconf ) git-ssh-key only use https://github.com/sorend/sshconf to manage ssh config

So your git clone error message Bad owner or permissions is only because , /home/ec2-user/.ssh/config is not allow read

You can see some solution here https://serverfault.com/questions/253313/ssh-returns-bad-owner-or-permissions-on-ssh-config https://superuser.com/questions/348694/bad-owner-or-permissions-error-using-cygwins-ssh-exe

Sorry I edited my answer, actually this command helped that day on EC-2 instance:

chmod go-w ~/.ssh/config

@kodekracker
Copy link

@emrahaydemir
Copy link

Hey guys

In the newer versions of git, there's a new configuration option - "core.sshCommand" https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresshCommand

As such, I think another approach (easier in my opinion) for handling the above would be to actually:

  1. Create a two new config files:
  • .ssh/config-alice-repo1
Host github.com
  IdentityFile /home/alice/.ssh/repo1.alice_github.id_rsa
  • .ssh/config-alice-repo2
Host github.com
 IdentityFile /home/alice/.ssh/repo2.alice_github.id_rsa
  1. When cloning the repo, set the core.sshCommand like this:
  • git -c core.sshCommand="ssh -F /home/ubuntu/.ssh/config-alice-repo1" clone ssh://git@github.com:alice/repo1.git
  • git -c core.sshCommand="ssh -F /home/ubuntu/.ssh/config-alice-repo2" clone ssh://git@github.com:alice/repo2.git

And that's it. Now, every time you'll do any git action, the proper ssh key / deploy key will be used.

If you already have a repo setup, you can modify the config using something like git config core.sshCommand "ssh -F /home/forge/.ssh/config-alice-repo1" (while in the repo1 folder).

I've been struggling with this problem for about 7 hours. this solution worked mysteriously and was very easy to implement. You didn't specify the part about generating new ssh keys. But it was easy to spot. Thank you very much...

@gubatron
Copy link
Author

gubatron commented Aug 5, 2022

@emrahaydemir that's really cool

@warrenkeil
Copy link

Hey guys

In the newer versions of git, there's a new configuration option - "core.sshCommand" https://git-scm.com/docs/git-config#Documentation/git-config.txt-coresshCommand

As such, I think another approach (easier in my opinion) for handling the above would be to actually:

  1. Create a two new config files:
  • .ssh/config-alice-repo1
Host github.com
  IdentityFile /home/alice/.ssh/repo1.alice_github.id_rsa
  • .ssh/config-alice-repo2
Host github.com
 IdentityFile /home/alice/.ssh/repo2.alice_github.id_rsa
  1. When cloning the repo, set the core.sshCommand like this:
  • git -c core.sshCommand="ssh -F /home/ubuntu/.ssh/config-alice-repo1" clone ssh://git@github.com:alice/repo1.git
  • git -c core.sshCommand="ssh -F /home/ubuntu/.ssh/config-alice-repo2" clone ssh://git@github.com:alice/repo2.git

And that's it. Now, every time you'll do any git action, the proper ssh key / deploy key will be used.

If you already have a repo setup, you can modify the config using something like git config core.sshCommand "ssh -F /home/forge/.ssh/config-alice-repo1" (while in the repo1 folder).

Thanks! This worked for me

@la4gia
Copy link

la4gia commented Apr 17, 2023

After creating and adding your deploy keys, you can update your .ssh/config file like so:

Host github.com-repo00
  Hostname github.com
  Identityfile=~/.ssh/repo00-key

Host github.com-repo01
  Hostname github.com
  Identityfile=~/.ssh/repo01-key

You can then clone with:
git clone git@github.com-repo00:username/repo00.git
git clone git@github.com-repo01:username/repo01.git

@AndreiCherniaev
Copy link

Thanks. The same example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment