Host your own npm registry

Post image

So you want your own npm registry?

In the Lab we like to experiment with technologies and methods, but do not want to share everything with the world. So sooner or later we wished to have our own npm-registry, so that we can ‘inner-source publish’ components and libraries and tinker with the full CI/CD-workflow of the release process.

So we looked around and found some free offerings:

And as we have our Lab-Kubernetes-Cluster running, we decided to self-host ’nexus repository’ for now.

Helm

Sonatype is providing helm-charts for their nexus repository oss , so we want to use these.

# add helm repo
helm repo add sonatype https://sonatype.github.io/helm3-charts/

# install with your values.yaml, see below
helm upgrade --install nexus-rm sonatype/nexus-repository-manager -n nexus-rm --create-namespace --values values.yaml

If you need to uninstall, you can simply use helm uninstall nexus-rm -n nexus-rm.

We use GitOps with ArgoCD for deployment of the helm-chart to our Lab-Cluster, but that is a different story. For now we just want to look at the manual helm deployment and the post-installation steps.

Individual values.yaml

You might want to customize some details on the first installation:

  • resources & limits for the nexus-pod: we used cpu: 2 and memory: 4Gi as requests and doubled the values for the limits
  • your preferred storageClass for persistence
  • maybe the size of the PV, default is 8 Gi - this is for the ‘default’, you can also configure any S3-blobstore for your repos later
  • the ingress-hosts and activate let’s encrypt TLS

Example values.yaml for the ingress:

ingress:
  enabled: true
  ingressClassName: nginx
  annotations:
    ...
    <ingress specific annotations for TLS and letsencrypt>
    ...
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hostPath: /
  hostRepo: repo.<your host>
  tls:
    - secretName: <your secret name>
      hosts:
        - repo.<your host>

Now you can install the repository manager - after some reconciliation, the repo is hopefully available under your specified URL https://repo.<your host>.

Post-Installation steps

The initial password for the admin user is written to /nexus-data/admin.password in the container, so get some shell to the container and obtain the password.

After that you will be able to log in to the Nexus Repository Manager’s Web-Interface.

Deactivate anonymous access

You might want to go to ‘Security / Anonymous Access’ and uncheck ‘Allow anonymous users to access the server’ if you want to keep your packages private.

Activate npm Bearer Token Realm

To enable npm-authentication, you have to activate ’npm Bearer Token Realm’ in ‘Security / Realms’.

Otherwise you’ll see Unable to authenticate, need: BASIC realm="Sonatype Nexus Repository Manager".

Take three: create a group of npm repositories

Let’s name our repositories ’npm-lab-hosted’ (for packages stored in your nexus), ’npm-lab-proxy’ (proxy for registry.npmjs.org) and group them by ’npm-lab-group’.

Minimal privileges: create a role & user for npm install

If we want to use our published packages, we need credentials for accessing our package-repository.

We create a role ’npm-read’ and assign the following privilege: `nx-repository-view-npm-npm-lab-group-read``

Create a user ’npm-read’ that has role ’npm-read’.

Now encode the credentials using echo -n 'myuser:mypassword' | openssl base64 and construct your .npmrc-file:

registry = https://repo.<your host>/repository/npm-lab-group/
email=<your email>
always-auth=true
_auth=<myuser:mypassword base64-encoded>

Copy the .npmrc to the root of your npm-project. If everything is right, you should now be able to npm install <any package> from either your hosted-repo (your own published packages) or the proxy-repo (packages published in registry.npmjs.org).

Minimal privileges: create a role & user for npm publish in your CI/CD pipeline

To publish packages to our repository from our CI/CD-pipelines, we need credentials with appropriate “write”-permissions for our npm-repo.

We create another role ’npm-publish’ and assign the following privileges:

  • nx-repository-view-npm-npm-lab-hosted-add
  • nx-repository-view-npm-npm-lab-hosted-edit
  • nx-repository-view-npm-npm-lab-hosted-read

This gives the user API-access to the hosted repo.

Then create a user ’npm-publish’ that has role ’npm-publish'.

Now encode the credentials using echo -n 'npm-publish:<mypassword>' | openssl base64 and construct your .npmrc-file:

registry = https://repo.<your host>/repository/npm-lab-hosted/
email=<your email>
always-auth=true
_auth=<myuser:mypassword base64-encoded>

Use the .npmrc file as secret in your CI/CD-pipeline. If everything works as expected, you should now be able to npm publish --repository https://repo.<your host>/repository/npm-lab-hosted/ (as workaround ) to your hosted-repo (your own published packages).

Troubleshooting

As you are experimenting with users, npmrc and so on, please be aware, that the credentials you have useed with npm login previously are stored in your npm user-config, see npm config edit. So if you keep getting Unable to authenticate like below, please try to delete the saved credentials:

npm ERR! code E401
npm ERR! Unable to authenticate, need: BASIC realm="Sonatype Nexus Repository Manager"

npm publish-workflow

You just have to setup a local npm-repository with npm init, write some code and test… then finally:

  • set the current version and tag using npm version v0.0.1
  • git push
  • npm publish to upload the package to our registry

We can easily automate the last step using a CI/CD-pipeline, e.g as Github Action , that runs on the release of a tagged version:

name: Publish to NPM
on:
  release:
    types: [created]
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: materialize .npmrc
        env:
          NPMRC: ${{secrets.NPMRC}}
        run: |
                    echo $NPMRC | base64 -d > .npmrc
        shell: bash

      - name: Publish package on NPM 📦
        run: |
                    npm publish --registry https://repo.<your host>/repository/npm-lab-hosted/

The Action, that runs on release of a tagged version, materializes the base64-encoded .npmrc from the ‘NPMRC’-Secret (with credentials for user npm-publish, see above) and uses the credentials to publish the package to your private hosted repository.

Conclusion

Nexus Repository Manager is easy to install and with a little setup, you are able to use it as private npm-registry and integrate it in your CI/CD-Workflows. But there is more - we can also use it for helm-, go- and python-packages if we like.

You May Also Like