Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michaeljdennis/99da2a7c246c04db7f3305919863ef8e to your computer and use it in GitHub Desktop.
Save michaeljdennis/99da2a7c246c04db7f3305919863ef8e to your computer and use it in GitHub Desktop.
How to use different ssh deploy keys for multiple private github repositories with Golang Modules (go mod)

How to use different ssh deploy keys for multiple private github repositories with Go Modules

Let's assume you are using Go Modules and have a go.mod file that contains multiple private repos each with a different ssh key. How can you get go mod download to do the right thing -- i.e. use ssh key A with private repo A and ssh key B with private repo B?

Ok, here we go!

Let's assume you have some github.com user with multiple private repos:

https://github.com/someuser/private-repo-1

https://github.com/someuser/private-repo-2

and a go.mod file that looks something like this:

module github.com/alice/repo

go 1.11

require (
	github.com/someuser/private-repo-1 v0.0.0
	github.com/someuser/private-repo-2 v0.0.0
	github.com/bob/public-repo v0.0.0
)

As part of an automated process (e.g. running go mod download in a Docker container) you need to clone these private repos without using a password and make sure that you use the right key with its corresponding repo.

(I'm skipping over all the ways to try and get this to work that don't)

In order to access the repos we are going to use Github deploy keys. Because a given deploy key can only be added to one specific repo, you'll need to generate a keypair for each:

$ ssh-keygen -t ecdsa -C "someuser@domain.com"
...
> private1_id_ecdsa, private1_id_ecdsa.pub # keys for private-repo-1

$ ssh-keygen -t ecdsa -C "someuser@domain.com"
...
> private2_id_ecdsa, private2_id_ecdsa.pub # keys for private-repo-2

Next you'll add each key to its corresponding repo via Settings > Deploy keys in Github:

private1_id_ecdsa.pub => github.com/someuser/private-repo-1

private2_id_ecdsa.pub => github.com/someuser/private-repo-2

Now you'll need to tell your ssh client what private key to use for which repo. Open up ~/.ssh/config and add:

Host private1.github.com
  HostName github.com
  IdentityFile ~/.ssh/private1_id_ecdsa
  IdentitiesOnly yes
  
Host private2.github.com
  HostName github.com
  IdentityFile ~/.ssh/private2_id_ecdsa
  IdentitiesOnly yes

This tells ssh when it sees a repo at private1.github.com/foo to use the private1_id_ecdsa deploy key, and likewise a repo at private2.github.com/bar should use the private2_id_ecdsa deploy key.

Ok great, but your repos are github.com/someuser/private-repo-1 and github.com/someuser/private-repo-1, so how can we make this work correctly with go mod download?

Bring the Magic

Edit your ~/.gitconfig file and add:

[url "git@private1.github.com:someuser/private-repo-1"]
        insteadOf = https://github.com/someuser/private-repo-1

[url "git@private2.github.com:someuser/private-repo-2"]
        insteadOf = https://github.com/someuser/private-repo-2

Now when go mod download encounters a url in your mod file like https://github.com/someuser/private-repo-1 it will automagicallly rewrite the host so your ~/.ssh/config picks it up correctly and uses the right key. \:D/ Yay!

p.s. You won't need to use GOPRIVATE when calling go mod -- it will just work -- but you might want to anyway if you're concerned about info leakage.

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