Skip to main content

Configuration File

This file is the cornerstone of Verdaccio where you can modify the default behaviour, enable plugins and extend features.

A default configuration file config.yaml is created the very first time you run verdaccio. You can find the most recent version of the default configuration here.

Default Configuration

The default configuration has support for scoped packages and allows any user to access all packages, but only authenticated users to publish or unpublish.

storage: ./storage

auth:
htpasswd:
file: ./htpasswd

uplinks:
npmjs:
url: https://registry.npmjs.org/

packages:
'@*/*':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs
'**':
access: $all
publish: $authenticated
unpublish: $authenticated
proxy: npmjs

middlewares:
audit:
enabled: true

log:
type: stdout
format: pretty
level: http

Sections

The following sections explain what each property means and their different options.

Storage

Is the location of the default storage. Verdaccio is by default based on local file system.

storage: ./storage

The environment variable VERDACCIO_STORAGE_PATH can be used to replace the location of the storage (only for the default storage; it does not apply to plugins unless they implement it independently).

The .verdaccio-db database

The tiny database is used to store private packages published by the user. The database is based on a JSON file that contains the list of private packages published and the secret token used for the token signature. It is created automatically when starting the application for the first time.

The location of the database is based on the config.yaml folder location, for instance:

If the config.yaml is located in /some_local_path/config.yaml, the database will be created in /some_local_path/storage/.verdaccio-db.

info

For users who have been using Verdaccio for an extended period and the .verdaccio-db file already exist the secret may be 64 characters long. However, for newer installations, the length will be generated as 32 characters long.

If the secret length is 64 characters long:

  • For users running Verdaccio 5.x on Node.js 22 or higher, the application will fail to start if the secret length is not 32 characters long.
  • For users running Verdaccio 5.x on Node.js 21 or lower, the application will start, but it will display a deprecation warning at the console.

How to upgrade the token secret at the storage?

⚠️ If the secret is updated will invalidate all previous generated tokens.

Option 1: Manually

Go to the storage location and edit manually the secret to be 32 characters long.

Option 2: Automatically

The migrateToSecureLegacySignature property is used to generate a new secret token if the length is 64 characters.

security:
api:
migrateToSecureLegacySignature: true

The token will be automatically updated to 32 characters long and the application will start without any issues. The property won't have any other effect on the application and could be removed after the secret is updated.

The .verdaccio-db file database is only available if user does not use a custom storage, by default verdaccio uses a tiny database to store private packages the storage property is defined in the config.yaml file. The location might change based on your operating system. Read the CLI section for more details about the location of files.

The structure of the database is based in JSON file, for instance:

{
"list": ["package1", "@scope/pkg2"],
"secret": "secret_token_32_characters_long"
}
  • list: Is an array with the list of the private packages published, any item on this list is considered being published by the user.
  • secret: The secret field is used for the token signature and verification, either for JWT or legacy token signature.

Plugins

Is the location of the plugin directory. Useful for Docker/Kubernetes-based deployments.

plugins: ./plugins

Authentication

The authentication setup is done here. The default auth is based on htpasswd and is built in. You can modify this behaviour via plugins. For more information about this section read the auth page.

auth:
htpasswd:
file: ./htpasswd
max_users: 1000

Token signature

The default token signature is based on the Advanced Encryption Standard (AES) with the algorithm aes-256-ctr, known as legacy. It's important to note that legacy tokens are not designed to expire. If expiration functionality is needed, it is recommended to use JSON Web Tokens (JWT) instead.

Security

The security block permits customization of the token signature with two options. The configuration is divided into two sections, api and web. When using JWT on api, it must be defined; otherwise, the legacy token signature (aes-256-ctr) will be utilized.

How to the token is generated?

The token signature requires a secret token generated by custom plugin that creates the .verdaccio-db database or in case a custom storage is used, the secret token is fetched from the plugin implementation itself. In any case the secret token is required to start the application.

Legacy Token Signature

The legacy property is used to enable the legacy token signature. By default is enabled. The legacy feature only applies to the API, the web UI uses JWT by default.

info

In 5.x versions using Node.js 21 or lower, there will see the warning [DEP0106] DeprecationWarning: crypto.createDecipher is deprecated. printed in your terminal. This warning indicates that Node.js has deprecated a function utilized by the legacy signature.

If verdaccio runs on Node.js 22 or higher, you will not see this warning since a new modern legacy signature has been implemented.

The migrateToSecureLegacySignature property is false by default.

security:
api:
legacy: true # by default is true even if this section is not defined

JWT Token Signature

To enable a new JWT (JSON Web Tokens) signature, the jwt block needs to be added to the api section; jwt is utilized by default in web.

By using the JWT signature is also possible to customize the signature and the token verification with your own properties.

security:
api:
jwt:
sign:
expiresIn: 29d
verify:
someProp: [value]
web:
sign:
expiresIn: 1h # 1 hour by default
verify:
someProp: [value]

Server

A set of properties to modify the behavior of the server application, specifically the API (Express.js).

You can specify HTTP/1.1 server keep alive timeout in seconds for incoming connections. A value of 0 makes the http server behave similarly to Node.js versions prior to 8.0.0, which did not have a keep-alive timeout. WORKAROUND: Through given configuration you can workaround following issue https://github.com/verdaccio/verdaccio/issues/301. Set to 0 in case 60 is not enough.

server:
keepAliveTimeout: 60

Legacy auth cache

Available since Verdaccio 6.10.0.

The legacyAuthCache option caches successful legacy token authentication results for a short period of time. This avoids running password verification through the authentication plugin for every request that reuses the same legacy bearer token.

The cache is disabled by default. Enable it only when you accept that changed or revoked credentials may remain valid until the cached entry expires.

server:
legacyAuthCache:
enabled: true
ttlMs: 15000
maxEntries: 1000
PropertyTypeRequiredDefaultDescription
enabledbooleanNofalseEnables the legacy token authentication cache.
ttlMsnumberNo15000Time in milliseconds before a cached validation expires.
maxEntriesnumberNo1000Maximum number of cached legacy tokens.

Dotfile requests

Available from 7.x

Ships in 7.x and later, and in the 9.x experimental line (verdaccio@next-9) where it lands first. Not available in 6.x.

Controls how requests whose path contains a dotfile segment — /.env, /.git/config, /.well-known/… — are answered. It mirrors the semantics of serve-static's option of the same name.

server:
dotfiles: ignore
ValueBehaviour
ignoreanswers 404, as if the path did not exist (default)
denyanswers 403
allowpasses the request through to the rest of the middleware

ignore is the default because it does not confirm to a scanner that the path exists. Choose deny only if you prefer an explicit refusal in your logs, and allow only if something in your setup legitimately serves dotfile paths.

Hiding static asset logs

Available from 7.x

Ships in 7.x and later, and in the 9.x experimental line (verdaccio@next-9) where it lands first. Not available in 6.x.

Requests for the web UI assets (/-/static/*) are noisy and rarely interesting. They are hidden from the logger by default:

server:
hideStaticLogs: true

Set it to false to log them like any other request. They are always available regardless of this setting by running with DEBUG=verdaccio:middleware:log.

Running behind a proxy

When Verdaccio sits behind a reverse proxy or a load balancer, every request appears to come from the proxy. trustProxy tells Express which upstream addresses to trust, so req.ip resolves to the real client:

server:
trustProxy: '127.0.0.1'

The value is passed straight to Express' trust proxy setting, so it accepts the same forms: an address, a subnet, a comma-separated list, or a hop count.

caution

This is not cosmetic. Two features depend on the client address being correct:

  • rate limiting, which otherwise counts every request as coming from the proxy and throttles all your users as if they were one
  • the CIDR whitelist of npm tokens, which cannot enforce anything useful if it only ever sees the proxy's address

Set it whenever there is a proxy in front, and only list addresses you actually control — trusting an address means believing the X-Forwarded-For header it sends.

See also the reverse proxy setup page.

Password policy

The minimum a password must satisfy when a user registers. It defaults to three characters:

server:
# at least 10 characters
passwordValidationRegex: /.{10}$/

The value is a regular expression. Written in YAML it arrives as a string and is compiled at runtime; an invalid pattern makes every password fail validation rather than being ignored, so test it after changing it.

This only applies where Verdaccio itself validates the password — user registration and password changes. An authentication plugin that manages its own users is not affected.

Custom plugin prefix

Plugins are resolved as verdaccio-<name> by default. If you publish your plugins under a different prefix, declare it here:

server:
pluginPrefix: acme

With that, a plugin configured as s3 resolves to the package acme-s3 instead of verdaccio-s3. Do not include the dash — it is added for you.

The prefix applies to every plugin category: authentication, storage, middleware and filters.

Web UI

This property allow you to modify the look and feel of the web UI. For more information about this section read the web UI page.

web:
enable: true
title: Verdaccio
logo: logo.png
scope:

Uplinks add the ability to fetch packages from remote registries when those packages are not available locally. For more information about this section read the uplinks page.

uplinks:
npmjs:
url: https://registry.npmjs.org/

Packages

This section allows you to control how packages are accessed. For more information about this section read the packages page.

packages:
'@*/*':
access: $all
publish: $authenticated
proxy: npmjs

Advanced Settings

Offline Publish

By default Verdaccio does not allow you to publish packages when the client is offline. This can be overridden by setting this value to true.

publish:
allow_offline: false

Checking Package Ownership

Available from 7.x

Ships in 7.x and later, and in the 9.x experimental line (verdaccio@next-9) where it lands first. Not available in 6.x.

By default, package access defines who is allowed to publish and unpublish packages. By setting check_owners to true, only package owners are allowed to make changes to a package. The first owner of a package is the user who published the first version. Further owners can be added or removed using npm owner. You can find the list of current owners using npm owner list or by checking the package manifest under maintainers.

publish:
check_owners: false

Keep Readmes

Available from 7.x

Ships in 7.x and later, and in the 9.x experimental line (verdaccio@next-9) where it lands first. Not available in 6.x.

By default, Verdaccio stores only the readme markdown of the latest version for each package. Setting keep_readmes to 'tagged' keeps the readmes of versions with dist-tags (for example, latest, next, and major branches). Using the 'all' setting will retain the complete history of readme versions. Note that 'all' can significantly increase the required storage space for packages published to Verdaccio!

publish:
keep_readmes: 'tagged'

URL Prefix

The prefix is intended to be used when the server runs behinds the proxy and won't work properly if is used without a reverse proxy, check the reverse proxy setup page for more details.

The internal logic builds correctly the public url, validates the host header and bad shaped url_prefix.

eg: url_prefix: /verdaccio, url_prefix: verdaccio/, url_prefix: verdaccio would be /verdaccio/

url_prefix: /verdaccio/

The new VERDACCIO_PUBLIC_URL is intended to be used behind proxies, this variable will be used for:

  • Used as base path to serve UI resources as (js, favicon, etc)
  • Used on return metadata dist base path
  • Ignores host and X-Forwarded-Proto headers
  • If url_prefix is defined would be appended to the env variable.
VERDACCIO_PUBLIC_URL='https://somedomain.org';
url_prefix: '/my_prefix'

// url -> https://somedomain.org/my_prefix/

VERDACCIO_PUBLIC_URL='https://somedomain.org';
url_prefix: '/'

// url -> https://somedomain.org/

VERDACCIO_PUBLIC_URL='https://somedomain.org/first_prefix';
url_prefix: '/second_prefix'

// url -> https://somedomain.org/second_prefix/'

User Agent

The user agent is disabled by default, in exchange the user agent client (package manager, browser, etc ...) is being bypassed to the remote. To enable the previous behaviour use boolean values.

user_agent: true
user_agent: false
user_agent: 'custom user agent'

User Rate Limit

Add default rate limit to user endpoints, npm token, npm profile, npm login/adduser and login website to 100 request peer 15 min, customizable via:

userRateLimit:
windowMs: 50000
max: 1000

Additonal configuration (only feature flags) is also possible via the middleware docs.

Max Body Size

By default the maximum body size for a JSON document is 10mb, if you run into errors that state "request entity too large" you may increase this value.

max_body_size: 10mb

Listen Port

verdaccio runs by default on the port 4873. Changing the port can be done via CLI or in the configuration file. The following options are valid:

listen:
# - localhost:4873 # default value
# - http://localhost:4873 # same thing
# - 0.0.0.0:4873 # listen on all addresses (INADDR_ANY)
# - https://example.org:4873 # if you want to use https
# - "[::1]:4873" # ipv6
# - unix:/tmp/verdaccio.sock # unix socket

HTTPS

To enable https in verdaccio it's enough to set the listen flag with the protocol https://. For more information about this section read the SSL page.

https:
key: ./path/verdaccio-key.pem
cert: ./path/verdaccio-cert.pem
ca: ./path/verdaccio-csr.pem

Proxy

Proxies are special-purpose HTTP servers designed to transfer data from remote servers to local clients. You can define a HTTP or HTTPS proxy in the main configuration or separately for each uplink. The definition for uplinks have higher priority.

note

The proxy configuration key (http_proxy or https_proxy) has to match the protocol of the uplink URL!

For example, to use a proxy for npm i.e. https://registry.npmjs.com, then you have to use https_proxy in your configuration to specify you proxy URL (no matter if the proxy uses http or https).

uplinks:
npmjs:
url: https://registry.npmjs.org/
https_proxy: http://my.proxy.local/

http_proxy and https_proxy

If you have a proxy in your network you can set a X-Forwarded-For header using the following properties:

http_proxy: http://something.local/
https_proxy: https://something.local/

no_proxy

This variable should contain a comma-separated list of domain extensions that the proxy should not be used for.

no_proxy: localhost,127.0.0.1

Notifications

Enabling notifications to third-party tools is fairly easy via webhooks. For more information about this section read the notifications page.

notify:
method: POST
headers: [{ 'Content-Type': 'application/json' }]
endpoint: https://usagge.hipchat.com/v2/room/3729485/notification?auth_token=mySecretToken
content: '{"color":"green","message":"New package published: * {{ name }}*","notify":true,"message_format":"text"}'

For more detailed configuration settings, please check the source code.

Logger

Deprecated: logs

The property is log. The older logs spelling still works but emits a deprecation warning (VERWAR002) on startup and may be removed at any time — rename it to log.

Two logger types are supported, you may chose only one of them:

console output (the default)

log: { type: stdout, format: pretty, level: http }

file output

log: { type: file, path: verdaccio.log, level: info }

For full information - see here: Features/logger

Audit

Verdaccio includes a built-in middleware plugin to handle npm audit.

If you have a new installation it comes by default, otherwise you need to add the following props to your config file

middlewares:
audit:
enabled: true
# timeout: 10000

Package Filter

Since: verdaccio@6.4.0

Verdaccio ships with a bundled, optional filter plugin @verdaccio/package-filter that controls which package versions are visible to consumers by filtering manifest responses.

info

It is disabled by default. To enable it, add it under filters in config.yaml (with no rules it is a no-op):

filters:
'@verdaccio/package-filter':

Supported options:

  • minAgeDays: hide versions published less than N days ago (quarantine window).
  • dateThreshold: only serve versions published before a given date (e.g. '2024-01-01'). When combined with minAgeDays, the earlier cutoff wins.
  • block: list of rules to hide versions. Each rule can target a scope, a package name, or a package + versions semver range. Add strategy: replace to substitute a blocked version with the nearest older safe one (useful for transitive deps).
  • allow: same shape as block, but exempts the matching scope/package/versions from all rules (including minAgeDays and dateThreshold). allow takes precedence over block.

Example combining all options:

filters:
'@verdaccio/package-filter':
minAgeDays: 7
dateThreshold: '2025-01-01'
block:
- scope: '@malicious'
- package: 'typosquat-pkg'
- package: 'compromised-lib'
versions: '>=3.0.0'
- package: 'legacy-lib'
versions: '>=2.0.0'
strategy: replace
allow:
- scope: '@my-org'
- package: 'compromised-lib'
versions: '3.0.1'

See the plugin README for manifest cleanup behavior and debug namespaces.

Feature Flags (former Experiments)

Verdaccio includes a flags configuration setting (formerly named experiments) that can be placed in the config.yaml and is completely optional.

This allows shipping new things without affecting production environments. We can add new features and get feedback from the community who decides to use them.

The features under this setting might not be stable and might be removed in future releases. By default, all flags are off (false).

Examples:

flags:
changePassword: false
webLogin: true

The flags currently available are:

FlagSinceWhat it enables
changePasswordallchanging a password from the web UI
createUseralluser registration from the web UI
webLoginallbrowser-based login for the CLI
stage7.xstaged publishing (npm stage)
tfa7.xtwo-factor authentication

The stage and tfa flags are not available in 6.x.

To disable console warnings related to the flags or experiments, you must comment out the complete flags and experiments sections.

Config Builder API

The advanced configuration builder API is a flexible way to generate programmatically configuration outputs either in JSON or YAML using the builder pattern, for example:

import { ConfigBuilder } from 'verdaccio';

const config = ConfigBuilder.build();
config
.addUplink('upstream', { url: 'https://registry.upstream.local' })
.addUplink('upstream2', { url: 'https://registry.upstream2.local' })
.addPackageAccess('upstream/*', {
access: 'public',
publish: 'foo, bar',
unpublish: 'foo, bar',
proxy: 'some',
})
.addLogger({ level: 'info', type: 'stdout', format: 'json' })
.addStorage('/tmp/verdaccio')
.addSecurity({ api: { legacy: true } });

// generate JSON object as output
config.getConfig();

// generate output as yaml
config.getAsYaml();