A plug-in for the config module that adds support for Docker secrets alongside standard environment variables.
config-secrets extends the config module so that values in your custom-environment-variables config file are resolved against both Docker secrets (files in the secrets directory) and process environment variables. Environment variables take precedence over secrets, so you can always override a secret with an env var at runtime.
npm install config-secrets
Replace your require('config') call with require('config-secrets'). The returned object is the fully-configured config instance — every existing config.get(...) / config.has(...) keeps working, with secret files now resolved alongside env vars.
const config = require('config-secrets');
console.log(config.get('db.password'));Under the hood, importing config-secrets reads SECRET_PATH (default /run/secrets) and copies each file's contents into process.env before loading node-config. Existing env vars are never overwritten, so explicit env values always win over secret files.
Set this environment variable to change the directory where Docker secrets are read from. Defaults to /run/secrets.
SECRET_PATH=/my/secrets/dir node app.js
By default config-secrets reads only regular files in SECRET_PATH — symlinks are skipped so a hostile symlink (e.g. one pointing at /etc/passwd) can't leak data from outside the secrets directory. Set this to true to opt in to following symlinks:
SECRET_PATH_FOLLOW_SYMLINKS=true node app.js
You still need a custom-environment-variables file in your config/ folder. The environment variable names in that file are used as the secret file names too.
# config/custom-environment-variables.yml
default:
service:
port: "PORT"
db:
password: "DB_PASSWORD"With the above config, config-secrets will look for a file named DB_PASSWORD inside SECRET_PATH and use its contents as db.password. If the DB_PASSWORD environment variable is also set, it takes precedence.
TypeScript declarations ship with the package (lib/index.d.ts). Install @types/config alongside this package and the import is fully typed — getSecrets() and parseSecretsAndEnv() augment the standard node-config surface.
import config from 'config-secrets';
const password: string = config.get('db.password');This project follows Semantic Versioning. Apply one of the following labels to your PR to signal the intended bump — the release draft version updates automatically:
| Label | Bump | When to use |
|---|---|---|
bump:patch |
patch | Bug fixes, documentation, dependency upgrades |
bump:minor |
minor | New features or behaviour that are backwards compatible |
bump:major |
major | Breaking changes — removed or renamed exports, changed defaults, dropped Node/config version support |
When a release is published, package.json is automatically updated to match the release tag and committed back to the default branch.
Prereleases can be published without cutting a full release via the Publish to npm workflow dispatch. Provide a preid such as beta, rc.1, or alpha.2 — the package is published as {version}-{preid} under a matching npm dist-tag (e.g. beta) so it does not land on latest.
Requires Node.js 18 or newer. Node 17 and earlier are not supported.
Tested against every config major from v1 through v4. The library ships a small util.is* polyfill (lib/util-shim.js) so config@1 and config@2 keep working on Node 23+ — where Node removed the legacy util.isRegExp / util.isDate / util.isArray helpers those older versions still call directly. The shim is loaded automatically before require('config'); no consumer action required.
config version |
Status |
|---|---|
^1 |
✓ supported (via built-in polyfill) |
^2 |
✓ supported (via built-in polyfill) |
^3 |
✓ supported |
^4 |
✓ supported |