Top Banner
← Back To Blog

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.

Vault 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/vault

Step 2 — Verify Vault

docker logs vault

Open:

http://localhost:8200

Step 3 — Install Node.js SDK

npm install node-vault

Step 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 root

Step 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-v2

What 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/myapp

Vault 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-vault

Step 9 — Create Vault Client

Create a file called:

vault.js
const 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.js
const 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.js

Expected 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 FilesVault
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 policies

Create:

policies/myapp-policy.hcl
path "secret/data/myapp" {
  capabilities = ["read"]
}

Apply the policy:

vault policy write myapp-policy policies/myapp-policy.hcl

Step 14 — Enable AppRole Authentication

AppRole is the recommended authentication method for backend applications and APIs.

vault auth enable approle

Step 15 — Create Application Role

vault write auth/approle/role/myapp token_policies="myapp-policy" token_ttl=1h token_max_ttl=4h

Step 16 — Retrieve Role ID

vault read auth/approle/role/myapp/role-id

Save the Role ID securely.

Step 17 — Generate Secret ID

vault write -f auth/approle/role/myapp/secret-id

Save 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=xxxxxxxx

Production Docker Compose Setup

Create:

docker-compose.yml
version: "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 -d

Initialize Vault

vault operator init

Save the generated unseal keys and root token in a secure password manager. These keys are required to recover Vault.

Unseal Vault

vault operator unseal

Repeat the unseal command using the required number of unseal keys returned during initialization.

Production Security Best Practices

✓ Use AppRole Authentication
✓ Enable Audit Logging
✓ Use TLS Everywhere
✓ Rotate Secrets Regularly
✓ Use Least Privilege Policies
✓ Backup Vault Storage

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/myapp

PostgreSQL Dynamic Credentials

Vault can generate temporary PostgreSQL credentials automatically instead of storing static usernames and passwords.

vault secrets enable database
vault 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/readonly

Vault 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.com

Recommended Production Architecture

Internet

Cloud Firewall

Nginx Reverse Proxy

HashiCorp Vault

PostgreSQL / MySQL

Node.js Applications

CloudRevol Recommendation

For production environments, CloudRevol recommends:

✓ AppRole Authentication
✓ TLS Everywhere
✓ Dynamic Database Credentials
✓ Daily Backup Strategy
✓ Security Monitoring
✓ Infrastructure Hardening

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.

🔐 Vault Deployment
🚀 Node.js Integration
🛡 Security Hardening
☁️ Managed Cloud Hosting