Setup HashiCorp Vault Secret Manager with Node.js
Learn how to securely store API keys, database passwords, OAuth credentials and application secrets using HashiCorp Vault and Node.js.

Why Use Vault?
Storing secrets directly inside source code, .env files or Git repositories creates significant security risks.
Security Problems
- ❌ Exposed API Keys
- ❌ Leaked Database Passwords
- ❌ Shared Credentials
- ❌ Git Repository Exposure
Vault Benefits
- ✓ Centralized Secrets
- ✓ Dynamic Credentials
- ✓ Audit Logging
- ✓ Access Policies
- ✓ Encryption At Rest
- ✓ Secret Rotation
Step 1 — Run Vault Using Docker
Start a local Vault instance:
docker run -d --name vault -p 8200:8200 -e VAULT_DEV_ROOT_TOKEN_ID=root hashicorp/vaultStep 2 — Verify Vault
docker logs vaultOpen:
http://localhost:8200Step 3 — Install Node.js SDK
npm install node-vaultStep 4 — Login To Vault
The development container starts with a root token. Login using the token specified when starting Vault.
export VAULT_ADDR=http://127.0.0.1:8200
vault login rootStep 5 — Enable KV Secrets Engine
The Key-Value (KV) secrets engine is the most commonly used engine for storing API keys, passwords and application secrets.
vault secrets enable -path=secret kv-v2What Is KV Version 2?
KV v2 supports versioned secrets, allowing you to rollback changes and maintain secret history.
Step 6 — Store Your First Secret
Store API credentials securely inside Vault.
vault kv put secret/myapp API_KEY="super-secret-api-key" DB_PASSWORD="strong-password" JWT_SECRET="very-long-random-secret"Step 7 — Read Secret From Vault
vault kv get secret/myappVault will return the stored values securely.
Step 8 — Create A Node.js Project
mkdir vault-nodejs-demo
cd vault-nodejs-demo
npm init -y
npm install node-vaultStep 9 — Create Vault Client
Create a file called:
vault.jsconst vault = require("node-vault")({
apiVersion: "v1",
endpoint: "http://127.0.0.1:8200",
token: "root",
});
module.exports = vault;Step 10 — Read Secrets In Node.js
Create:
app.jsconst vault = require("./vault");
async function run() {
try {
const secret = await vault.read(
"secret/data/myapp"
);
console.log(secret.data.data);
} catch (error) {
console.error(error);
}
}
run();Step 11 — Run The Application
node app.jsExpected output:
{
API_KEY: 'super-secret-api-key',
DB_PASSWORD: 'strong-password',
JWT_SECRET: 'very-long-random-secret'
}Why This Is Better Than .env Files
| Feature | .env Files | Vault |
|---|---|---|
| Centralized | ✗ | ✓ |
| Audit Logging | ✗ | ✓ |
| Secret Rotation | ✗ | ✓ |
| Access Control | ✗ | ✓ |
Step 12 — Update Existing Secrets
vault kv put secret/myapp API_KEY="new-api-key" DB_PASSWORD="new-password" JWT_SECRET="updated-secret"Vault automatically creates a new version of the secret while preserving previous versions.
Step 13 — Create Vault Policies
In production, applications should never use the root token. Instead, create policies that only grant access to specific secrets.
mkdir policiesCreate:
policies/myapp-policy.hclpath "secret/data/myapp" {
capabilities = ["read"]
}Apply the policy:
vault policy write myapp-policy policies/myapp-policy.hclStep 14 — Enable AppRole Authentication
AppRole is the recommended authentication method for backend applications and APIs.
vault auth enable approleStep 15 — Create Application Role
vault write auth/approle/role/myapp token_policies="myapp-policy" token_ttl=1h token_max_ttl=4hStep 16 — Retrieve Role ID
vault read auth/approle/role/myapp/role-idSave the Role ID securely.
Step 17 — Generate Secret ID
vault write -f auth/approle/role/myapp/secret-idSave the Secret ID securely.
Security Warning
Never commit Role IDs, Secret IDs or Vault tokens into Git repositories.
Step 18 — Authenticate Using AppRole In Node.js
Replace your existing Vault client with:
const vault = require("node-vault")({
apiVersion: "v1",
endpoint: "http://127.0.0.1:8200",
});
async function login() {
const result = await vault.approleLogin({
role_id: process.env.VAULT_ROLE_ID,
secret_id: process.env.VAULT_SECRET_ID,
});
vault.token = result.auth.client_token;
return vault;
}
module.exports = login;Step 19 — Read Secrets Using AppRole
const login = require("./vault");
async function run() {
const vault = await login();
const secret = await vault.read(
"secret/data/myapp"
);
console.log(secret.data.data);
}
run();Step 20 — Store Credentials In Environment Variables
VAULT_ROLE_ID=xxxxxxxx
VAULT_SECRET_ID=xxxxxxxxProduction Docker Compose Setup
Create:
docker-compose.ymlversion: "3.9"
services:
vault:
image: hashicorp/vault:latest
restart: unless-stopped
ports:
- "8200:8200"
cap_add:
- IPC_LOCK
environment:
VAULT_LOCAL_CONFIG: |
{
"storage": {
"file": {
"path": "/vault/data"
}
},
"listener": {
"tcp": {
"address": "0.0.0.0:8200",
"tls_disable": true
}
},
"ui": true
}
volumes:
- vault-data:/vault/data
volumes:
vault-data:Start Production Vault
docker compose up -dInitialize Vault
vault operator initSave the generated unseal keys and root token in a secure password manager. These keys are required to recover Vault.
Unseal Vault
vault operator unsealRepeat the unseal command using the required number of unseal keys returned during initialization.
Production Security Best Practices
Secret Rotation
One of the biggest advantages of Vault is the ability to rotate secrets without modifying application code.
vault kv put secret/myapp API_KEY="new-api-key-v2" DB_PASSWORD="new-secure-password" JWT_SECRET="new-jwt-secret"Applications automatically retrieve the latest version when reading secrets from Vault.
View Secret Versions
vault kv metadata get secret/myappPostgreSQL Dynamic Credentials
Vault can generate temporary PostgreSQL credentials automatically instead of storing static usernames and passwords.
vault secrets enable databasevault write database/config/postgres plugin_name=postgresql-database-plugin allowed_roles="readonly" connection_url="postgresql://{{username}}:{{password}}@localhost:5432/postgres?sslmode=disable" username="postgres" password="StrongPassword123"vault write database/roles/readonly db_name=postgres creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" default_ttl="1h" max_ttl="24h"Generate PostgreSQL Credentials
vault read database/creds/readonlyVault generates temporary credentials that expire automatically.
MySQL Dynamic Credentials
vault write database/config/mysql plugin_name=mysql-database-plugin allowed_roles="readonly" connection_url="{{username}}:{{password}}@tcp(localhost:3306)/" username="root" password="StrongPassword123"vault write database/roles/readonly db_name=mysql creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT ON *.* TO '{{name}}'@'%';" default_ttl="1h" max_ttl="24h"Nginx Reverse Proxy For Vault
Never expose Vault directly to the internet. Use Nginx as a reverse proxy with SSL.
server {
listen 80;
server_name vault.example.com;
location / {
proxy_pass http://127.0.0.1:8200;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}SSL With Let's Encrypt
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d vault.example.comRecommended Production Architecture
↓
Cloud Firewall
↓
Nginx Reverse Proxy
↓
HashiCorp Vault
↓
PostgreSQL / MySQL
↓
Node.js Applications
CloudRevol Recommendation
For production environments, CloudRevol recommends:
Frequently Asked Questions
Is Vault free?
Yes. HashiCorp Vault Open Source is free and suitable for most development and production workloads.
Should I store secrets in .env files?
For production systems, Vault provides significantly better security, auditing and secret management.
Can Vault rotate database credentials?
Yes. Vault can generate and rotate temporary PostgreSQL and MySQL credentials automatically.
Can Node.js use Vault directly?
Yes. Applications can securely retrieve secrets using the official API and libraries such as node-vault.
Related Articles
Need Help Deploying Vault In Production?
CloudRevol helps businesses deploy secure HashiCorp Vault environments, integrate Node.js applications, configure secret rotation, harden infrastructure and implement production-grade security practices.

