Use an environment variable, not an inline value. Verdaccio's uplink auth setting supports token_env, which reads the token from the environment, and token, which puts it in the config file. The docs advise against the inline form for security reasons.
How the setting works
The Verdaccio uplinks documentation says auth uses type: bearer with one of these token sources.
token_env: truereads theNPM_TOKENenvironment variable.token_env: <NAME>reads a custom variable name.token: '<value>'sets the token directly in the config file.
If both token and token_env are set, token takes priority. That detail matters: leaving an old inline value in place silently overrides the environment variable you thought you were using.
You can also send custom headers through headers, for example an authorization header for registries that expect a different form.
uplinks:
upstream:
url: https://registry.example/
auth:
type: bearer
token_env: UPSTREAM_TOKEN
Why env vars are better
A config file is easy to copy. It gets committed, pasted into tickets and baked into container images. A token in it travels everywhere the file does. An environment variable lives in your orchestrator or secret manager, with access control and rotation.
Env vars are not perfect. They show up in process listings on some hosts and in crash dumps, and every process in the container can read them. Mount from a secret store where you can, and limit who can exec into the container.
Scoping the token
The token is what lets your mirror read a private upstream. Give it the least rights that work.
- Read only, never publish.
- Limited to the packages or scopes the mirror needs.
- An expiry, with a calendar reminder to rotate.
- Its own identity, so that logs show mirror traffic apart from people.
Remember that anyone who can install through your mirror can effectively read the private packages the token reaches, unless your access rules restrict them. So the access rules on the mirror matter as much as the token.
Rotation steps
- Create the new upstream token.
- Update the secret in your secret store.
- Restart or reload the mirror so it picks it up.
- Confirm an install of a private package succeeds.
- Revoke the old token.
- Search config repositories for the old value, in case it was ever inline.
What to watch
Upstream 401 errors in the mirror logs mean the token expired or was revoked. A sudden jump in upstream requests from the mirror may mean something is scraping private content through it.
Safeguard's dependency scanning and SBOM generation can show what the mirror delivered, with a free scan at gold.safeguard.sh/scan.
Quick check
Which wins if token and token_env are both set?
The inline token takes priority, according to the Verdaccio docs.
Can people who use my mirror read private upstream packages?
Potentially yes, since the mirror uses its own token. Restrict who can install through the access rules.
Sources
Last reviewed: 19 October 2026.