Selecting NPM Private Registries at Repository Level in Renovate Using Presets
This guide shows how to let repository owners choose which approved NPM private registry to use (e.g., dev vs. release or internal-only vs. virtual public mirror/cache) by opting into a preset while securely managing all tokens and endpoints at the platform level.
Why this matters
Developer flexibility: Repos can switch between approved registries (e.g., dev/release) without Ops changes.
Security first: Tokens never live in repo config; they are centrally injected and redacted.
Consistency: All repos use vetted registries with consistent
.npmrc
definitions.Minimal friction: Opt-in via an
extends
preset; no service restarts or global edits required.
Configuration overview
Define environment variables for each approved registry endpoint and token (e.g., dev and release) on the Renovate worker.
Map environment variables to Renovate
secrets
inconfig.js
and define.npmrc
strings from them.Set a secure default (e.g., release registry) in global config using
npmrc
,packageRules
.Publish one preset per registry that overrides
npmrc
andregistryUrls
(viapackageRules
) to point to the alternate registry.Repo owners opt in by extending the desired preset, effectively routing package lookup to the alternate registry only for their repo.
Step 1: Runtime environment (examples)
Kubernetes (Helm values.yaml
):
renovateWorker:
extraEnvVars:
- name: NPM_REGISTRY_DEV
value: "<https://company.jfrog.io/artifactory/api/npm/npm-dev/>"
- name: NPM_REGISTRY_DEV_TOKEN
valueFrom:
secretKeyRef:
name: mend-renovate-worker
key: artifactoryToken_dev
- name: NPM_REGISTRY_RELEASE
value: "<https://company.jfrog.io/artifactory/api/npm/npm-release/>"
- name: NPM_REGISTRY_RELEASE_TOKEN
valueFrom:
secretKeyRef:
name: mend-renovate-worker
key: artifactoryToken_rel
Notes:
Keep tokens only in your secret store. Confirm secret value has no trailing whitespace/newlines (e.g., use
echo -n
when encoding to base64).
Step 2: Global config.js
— break down
2.1 Secrets
Expose the runtime environment variables via secrets
so they can be safely referenced in presets using {{ secrets.* }}
.
module.exports = {
secrets: {
NPM_REGISTRY_DEV: process.env.NPM_REGISTRY_DEV,
NPM_REGISTRY_DEV_TOKEN: process.env.NPM_REGISTRY_DEV_TOKEN,
NPM_REGISTRY_RELEASE: process.env.NPM_REGISTRY_RELEASE,
NPM_REGISTRY_RELEASE_TOKEN: process.env.NPM_REGISTRY_RELEASE_TOKEN,
// npmrc strings built from the above
NPMRC_DEV: `registry=${process.env.NPM_REGISTRY_DEV}\n${process.env.NPM_REGISTRY_DEV.replace('https:', '')}:_authToken=${process.env.NPM_REGISTRY_DEV_TOKEN}`,
NPMRC_RELEASE: `registry=${process.env.NPM_REGISTRY_RELEASE}\n${process.env.NPM_REGISTRY_RELEASE.replace('https:', '')}:_authToken=${process.env.NPM_REGISTRY_RELEASE_TOKEN}`
},
2.2 npmrc
Define a global default .npmrc
that all repos inherit unless they opt into an alternate preset.
npmrc: "{{ secrets.NPMRC_RELEASE }}",
2.3 Package rules
Set default packageRules
so Renovate resolves npm packages against the default registry by default.
packageRules: [
{
matchDatasources: ["npm"],
matchManagers: ["npm"],
registryUrls: [process.env.NPM_REGISTRY_RELEASE]
}
],
2.4 Host rules
Provide tokens for all approved registries so Renovate can authenticate when resolving dependencies.
hostRules: [
{
hostType: "npm",
matchHost: process.env.NPM_REGISTRY_DEV,
token: process.env.NPM_REGISTRY_DEV_TOKEN
},
{
hostType: "npm",
matchHost: process.env.NPM_REGISTRY_RELEASE,
token: process.env.NPM_REGISTRY_RELEASE_TOKEN
}
]
};
Step 3: Create one preset per approved NPM registry
Example preset for the dev registry (dev-registry.json
) in your shared renovate-config
repo:
{
"$schema": "<https://docs.renovatebot.com/renovate-schema.json>",
"npmrc": "{{ secrets.NPMRC_DEV }}",
"packageRules": [
{
"matchDatasources": ["npm"],
"matchManagers": ["npm"],
"registryUrls": ["{{ secrets.NPM_REGISTRY_DEV }}"]
}
]
}
npmrc: switches the active registry and sets the token via secrets.
packageRules: ensures Renovate resolves npm packages from the dev registry while this preset is active.
Create similar presets for other approved registries (e.g., release-registry.json
if you want an explicit one).
Step 4: Repo opt-in via extends
Any repository can choose a different registry by extending the preset:
{
"$schema": "<https://docs.renovatebot.com/renovate-schema.json>",
"extends": [
"config:recommended",
"local>your-scm-org/renovate-config:dev-registry"
]
}
Only repos that opt in will use the alternate registry, otherwise, the default is used.
Security and governance
Secrets never in repos: Tokens are injected via environment and referenced through
secrets
only.Approved endpoints only: Presets reference known approved URLs. Developers cannot inject arbitrary registry hosts.
Visibility: Presets are viewable by repo owners in the shared config repo.
Scoped credentials: Use separate tokens per registry and scope them to least privilege.
Rotation-friendly: Rotate tokens centrally; repos inherit updated secrets automatically.
Troubleshooting tips
Auth errors: Verify secret values (no trailing newline). You can decode the K8s Secret and
od -c
to spot hidden characters.Wrong registry: Confirm the repo actually extends the intended preset and Renovate logs show the chosen
registryUrls
.404s: Ensure package exists in the selected registry (dev vs. release content can differ).