313

Here is my problem. We have a private NPM registry which only works in VPN. I would like to have a fallback registry https://registry.npmjs.org so that when I am out of VPN it works seamlessly.

P.S. Currently I am using npmrc which does a good job in switching between .npmrc files as a workaround

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
Abhijit Mazumder
  • 8,641
  • 7
  • 36
  • 44
  • 9
    I actually would love to know the same thing. Maybe either have my private registry get pinged first and if it fails fallback to the public registry (from local fallback, not one setup on the private server). Or alternatively switching my registry based on my wifi name. – ProLoser Jul 03 '16 at 20:32
  • 2
    for lost souls like myself, a [usefull doc to npmrc](https://docs.npmjs.com/configuring-your-registry-settings-as-an-npm-enterprise-user#using-npmrc-to-managing-multiple-profiles-for-different-registries) – Andreas Jun 25 '20 at 12:06
  • https://stackoverflow.com/a/67067209/4989208 – Swanky Coder Nov 11 '21 at 10:55
  • Give an upvote to [Allow list of registries (to be used as a per-project .npmrc override) #340](https://github.com/npm/rfcs/issues/340) perhaps? Actually maybe https://github.com/npm/rfcs/issues/427 is better, mentioned this there – Ben Creasy Feb 13 '23 at 23:47

14 Answers14

334

You can have multiple registries for scoped packages in your .npmrc file. For example:

@polymer:registry=<url register A>
registry=http://localhost:4873/

Packages under @polymer scope will be received from https://registry.npmjs.org, but the rest will be received from your local NPM.

Pierre F
  • 1,332
  • 15
  • 33
José Alberto Ruiz
  • 3,375
  • 1
  • 9
  • 4
  • 21
    Thank you for this advice. Could you please tell, is it possible to add authentication to these scoped registries? Because I need _auth key to my main registry. – Bloomca Oct 06 '16 at 08:52
  • 5
    What is a scoped package? I've never heard of this. – jcollum Oct 16 '16 at 00:50
  • this answer really helped me and my coworkers out. thanks! – gonzofish Jan 23 '17 at 16:06
  • 3
    @jcollum, Scoped packages are simply packages that are grouped (or scoped) via a namespace. See https://docs.npmjs.com/misc/scope for details. Scoping can be used to associate several packages (like @angular) which makes it easy to know that a package (@angular/core) is part of Angular, but could also be a company like @mycompany/mypackage. – PatS Jun 22 '18 at 21:13
  • I guess this is gem fury specific, but I got auth to work using `npm config set @myscope:registry https://npm.fury.io//username/` This command just creates/updates the .npmrc file where appropriate. – Phil Sep 14 '18 at 19:06
  • 19
    Is this possible without scoped packages? let's say if we are looking for this specific package go to this registry, otherwise go to that registry – PinguinoSod Nov 27 '18 at 14:16
  • 3
    @PinguinoSod, No it is still (as of Dec 2019) not possible for non-scoped packages. Sonatype is the only solution that I know of. See https://stackoverflow.com/a/50995915/3281336 – PatS Dec 18 '19 at 22:17
  • 1
    don't know if this helps or not but we used a scoped registry with auth and the public npm registry with an .npmrc by @scope:registry=https://orgname.pkgs.visualstudio.com/_packaging/reponame/npm/registry always-auth=true registry=https://registry.npmjs.org – dev null Jan 21 '21 at 15:52
  • It is possible to do this now with `npmrc`. Please refer to my answer below: https://stackoverflow.com/a/67067209/4989208 – Swanky Coder Apr 13 '21 at 00:24
  • Is there also a way to explicitly specify multiple registries to try in order for a single scope (without only falling back to the one default registry)? – sschuberth Nov 19 '21 at 10:05
111

On version 4.4.1, if you can change package name, use:

npm config set @myco:registry http://reg.example.com

Where @myco is your package scope.

You can install package in this way:

npm install @myco/my-package

For more info: https://docs.npmjs.com/misc/scope

Javier C.
  • 7,859
  • 5
  • 41
  • 53
Gilberto Alexandre
  • 2,227
  • 1
  • 18
  • 20
36

I believe the top-voted answer might be outdated. As of June 2021, there is a much easier way to do this using the npmrc npm library.

1. Install npmrc

To install npmrc, on the command line, run npm i npmrc -g

2. Create your first npm profile

After installing npmrc, you can create a profile to access your custom (maybe company's) registry.

To create an npm Enterprise profile, on the command line, run npmrc -c name-of-profile. For example, to create a profile called "work", run the following command: npmrc -c work

To set an npm Enterprise registry for the profile, run the following command, replacing your-company-registry with the name of your company's npm Enterprise registry:

npm config set registry https://registry.your-company-registry.npme.io/

3. Create a profile for the public npm registry

After you have created your npm Enterprise profile, you can create a second profile for a different registry, such as the public npm registry.

To create a profile for the public registry, on the command line, run npmrc -c name-of-profile. For example, to create a profile called "open-source", run npmrc -c open-source. To set the public registry for your open source profile, run the following command: npm config set registry https://registry.npmjs.org/

4. Switch profiles with npmrc

To switch profiles, on the command line, run the following command, replacing profile-name with the name of your profile:

npmrc profile-name

Swanky Coder
  • 862
  • 1
  • 8
  • 23
  • 5
    How can I handle the use case where the scope name is used on multiple repositories? For eg. @test/a on npm and @test/b on github – Shawn Mclean Nov 03 '21 at 04:15
  • @ShawnMclean Can you please elaborate on the question? I didn't quite understand what you are trying to do. – Swanky Coder Nov 11 '21 at 10:52
  • How do you set different credentials for different registries? – Murat Can OĞUZHAN Aug 23 '22 at 07:57
  • 2
    @Murat: Once you switched to the profile, you can execute in the command line: `npm config set //pkgs.dev.azure.com/myCompany/_packaging/npm/:username=myCompanyUsername && npm config set //pkgs.dev.azure.com/my_company/_packaging/npm/:_password="...."` – Francesco Sep 15 '22 at 11:46
  • npm enterprise was deprecated/sunset in 2020 – joshvito Apr 14 '23 at 17:14
  • @joshvito The npmrc library still seems to be working great. Remove the outdated link for npm enterprise from the answer. Thanks! – Swanky Coder Apr 17 '23 at 23:13
28

Not the best way but If you are using mac or linux even in windows you can set alias for different registries.

##############NPM ALIASES######################
alias npm-default='npm config set registry https://registry.npmjs.org'
alias npm-sinopia='npm config set registry http://localhost:4873/'
owais
  • 4,752
  • 5
  • 31
  • 41
  • 6
    A similar solution is to setup an alias that passes the --registry option to npm. This has the same effect, but only for the single command. Syntax is `alias npm-sin=npm --registry https://localhost:4873/` – PatS Jul 17 '19 at 21:32
28

For anyone looking also for a solution for authentication, I would add on the scoped packages solution that you can have multiple lines in your .npmrc file:

//internal-npm.example.com:8080/:_authToken=xxxxxxxxxxxxxxx
//registry.npmjs.org/:_authToken=yyyyyyyyyy

Each line represents a different NPM registry

Gregra
  • 773
  • 8
  • 22
  • 5
    I would use the command `npm login --registry=npm.example.com`. It will store the login credentials (authTokens) in the .npmrc file in your user folder, so you don't need to have it in the source code (https://docs.npmjs.com/cli/adduser) – magikMaker Nov 26 '18 at 16:57
  • it worked for me, thanks, Basically i had private nexus registry to my lib but my Lib has another few dependencies which need to install from `registry.npmjs.org`, this worked for me – Chanuka Asanka Jul 23 '20 at 08:32
13

Since it has been a couple years and it doesn't seem possible to do this (using npm alone), a solution to this problem is to use the Nexus Repository Manager (from Sonatype). Nexus supports multiple repositories, lets you order them, and also proxies/caches to improve speed.

A free version and pro/paid version exist. The feature that supports this is described at: https://help.sonatype.com/repomanager3/node-packaged-modules-and-npm-registries

The relevant information is duplicated below so if/when the above URL/link stops working the information is still here.

A repository group is the recommended way to expose all your npm registries repositories from the repository manager to your users, without needing any further client side configuration. A repository group allows you to expose the aggregated content of multiple proxy and hosted repositories with one URL to npm and other tools.

It lets you create private npm registries

A private npm registry can be used to upload your own packages as well as third-party packages.

And

To reduce duplicate downloads and improve download speeds for your developers and CI servers, you should proxy the registry hosted at https://registry.npmjs.org. By default npm accesses this registry directly. You can also proxy any other registries you require.

So a quick bulleted list of things you do to get this working is:

  • Install Nexus

  • Create a local/private repo (or point to your private repo on another server)

  • Create a GROUP that lists your private repo, and the public repo.

  • Configure your $HOME/.npmrc file to point to the "GROUP" just created.

  • Publish your private npm packages to the local repo.

  • Users now can run a one time setup.

npm config set registry https://nexus/content/groups/GROUP

  • Then users can install both public or private packages via npm install. npm install my-private-package npm install lodash any-other-public-package

And both your public and private packages can be installed via a simple npm install command. Nexus finds the package searching each repo configured in the group and returns the results. So npm still thinks there is just one registry but behind the curtain there are multiple repos being used.

IMPORTANT NOTE: When you publish your components, you'll need to specify the npm publish --registry https://nexus/content/repositories/private-repo my-private-package command so your package is published to the correct repo.

PatS
  • 8,833
  • 12
  • 57
  • 100
  • can i configure both registry(for deploying my own artifacts and for pull public artifacts) in the .npmrc file so that i don't have to mentioned everytime i am doing npm publish? For pushing my artifacts i am using separate npm repository and for pull all artifacts i am using virtual repository. Please help me to configure both in .npmrc file. – Anshita Singh Mar 30 '20 at 09:18
  • 1
    @AnshitaSingh I just went through this. If you like me have a different repository for publishing (e.g. `npm-private` instead of `npm-group`), you can override the `registry`-key in the `package.json` of your project (see `https://blog.sonatype.com/using-nexus-3-as-your-repository-part-2-npm-packages` for details). Using `npm config set registry ` you can set it to e.g. `npm-group`, which contains `npm-registry` (forwarding repository) and `npm-private` (your own repository). I used this solution, because getting artifacts off of local GitLab CE was too complicated. – Igor May 17 '20 at 23:02
13

You can use multiple repositories syntax for the registry entry in your .npmrc file:

registry=http://serverA.url/repository-uri/
//serverB.url/repository-uri/
//serverC.url/repository-uri/:_authToken=00000000-0000-0000-0000-0000000000000
//registry.npmjs.org/

That would make your npm look for packages in different servers.

  • Yes, but the `serverA`, `serverB` and `serverC` example repositories are all from our internal network, wont work for you. I dont know if it's suitable for you but if think it is you can try deploy a Nexus Repository Manager for the internal repos. – Fernando Fernandes Sep 24 '18 at 16:01
  • 1
    according to [this response](https://stackoverflow.com/a/53281483/2512765) the double slash has no meaning, so you are just setting the keys without values – PinguinoSod Nov 27 '18 at 14:09
  • 1
    As far as I could see from the npm/ini property file reader, indeed, the // will be read as key with no value. By the way, like the scoped sections, it will get stored as secondary registry servers. They will get into npm and will be processed as registry configuration servers accordingly to npm's internal evaluation algorithm. – Fernando Fernandes Nov 29 '18 at 13:18
  • 1
    Have anybody tried this solution. Does it works and helps to configure a fallback repository ? – Luke P. Issac Sep 27 '19 at 05:22
  • 4
    Is there any official documentation describing this functionality? I cannot find any. – Julian Sep 30 '20 at 22:10
4

Some steps you can try. (its how we do it at my workplace)

  • Create a registry group with two (or more) repository source address. One would be your internal private and the other a proxy to npmjs giving priority to the internal one.
  • Make this group your registry in the .npmrc file. This way npm will always try to get it from the internal one, if not found get it from the proxy

Hope that helps.

Kaus2b
  • 747
  • 4
  • 12
  • 8
    How does one create a registry group in npm? What does that mean? – Tuupertunut Sep 28 '16 at 11:04
  • 1
    @Tuupertunut registry Easiest way to do it would be to use some kind of repository manager, like sonatype nexus. It can host private registries, proxy in npmjs as well as create repository groups. – Kaus2b Sep 29 '16 at 15:28
3

I had the same issue and I've tried many solutions that didn't work, now i encountered that by using different scoops for my npm private packages. Now, I can use multiple registries with same .npmrc file like that :

  • .npmrc : (You can put as many packages you want)
@scop1:registry=https://gitlab.example.com/api/v4/projects/<project1_id>/packages/npm/
@scop2:registry=https://gitlab.example.com/api/v4/projects/<project2_id>/packages/npm/

//gitlab.example.com/api/v4/projects/<project1_id>/packages/npm/:_authToken=${GITLAB_TOKEN}
//gitlab.example.com/api/v4/projects/<project2_id>/packages/npm/:_authToken=${GITLAB_TOKEN}
  • with this solution, is there a way to do this for packages that aren't scoped? Looking in my package.json i see a bunch that don't have `@scope` that I know are from a private repo. so they are just listed as `"private-repo": "1.0.0"` – Keith E. Truesdell Jun 09 '23 at 15:26
2

I encounter the same problem when my company set up its own registry, so I heavily rework on proxy-registry into proxy-multi-registries to solve this problem. Hope it will also helps you.

xymopen
  • 31
  • 2
2

As of 13 April 2020 there is no such functionality unless you are able to use different scopes, but you may use the postinstall script as a workaround. It is always executed, well, after each npm install:

Say you have your .npmrc configured to install @foo-org/foo-pack-private from your private github repo, but the @foo-org/foo-pack-public public package is on npm (under the same scope: foo-org).

Your postinstall might look like this:

"scripts": {
    ...
    "postinstall": "mv .npmrc .npmrcc && npm i @foo-org/foo-pack --dry-run && mv .npmrcc .npmrc".
}

Don't forget to remove @foo-pack/foo-org from the dependencies array to make sure npm install does not try and get it from github and to add the --dry-run flag that makes sure package.json and package-lock.json stay unchanged after npm install.

  • to clarify for those who may not know: postinstall is only executed after local package installs (i.e. `npm install`) not dependency/devDependency installs *for* that package (i.e. `npm install `) – SgtPooki Jan 21 '21 at 22:35
2

My approach was to make a slight command line variant that adds the registry switch.

I created these files in the nodejs folder where the npm executable is found:

npm-.cmd:

@ECHO OFF
npm --registry https://registry.npmjs.org %*

npm-:

#!/bin/sh
"npm" --registry https://registry.npmjs.org "$@"

Now, if I want to do an operation against the normal npm registry (while I am not connected to the VPN), I just type npm- where I would usually type npm.

To test this command and see the registry for a package, use this example:

npm- view lodash

PS. I am in windows and have tested this in Bash, CMD, and Powershell. I also

Mark Whitfeld
  • 6,500
  • 4
  • 36
  • 32
1

I use Strongloop's cli tools for that; see https://strongloop.com/strongblog/switch-between-configure-public-and-private-npm-registry/ for more information

Switching between repositories is as easy as : slc registry use <name>

davidcyp
  • 649
  • 8
  • 18
0

No, NPM does not support multiple registry except for scoped one.

Refer to: https://docs.npmjs.com/cli/v7/using-npm/scope

Vincent
  • 1,178
  • 1
  • 12
  • 25