Npm installing multiple private Github repos using ssh aliases
2022-04-21 17:10:00 +07:00 by Mark Smith
When you are developing in NodeJS it’s often useful to be able to install private modules.
The main ways to do that are:
- Github Packages using Personal Access Token (PAT)
- Private Github repo using Personal Access Token (PAT)
- Private Github repo using Deploy Keys
Apparently (1) is the most popular among developers, however it requires setup and management of additional workflows to create the Github Package.
(2) Only works for a maximum of 1 private repo.
(3) Works for 1 private repo, and can be extended using ssh aliases to work with multiple private repos.
Deploy keys are also more granular in terms of security than PAT.
This article focuses on method (3).
Github has an example repo that demonstrates how to install a private repo using deploy keys. It’s worth testing that out.
If you try the same methodology for installing more than 1 private repo in the same workflow, you’ll run into an issue. The reason being that Github doesn’t allow you to re-use the same deploy key across repos, and by default npm will use the default ssh private key (~/.ssh/id_rsa), of which there is only one.
However if you configure ssh to use aliases, you can specify a different private key for each alias, and then use those aliases in your package.json to specify the private module dependency.
Read more details about how to do that in the Github docs.
For example if you had 3 private repos:
- username/repo1
- username/repo2
- username/repo3
Where repo1 installs both repo2 and repo3, then add an ssh config ($HOME/.ssh/config) as follows:
Host github.com-repo2 Hostname github.com IdentityFile=/home/user/.ssh/private_key_repo2 Host github.com-repo3 Hostname github.com IdentityFile=/home/user/.ssh/private_key_repo3
Then specify the modules like so in repo1’s package.json:
"dependencies": { … "repo2": "git+ssh://[email protected]:username/repo2", "repo3": "git+ssh://[email protected]:username/repo3", … }
It’s important to specify the protocol correctly. Without ‘git+ssh://‘ the install completes but none of the files actually get installed. Instead some type of symlink gets created. At least that’s what happened in my tests.
Store your private keys in Github secrets, and before your install step, create the private keys on the filesystem from those secrets:
/home/user/.ssh/private_key_repo2
and
/home/user/.ssh/private_key_repo3
Now in your repo1 workflow you should be able to install all repo1 dependencies using:
npm install
It’s worth having a verify step after install that lists the installed files using ls -l and/or tree.