One of the really cool, more obscure, features of npm is the ability to install git repos directly via the
npm install command.
The problem is that installing packages this way, the ssh username will be saved in the package.json file. Basically, making this dependency useless for the rest of your team.
npm install -s git+ssh://<username>@<hostname>:<path>
After installing a package via a command like the one above. Your dependency in package.json, instead of the common semver versioning number (^1.0.0.), would instead be the exact url used to install the package, username and all.
So, if that package.json gets commited, no one else on your team would be able to
npm install the dependencies as they wouldn’t have username’s ssh credentials.
Example package.json file with private git repo dependency
Help us ssh! (the solution)
The clue to solving this problem is in the url’s protocol ‘git+ssh’. Npm is basically using 2 different tools, git and ssh, to access the contents of your module. So, if we could access that module without typing our credentials in the url, problem solved!
Thankfully, ssh has a very helpful way of configuring it via an
~/.ssh/config file. In it you can alias different hosts and typein specific configurations for each of these hosts.
Example ~/.ssh/config file
With this last config file as an example, I could now type
ssh myreal.server.com and it would try connecting to server.com using foo users private key. But the real money maker for our situation is that, we could also now type
npm install -s git+ssh://server.com:/path/to/privateModule.git and our package.json would set the dependency field to:
Yay, no user specificity!
At this point you’re either really happy this solved a HUGE problem you had, or you’re kinda bummed you know what I’m gonna say next. Any developer that uses this, needs to have the same alias for the same hostname in ~/.ssh/config. Otherwise, ssh won’t know what credentials to use for what server ¯\(ツ)/¯.
Note: this doesn not mean developers need to share private keys!
Developers with different config files, only sharing the needed information to be able to install private modules from server.com
One last important difference, is that we have to use a different versioning scheme. With regular npm registry modules, you could simply add it as the semver value to a packages json entry in the dependencies field.
But since with this method, the right-hand side will be a url, we need to append to that url a commit-ish (I swear thats the legit parlance) code. And that means any branch name, commit hash or tag. Also important to note, we cant use a package.json’s version number.
npm install --save git+ssh://server.com:/path/to/privateModule.git#dev
installs whatever version of the module the dev branch points to
npm install --save git+ssh://server.com:/path/to/privateModule.git#v1.0.4
installs the version of the module pointed at by tag v1.0.4
npm install --save git+ssh://server.com:/path/to/privateModule.git#1b1d8f5
installs the version of the module at commit 1b1d8f5