How to use Verdaccio with GitHub registry
Juan Picado
Posted on March 22, 2020
I've been asked for this couple of times and I want to share how you can achieve a seamless integration GitHub with Verdaccio. Node.js package managers only allow using one registry when you are running an eg: npm install
unless you modify the .npmrc
and add some specific configuration, but frankly, we can do better using a proxy.
Generating the Token at GitHub
First of all, we need to understand the GitHub registry is not a conventional registry, it does not support all npm
commands you are get used to (eg: npm token
).
I'd recommend you read first the official documentation at GitHub how to use packages.
Once you have set up and created a personal token in their User Interface (remember you cannot use npm adduser
). Copy the token from the website and proceed to log in to your terminal.
$ npm login --registry=https://npm.pkg.github.com
> Username: USERNAME
> Password: TOKEN
The last thing is recovering the token generated by the GitHub registry in the ~/.npmrc
file and find the line to verify npm you can use npm
commands against GitHub registry.
//npm.pkg.github.com/:_authToken=TOKEN{% raw %}`.
```
One optional step is to publish a package, I have already one published one for my example below.
> This step is required if you have not published packages, otherwise, you don't need to log in, just copy the token.
Great, you have a **token** and that's all you need for *Verdaccio*.
### Installing Verdaccio
Let's imagine you don't know anything about [Verdaccio](https://verdaccio.org/). So here is what it does.
**Verdaccio is a lightweight private proxy registry build in Node.js**
and with straightforward installation, with no dependencies aside to have installed Node.js.
```
npm install --global verdaccio
```
to run *Verdaccio* just run in your terminal,
```
ā verdaccio
warn --- config file - /Users/user/.config/verdaccio/config.yaml
warn --- Verdaccio started
warn --- http address - http://localhost:4873/ - verdaccio/4.5.0
```
for further information I'd recommend read our [documentation](https://verdaccio.org/docs/en/installation).
For this article, we will focus on the **proxy**, which is the most powerful and popular feature by far.
### Hooking the GitHub registry
First of all, you need a published package in the registry, here is mine and as you can see **GitHub only support scoped packages**.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/oydvxn9kuve9ttcsoypq.png)
This example is about how to fetch packages from **npmjs** and **GitHub** registries at the same time without modify the `.npmrc` file.
#### Uplinks
Open the verdaccio configuration file (eg: `/Users/user/.config/verdaccio/config.yaml`) and update the `uplinks` section adding a new registry.
```
uplinks:
npmjs:
url: https://registry.npmjs.org/
github:
url: https://npm.pkg.github.com
auth:
type: bearer
token: xxxx
```
For demonstration purposes let's copy the token in the example above, populate the config file with `token` is not the best approach, I recommend using *environment variables* with **auth** property, read more about it [here](https://verdaccio.org/docs/en/uplinks#auth-property).
#### Package Access
To install packages, we need the list of dependencies in your `package.json` file. Here is my example:
```
"dependencies": {
"@types/babel__parser": "7.1.1",
"@juanpicado/registry_test": "*",
"lodash": "*"
}
```
If you recall, I've published a package in my GitHub profile named `registry_test`, but GitHub requires to access my public package scoped with my user name, that would be `@juanpicado/registry_test`.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3zdrvka3jh7330q5lm7h.png)
To make it more interesting, I also added a random published public package published by another user named `@types/babel__parser`.
The next step is setting up the **package access** section:
```
packages:
'@juanpicado/*':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: github
'@types/babel__parser':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: github
'@*/*':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs
'**':
access: $all
publish: $authenticated
proxy: npmjs
```
As we describe in the packages [documentation](https://verdaccio.org/docs/en/packages#usage), the **order is important**. Define the scoped packages you want to match on top of `'@*/*'` and define the `proxy` properties to the name used in the uplink section, for our example would be `proxy: github`.
With such configuration, *Verdaccio* will be able to route the request to the right remote.
```
http --> 200, req: 'GET https://registry.npmjs.org/lodash' (streaming)
http --> 200, req: 'GET https://registry.npmjs.org/lodash', bytes: 0/194928
http <-- 200, user: null(127.0.0.1), req: 'GET /lodash', bytes: 0/17599
http <-- 200, user: null(127.0.0.1), req: 'GET /lodash', bytes: 0/17599
http --> 200, req: 'GET https://npm.pkg.github.com/@types%2Fbabel__parser' (streaming)
http --> 200, req: 'GET https://npm.pkg.github.com/@types%2Fbabel__parser', bytes: 0/1113
http --> 200, req: 'GET https://npm.pkg.github.com/@juanpicado%2Fregistry_test' (streaming)
http --> 200, req: 'GET https://npm.pkg.github.com/@juanpicado%2Fregistry_test', bytes: 0/2140
http <-- 200, user: null(127.0.0.1), req: 'GET /@types%2fbabel__parser', bytes: 0/708
http <-- 200, user: null(127.0.0.1), req: 'GET /@types%2fbabel__parser', bytes: 0/708
http <-- 200, user: null(127.0.0.1), req: 'GET /@juanpicado%2fregistry_test', bytes: 0/911
http <-- 200, user: null(127.0.0.1), req: 'GET /@juanpicado%2fregistry_test', bytes: 0/911
```
As we can observe if we have a close look at the server output.
* `lodash` is routed through -> `https://registry.npmjs.org/` .
* `"@types/babel__parser": "7.1.1"` is routed through -> `https://npm.pkg.github.com/@types%2Fbabel__parser`.
* `"@juanpicado/registry_test": "*"` is routed through `https://npm.pkg.github.com/@juanpicado%2Fregistry_test'.`.
Verdaccio is able to handle as many remotes you need, furthermore, you can add two *proxy* values as a fallback in case the package is not being found in the first option.
```
packages:
'@juanpicado/*':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs github
```
Verdaccio will try to fetch from *npmjs* and if the package fails for any reason will retry on *github*. This scenario is useful if you are not 100% sure whether the package is available or not in a specific registry. As a downside, if you add multiple proxies will slow down the installations due to the multiple looks up have to perform.
```
http --> 404, req: 'GET https://registry.npmjs.org/@juanpicado%2Fregistry_test' (streaming)
http --> 404, req: 'GET https://registry.npmjs.org/@juanpicado%2Fregistry_test', bytes: 0/21
http --> 200, req: 'GET https://npm.pkg.github.com/@juanpicado%2Fregistry_test' (streaming)
http --> 200, req: 'GET https://npm.pkg.github.com/@juanpicado%2Fregistry_test', bytes: 0/2140
http <-- 200, user: null(127.0.0.1), req: 'GET /@juanpicado%2fregistry_test', bytes: 0/908
http <-- 200, user: null(127.0.0.1), req: 'GET /@juanpicado%2fregistry_test', bytes: 0/908
```
#### One more thing
During writing this blog post, I've noticed all files retrieved from the GitHub registry are not tarballs like those that come from other registries which always finish with the suffix `*.tgz`.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/auuzx8avfhdtgu65cu5c.png)
## Wrapping up
**Verdaccio** is a powerful lightweight registry that can be used in multiple ways, you can find more about it in our [website](https://verdaccio.org). This project is run by voluntaries and [you can also be part of it](https://github.com/verdaccio/verdaccio/issues/1461).
If you would like to donate, it can be done through [OpenCollective](https://opencollective.com/verdaccio), help us to reach more developers to have a sustainable Node.js registry.
Thanks for using Verdaccio and please, **keep safe, stay at home and wash your hands regularly.**
Posted on March 22, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.