When you are developing in NodeJS it’s often useful to be able to install private modules.

The main ways to do that are:

  1. Github Packages using Personal Access Token (PAT)
  2. Private Github repo using Personal Access Token (PAT)
  3. 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

Host github.com-repo3
  Hostname github.com

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:




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.

If you liked this post you might find my daily linkblog interesting, and there's also a weekly newsletter.

For enquiries about my consulting, development, training and writing services, aswell as sponsorship opportunities contact me directly via email. More details about me here.

subscribe via RSS