develop

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:

  1. make sure you add npm bearer token to the active realms under Security/Realms
  2. make sure you don’t add a trailing slash / when you run npm 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