Self-hosted nexus for private scoped npm packages
Setting up a self-hosted Nexus artifact repository for private, scoped package hosting.
If you develop your own private packages to be shared internally, but you want to make them scoped e.g. @my-team/my-package
, you’ll need to either host them with a pro or teams account with NPM, or you’ll have to self-host an artifact repository.
I decided to give the self-hosted route a try with Nexus Respository OSS. Luckily, they supply a docker container image. Best to create a volume to persist the data over restarts first and then start the container with:
$ docker volume create nexus-data
$ docker run -d -p 8081:8081 --name nexus -v nexus-data:/nexus-data --restart always sonatype/nexus3
Once it has started up, you’ll need to get the random admin password with:
$ docker exec -it nexus cat /nexus-data/admin.password
Now you can navigate your browser to your server on port :8081
and login as an administrator to configure the npm repository.
Switch to the Server Administration and Configuration tab and open Repositories. Here you can create a new repository and remove the default ones you don’t care about. Most of the defaults are fine for a npm (hosted) repository, but you need to choose a name. The chosen name will form part of your repository url e.g. http://mydomain.name:8081/repository/NAME
I named my repository npm
to keep it simple.
When I first tried to publish a package, I got stuck on getting the authentication working and kept getting an error like this:
npm ERR! code E401
npm ERR! Unable to authenticate, need: BASIC realm="Sonatype Nexus Repository Manager"
I searched a bit and found some helpful suggestions on Stack Overflow and this comment, after which I finally got it working.
If you’re getting the same error as above:
- make sure you add npm bearer token to the active realms under Security/Realms
- make sure you don’t add a trailing slash
/
when you runnpm login --always-auth=true --registry=http://mydomain.name:8081/repository/npm
You can then add a .npmrc file to your code repo if you want to only use your own registry for a specific scope e.g. for @my-team
do:
//mydomain.name:8081/repository/npm:always-auth=true
//mydomain.name:8081/repository/npm:_auth=$NPM_TOKEN
@my-team:registry=http://mydomain.name:8081/repository/npm
The $NPM_TOKEN
will be populated from the earlier npm login
command. NOTE: Do not push any secrets to your source control.
To make sure you publish to the self-hosted repository, change your package.json to indicate your URL in the publishConfig
section.
{
...,
"publishConfig": {
"registry": "http://mydomain.name:8081/repository/npm"
}
}
If you want to remember your custom registry for your scope, you can also set npm config with:
$ npm config set @my-team:registry http://mydomain.name:8081/repository/npm