JSPM

  • Created
  • Published
  • Downloads 104
  • Score
    100M100P100Q69809F
  • License MIT

Multi-backend environment variable and secrets manager with AES-256-GCM encryption

Package Exports

  • vaulter
  • vaulter/load
  • vaulter/loader
  • vaulter/package.json

Readme

๐Ÿ” vaulter

Multi-Backend Environment & Secrets Manager

One CLI to manage all your environment variables.

npm version TypeScript Node.js MCP License

Store secrets anywhere: AWS S3, MinIO, R2, Spaces, B2, or local filesystem.
AES-256-GCM encryption. RSA/EC hybrid encryption. Native K8s, Helm & Terraform integration.

Quick Start ยท Security ยท CI/CD ยท Commands


Installation

# One-liner (recommended)
curl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh

# Or via npm/pnpm
npm install -g vaulter
pnpm add -g vaulter

Quick Start

# Initialize project
vaulter init

# Set secrets (encrypted, synced to backend)
vaulter set DATABASE_URL="postgres://localhost/mydb" -e dev

# Export to shell
eval $(vaulter export -e dev)

# Deploy to Kubernetes
vaulter k8s:secret -e prd | kubectl apply -f -

Table of Contents


Why Vaulter?

The Problem

Environment variables and secrets are scattered across .env files, CI/CD settings, cloud consoles, and team Slack messages. This creates:

  • Security gaps: Secrets in plaintext files, git history, or shared docs
  • Sync issues: "Works on my machine" because .env files differ
  • Deploy friction: Manual copy-paste between environments
  • Audit blindness: No idea who changed what, when

The Solution

Vaulter centralizes all environment variables in encrypted storage (S3-compatible) while maintaining the simplicity of .env files:

Traditional With Vaulter
Secrets in plaintext .env Encrypted at rest (AES-256-GCM)
Manual sync between devs vaulter pull / vaulter push
Copy-paste to CI/CD eval $(vaulter export -e prd)
No audit trail Full history via S3 versioning
Different files per machine Single source of truth

Why Trust Vaulter?

  1. Open source: All code is auditable
  2. No lock-in: Your data lives in YOUR storage (S3, MinIO, R2, filesystem)
  3. Standard encryption: AES-256-GCM, the same used by AWS, Google, and banks
  4. Zero external dependencies: No SaaS, no API keys, no third-party services
  5. Offline capable: Works with local filesystem backend

Security

Encryption Model

Every secret is encrypted before leaving your machine using AES-256-GCM:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                     Your Machine                            โ”‚
โ”‚                                                             โ”‚
โ”‚  .env file โ”€โ”€โ–บ vaulter encrypt โ”€โ”€โ–บ encrypted blob โ”€โ”€โ–บ S3   โ”‚
โ”‚               (AES-256-GCM)         (unreadable)           โ”‚
โ”‚                                                             โ”‚
โ”‚  S3 โ”€โ”€โ–บ encrypted blob โ”€โ”€โ–บ vaulter decrypt โ”€โ”€โ–บ .env file   โ”‚
โ”‚         (unreadable)       (AES-256-GCM)                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

What this means:

  • The backend (S3, MinIO, etc.) only sees encrypted data
  • Even with S3 access, secrets are unreadable without the key
  • Each value is encrypted individually (field-level encryption)
  • Authenticated encryption prevents tampering (GCM mode)

Key Management

Vaulter stores keys in ~/.vaulter/ directory (outside project) for security:

~/.vaulter/
โ”œโ”€โ”€ projects/
โ”‚   โ””โ”€โ”€ <project-name>/
โ”‚       โ””โ”€โ”€ keys/
โ”‚           โ”œโ”€โ”€ master           # Private key (mode 600)
โ”‚           โ””โ”€โ”€ master.pub       # Public key (mode 644)
โ””โ”€โ”€ global/
    โ””โ”€โ”€ keys/                    # Shared across all projects
        โ”œโ”€โ”€ shared
        โ””โ”€โ”€ shared.pub

Key Commands

# Generate keys
vaulter key generate --name master                    # Symmetric key
vaulter key generate --name master --asymmetric       # RSA-4096 key pair
vaulter key generate --name master --asym --alg ec-p256  # EC P-256 key pair
vaulter key generate --name shared --global           # Global key (all projects)

# List and show keys
vaulter key list                      # List all keys (project + global)
vaulter key show --name master        # Show key details

# Export/import for deployment
vaulter key export --name master -o keys.enc    # Export encrypted bundle
vaulter key import -f keys.enc                  # Import on another machine

# Set VAULTER_EXPORT_PASSPHRASE to encrypt the bundle with custom passphrase

Configuration with key_name

The simplest way to use keys is via key_name resolution:

# .vaulter/config.yaml
encryption:
  mode: asymmetric
  asymmetric:
    algorithm: rsa-4096
    key_name: master           # โ†’ ~/.vaulter/projects/<project>/keys/master[.pub]
    # Or for global key:
    # key_name: global:master  # โ†’ ~/.vaulter/global/keys/master[.pub]

Legacy Key Sources (still supported)

You can also specify explicit key sources:

encryption:
  key_source:
    - env: VAULTER_KEY           # 1. Environment variable (CI/CD)
    - file: .vaulter/.key        # 2. Local file (development)
    - s3: s3://keys/vaulter.key  # 3. Remote S3 (shared teams)
# Generate a key
vaulter key generate --name master

# Set in CI/CD secrets from the generated key
export VAULTER_KEY=$(cat ~/.vaulter/projects/myproject/keys/master)

Pros: Key never in project directory, rotates easily via CI/CD secret rotation Use case: GitHub Actions, GitLab CI, Jenkins

encryption:
  mode: asymmetric
  asymmetric:
    key_name: master    # Auto-resolves to ~/.vaulter/projects/<project>/keys/

Pros: Simple, keys stored securely outside project Use case: Local development, team workflows

Option 3: Remote S3 (Team Shared)
encryption:
  key_source:
    - s3: s3://company-keys/vaulter/project.key?region=us-east-1

Pros: Centralized key management, IAM-controlled access Use case: Teams, multiple developers needing same key

Asymmetric Key Encryption (RSA/EC)

For enhanced security with separate encrypt/decrypt permissions, Vaulter supports hybrid encryption using RSA or Elliptic Curve key pairs.

How It Works

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                     Hybrid Encryption                          โ”‚
โ”‚                                                                โ”‚
โ”‚  Your secret โ”€โ”€โ–บ AES-256-GCM โ”€โ”€โ–บ Encrypted data               โ”‚
โ”‚                      โ”‚                                         โ”‚
โ”‚                      โ”‚ (random AES key)                        โ”‚
โ”‚                      โ–ผ                                         โ”‚
โ”‚  Public key โ”€โ”€โ–บ RSA/EC encrypt โ”€โ”€โ–บ Encrypted AES key          โ”‚
โ”‚                                                                โ”‚
โ”‚  Stored: { encrypted_key + encrypted_data + metadata }        โ”‚
โ”‚                                                                โ”‚
โ”‚  Decryption requires: Private key + Encrypted blob            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Benefits:

  • Separation of duties: Public key can only encrypt, private key can decrypt
  • CI/CD security: Give CI/CD only the public key - it can write but not read secrets
  • Production isolation: Only production has the private key for decryption

Generate Key Pair

# RSA 4096-bit (default, most compatible)
vaulter key generate --name master --asymmetric

# RSA 2048-bit (faster, less secure)
vaulter key generate --name master --asym --algorithm rsa-2048

# Elliptic Curve P-256 (modern, fast)
vaulter key generate --name master --asym --alg ec-p256

# Elliptic Curve P-384 (stronger EC)
vaulter key generate --name master --asym --alg ec-p384

# Global key (shared across all projects)
vaulter key generate --name shared --global --asymmetric

Output:

โœ“ Generated rsa-4096 key pair: master
  Private: ~/.vaulter/projects/my-project/keys/master (mode 600 - keep secret!)
  Public:  ~/.vaulter/projects/my-project/keys/master.pub (mode 644)

To use these keys in config.yaml:
  encryption:
    mode: asymmetric
    asymmetric:
      algorithm: rsa-4096
      key_name: master

Configuration

# .vaulter/config.yaml
encryption:
  mode: asymmetric              # Enable asymmetric mode
  asymmetric:
    algorithm: rsa-4096         # or rsa-2048, ec-p256, ec-p384
    key_name: master            # Uses ~/.vaulter/projects/<project>/keys/master[.pub]
    # Or for global keys:
    # key_name: global:master   # Uses ~/.vaulter/global/keys/master[.pub]

# Alternative: explicit key sources (for CI/CD or custom paths)
# encryption:
#   mode: asymmetric
#   asymmetric:
#     algorithm: rsa-4096
#     public_key:
#       - file: /path/to/master.pub
#       - env: VAULTER_PUBLIC_KEY
#     private_key:
#       - file: /path/to/master
#       - env: VAULTER_PRIVATE_KEY

Supported Algorithms

Algorithm Key Size Performance Use Case
rsa-4096 4096 bits Slower Maximum security, wide compatibility
rsa-2048 2048 bits Medium Good balance, legacy systems
ec-p256 256 bits Fast Modern systems, smaller keys
ec-p384 384 bits Medium Higher security EC

Use Case: Secure CI/CD Pipeline

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Development                                                  โ”‚
โ”‚   Developers have BOTH keys โ†’ can read and write secrets    โ”‚
โ”‚   vaulter set API_KEY="..." -e dev                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                           โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ CI/CD (GitHub Actions, Jenkins, etc.)                        โ”‚
โ”‚   Only PUBLIC key โ†’ can write NEW secrets, cannot read      โ”‚
โ”‚   Useful for automated secret rotation scripts              โ”‚
โ”‚                                                             โ”‚
โ”‚   env:                                                      โ”‚
โ”‚     VAULTER_PUBLIC_KEY: ${{ secrets.VAULTER_PUBLIC_KEY }}   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                           โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Production                                                   โ”‚
โ”‚   Only PRIVATE key โ†’ can read secrets at runtime            โ”‚
โ”‚                                                             โ”‚
โ”‚   env:                                                      โ”‚
โ”‚     VAULTER_PRIVATE_KEY: ${{ secrets.VAULTER_PRIVATE_KEY }} โ”‚
โ”‚                                                             โ”‚
โ”‚   # Application reads secrets at startup                    โ”‚
โ”‚   eval $(vaulter export -e prd)                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Environment Variables

Variable Purpose
VAULTER_PUBLIC_KEY Public key PEM content (for encryption)
VAULTER_PRIVATE_KEY Private key PEM content (for decryption)

Advanced Security Configurations

AWS KMS Integration (Planned)

For enterprises requiring HSM-backed keys:

encryption:
  kms:
    key_id: arn:aws:kms:us-east-1:123456789:key/abc-123
    # Key never leaves AWS KMS
    # Envelope encryption: KMS encrypts the data key

How it works:

  1. Vaulter generates a data encryption key (DEK)
  2. DEK encrypts your secrets locally
  3. AWS KMS encrypts the DEK (envelope encryption)
  4. Only encrypted DEK + encrypted secrets are stored
  5. Decryption requires both KMS access AND S3 access

Threat Model

Threat Protection
S3 bucket breach Data encrypted, key required
Key file leaked Rotate key, re-encrypt
Man-in-middle TLS + authenticated encryption
Malicious insider Audit logs via S3 versioning
Accidental git commit Secrets encrypted in .env

Security Best Practices

# โœ… DO
vaulter key generate                    # Random 256-bit key
echo ".vaulter/.key" >> .gitignore      # Never commit keys
export VAULTER_KEY="${{ secrets.KEY }}" # CI/CD secrets

# โŒ DON'T
echo "password123" > .vaulter/.key      # Weak key
git add .vaulter/.key                   # Exposed key
vaulter set KEY=val --key "hardcoded"   # Key in command history

Daily Use

Workflow Overview

# Morning: sync with team's changes
vaulter pull -e dev

# During development: add new variable
vaulter set NEW_API_KEY="sk-xxx" -e dev

# End of day: push changes
vaulter push -e dev

# Deploy: export to production
vaulter k8s:secret -e prd | kubectl apply -f -

Commands Reference

Core Commands

Command Description Example
init Initialize project vaulter init
get <key> Get a variable vaulter get DATABASE_URL -e prd
set KEY=val Set secrets (batch) vaulter set A=1 B=2 -e prd
set KEY::val Set configs (plain) vaulter set PORT::3000 -e dev
delete <key> Delete a variable vaulter delete OLD_KEY -e dev
list List all variables vaulter list -e prd
list --all-envs List across all envs vaulter list --all-envs
export Export for shell eval $(vaulter export -e dev)

Sync Commands

Command Description Example
sync Merge local and backend vaulter sync -e dev
pull Download from backend vaulter pull -e prd
push Upload to backend vaulter push -e dev

Integration Commands

Command Description Example
k8s:secret Kubernetes Secret vaulter k8s:secret -e prd
k8s:configmap Kubernetes ConfigMap vaulter k8s:configmap -e prd
helm:values Helm values.yaml vaulter helm:values -e prd
tf:vars Terraform .tfvars vaulter tf:vars -e prd
scan Scan monorepo vaulter scan

Set Command Syntax

# Secrets (encrypted, synced to backend)
vaulter set KEY=value                    # Single secret
vaulter set A=1 B=2 C=3 -e dev           # Batch secrets
vaulter set KEY:=123                     # Typed (number/boolean)

# Configs (plain text in split mode)
vaulter set PORT::3000 HOST::localhost   # Configs
Separator Type Backend Sync Encrypted
= Secret โœ“ โœ“
:= Secret (typed) โœ“ โœ“
:: Config Split: โœ— / Unified: โœ“ โœ“

Global Options

-p, --project <name>    Project name
-s, --service <name>    Service name (monorepos)
-e, --env <env>         Environment name (as defined in config)
-b, --backend <url>     Backend URL override
-k, --key <path|value>  Encryption key
-f, --file <path>       Input file path
-o, --output <path>     Output file path
-n, --namespace <name>  Kubernetes namespace
    --format <fmt>      Output format (shell/json/yaml/env/tfvars/docker-args)
-v, --verbose           Verbose output (shows values)
    --dry-run           Preview without applying
    --json              JSON output
    --force             Skip confirmations
    --all               Apply to all services in monorepo

Flexible Environment Names

Vaulter lets you define your own environment names. Use whatever convention fits your workflow:

# Short names (default)
environments: [dev, stg, prd]

# Full names
environments: [development, staging, production]

# Custom names
environments: [local, homolog, qa, uat, prod]

# Brazilian pattern
environments: [dev, homolog, prd]

All commands use -e with your custom names:

vaulter list -e homolog
vaulter pull -e development
vaulter k8s:secret -e uat | kubectl apply -f -

CI/CD

GitHub Actions (Quick Start)

name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy secrets to Kubernetes
        env:
          VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: |
          npx vaulter k8s:secret -e prd | kubectl apply -f -

GitHub Actions (Complete Example)

name: Deploy to Kubernetes
on:
  push:
    branches: [main, develop]
  workflow_dispatch:
    inputs:
      environment:
        description: 'Target environment'
        required: true
        default: 'dev'
        type: choice
        options: [dev, stg, prd]

env:
  VAULTER_VERSION: '1.0.1'

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'prd') || 'dev' }}

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'

      - name: Install Vaulter
        run: npm install -g vaulter@${{ env.VAULTER_VERSION }}

      - name: Configure kubectl
        uses: azure/k8s-set-context@v4
        with:
          kubeconfig: ${{ secrets.KUBECONFIG }}

      - name: Deploy Secrets
        env:
          VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: |
          ENV=${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'prd') || 'dev' }}

          # Deploy K8s Secret
          vaulter k8s:secret -e $ENV -n my-namespace | kubectl apply -f -

          # Deploy ConfigMap (non-sensitive config)
          vaulter k8s:configmap -e $ENV -n my-namespace | kubectl apply -f -

          # Verify deployment
          kubectl get secret,configmap -n my-namespace

      - name: Restart Deployment
        run: |
          kubectl rollout restart deployment/my-app -n my-namespace
          kubectl rollout status deployment/my-app -n my-namespace --timeout=120s

GitHub Actions (Monorepo with Services)

name: Deploy Service
on:
  push:
    branches: [main]
    paths:
      - 'apps/svc-*/**'

jobs:
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      services: ${{ steps.changes.outputs.services }}
    steps:
      - uses: actions/checkout@v4
      - id: changes
        run: |
          # Detect which services changed
          SERVICES=$(git diff --name-only HEAD~1 | grep '^apps/svc-' | cut -d'/' -f2 | sort -u | jq -R -s -c 'split("\n")[:-1]')
          echo "services=$SERVICES" >> $GITHUB_OUTPUT

  deploy:
    needs: detect-changes
    runs-on: ubuntu-latest
    strategy:
      matrix:
        service: ${{ fromJson(needs.detect-changes.outputs.services) }}
    steps:
      - uses: actions/checkout@v4

      - name: Deploy ${{ matrix.service }}
        env:
          VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
        run: |
          # Deploy secrets for specific service
          vaulter k8s:secret -e prd -s ${{ matrix.service }} | kubectl apply -f -

GitHub Actions (Using Binary for Speed)

name: Deploy (Fast)
on: [push]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Download Vaulter Binary
        run: |
          curl -sL https://github.com/forattini-dev/vaulter/releases/latest/download/vaulter-linux -o vaulter
          chmod +x vaulter
          sudo mv vaulter /usr/local/bin/

      - name: Deploy
        env:
          VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
        run: |
          vaulter k8s:secret -e prd | kubectl apply -f -

GitHub Actions (Matrix Deploy)

name: Deploy All Environments
on:
  workflow_dispatch:
    inputs:
      environment:
        type: choice
        options: [dev, stg, prd]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ inputs.environment }}
    steps:
      - uses: actions/checkout@v4

      - name: Deploy secrets
        env:
          VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
        run: |
          npx vaulter k8s:secret -e ${{ inputs.environment }} | kubectl apply -f -

      - name: Deploy configmaps
        run: |
          npx vaulter k8s:configmap -e ${{ inputs.environment }} | kubectl apply -f -

GitLab CI

stages:
  - deploy

deploy-secrets:
  stage: deploy
  image: node:22-alpine
  script:
    - npx vaulter k8s:secret -e ${CI_ENVIRONMENT_NAME} | kubectl apply -f -
  environment:
    name: $CI_COMMIT_REF_NAME
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      variables:
        CI_ENVIRONMENT_NAME: prd
    - if: $CI_COMMIT_BRANCH == "develop"
      variables:
        CI_ENVIRONMENT_NAME: dev

Jenkins Pipeline

pipeline {
    agent any

    environment {
        VAULTER_KEY = credentials('vaulter-key')
        AWS_ACCESS_KEY_ID = credentials('aws-access-key')
        AWS_SECRET_ACCESS_KEY = credentials('aws-secret-key')
    }

    stages {
        stage('Deploy Secrets') {
            steps {
                sh 'npx vaulter k8s:secret -e prd | kubectl apply -f -'
            }
        }
    }
}

Docker Integration

# Recommended: Use --env-file for production (handles all values safely)
vaulter export -e prd --format=env > .env.prd
docker run --env-file .env.prd myapp

# For simple values only: command substitution (no spaces/newlines in values)
docker run $(vaulter export -e prd --format=docker-args) myapp

Note: The docker-args format outputs -e "KEY=VALUE" flags. Due to shell word-splitting, values containing spaces or special characters won't work correctly with $(...) substitution. Use --env-file for complex values or production deployments.

For docker build with build args, use shell format:

# Export to shell and use in build
eval $(vaulter export -e prd)
docker build \
  --build-arg DATABASE_URL="$DATABASE_URL" \
  --build-arg API_KEY="$API_KEY" \
  -t myapp .

Terraform Integration

# Generate tfvars
vaulter tf:vars -e prd > secrets.auto.tfvars

# Or inline
terraform plan -var-file=<(vaulter tf:vars -e prd)

Helm Integration

# Upgrade with secrets as values
vaulter helm:values -e prd | helm upgrade myapp ./chart -f -

# Or save to file
vaulter helm:values -e prd > values.secrets.yaml
helm upgrade myapp ./chart -f values.yaml -f values.secrets.yaml

Shell Aliases (Development)

# Add to ~/.bashrc or ~/.zshrc
alias vdev='eval $(vaulter export -e dev)'
alias vstg='eval $(vaulter export -e stg)'
alias vprd='eval $(vaulter export -e prd)'

# Usage
vdev npm run dev
vstg npm run test:integration

Configuration

Basic Config

# .vaulter/config.yaml
version: "1"

project: my-project
service: api  # optional, for monorepos

backend:
  url: s3://bucket/envs?region=us-east-1
  # Or multiple with fallback
  urls:
    - s3://bucket/envs?region=us-east-1
    - file:///home/user/.vaulter-store

encryption:
  key_source:
    - env: VAULTER_KEY
    - file: .vaulter/.key

environments:
  - dev
  - stg
  - prd

default_environment: dev

Directory Modes

Unified Mode (Default)

my-project/
โ”œโ”€โ”€ .vaulter/
โ”‚   โ”œโ”€โ”€ config.yaml
โ”‚   โ””โ”€โ”€ environments/
โ”‚       โ”œโ”€โ”€ dev.env
โ”‚       โ”œโ”€โ”€ stg.env
โ”‚       โ””โ”€โ”€ prd.env

Split Mode

Separates configs (committable) from secrets (gitignored):

my-project/
โ”œโ”€โ”€ .vaulter/config.yaml
โ””โ”€โ”€ deploy/
    โ”œโ”€โ”€ configs/           # โœ… Committable (PORT, HOST, LOG_LEVEL)
    โ”‚   โ”œโ”€โ”€ dev.env
    โ”‚   โ””โ”€โ”€ prd.env
    โ””โ”€โ”€ secrets/           # โŒ Gitignored (DATABASE_URL, API_KEY)
        โ”œโ”€โ”€ dev.env
        โ””โ”€โ”€ prd.env
directories:
  mode: split
  configs: deploy/configs
  secrets: deploy/secrets

Initialize with: vaulter init --split

Backend URLs

Provider URL Format
AWS S3 s3://bucket/path?region=us-east-1
AWS S3 + Profile s3://bucket/path?profile=myprofile
MinIO http://KEY:SECRET@localhost:9000/bucket
Cloudflare R2 https://KEY:SECRET@ACCOUNT.r2.cloudflarestorage.com/bucket
DigitalOcean Spaces https://KEY:SECRET@nyc3.digitaloceanspaces.com/bucket
Backblaze B2 https://KEY:SECRET@s3.us-west-002.backblazeb2.com/bucket
FileSystem file:///path/to/storage
Memory memory://bucket-name

Integrations

Kubernetes

# Deploy Secret
vaulter k8s:secret -e prd -n my-namespace | kubectl apply -f -

# Deploy ConfigMap
vaulter k8s:configmap -e prd | kubectl apply -f -

Note: Custom secret/configmap names are configured in .vaulter/config.yaml:

integrations:
  kubernetes:
    secret_name: my-app-secrets
    configmap_name: my-app-config

Helm

# Pass as values
vaulter helm:values -e prd | helm upgrade myapp ./chart -f -

# Save to file
vaulter helm:values -e prd > values.secrets.yaml

Terraform

# Generate tfvars
vaulter tf:vars -e prd > terraform.tfvars

# Generate JSON
vaulter tf:json -e prd > terraform.tfvars.json

Monorepo Support

Vaulter auto-detects all major monorepo tools:

Tool Detection File Workspace Config
NX nx.json workspaceLayout
Turborepo turbo.json Uses pnpm/yarn workspaces
Lerna lerna.json packages array
pnpm pnpm-workspace.yaml packages array
Yarn package.json workspaces field
Rush rush.json projects[].projectFolder

Scan Command

# Discover all packages
vaulter scan

# Output:
# Monorepo: NX
# Found 17 package(s):
#   โœ“ Initialized: 3
#   โ—‹ Not initialized: 14
#   ๐Ÿ“„ With .env files: 11

Batch Operations

# Sync all services
vaulter sync -e dev --all

# Sync specific services
vaulter sync -e dev -s api,worker

API Usage

import { VaulterClient, loadConfig } from 'vaulter'

const config = loadConfig()
const client = new VaulterClient({ config })

await client.connect()

// CRUD operations
const value = await client.get('DATABASE_URL', 'my-project', 'prd')
await client.set({ key: 'API_KEY', value: 'sk-xxx', project: 'my-project', environment: 'prd' })
const vars = await client.list({ project: 'my-project', environment: 'prd' })

await client.disconnect()

Dotenv Compatible

// Auto-load .env into process.env
import 'vaulter/load'

// Or with options
import { loader } from 'vaulter'
loader({ path: '.env.local', override: true })

MCP Server

Vaulter includes a Model Context Protocol (MCP) server for AI assistant integration.

Setup

# Start server
vaulter mcp

# Test with MCP Inspector
npx @anthropic-ai/mcp-inspector vaulter mcp

Claude Desktop Config

{
  "mcpServers": {
    "vaulter": {
      "command": "vaulter",
      "args": ["mcp"]
    }
  }
}

Available Tools (19)

Tool Description
vaulter_get Get a variable
vaulter_set Set a variable
vaulter_delete Delete a variable
vaulter_list List variables
vaulter_export Export in various formats
vaulter_sync Bidirectional sync
vaulter_pull Download from backend
vaulter_push Upload to backend
vaulter_compare Compare environments
vaulter_search Search by pattern
vaulter_scan Scan monorepo
vaulter_services List services
vaulter_k8s_secret Generate K8s Secret
vaulter_k8s_configmap Generate K8s ConfigMap
vaulter_init Initialize project
vaulter_key_generate Generate encryption key (symmetric or asymmetric)
vaulter_key_list List all keys (project + global)
vaulter_key_show Show key details
vaulter_key_export Export key to encrypted bundle
vaulter_key_import Import key from encrypted bundle

Resources (7)

  • vaulter://config โ€” Project configuration
  • vaulter://services โ€” Monorepo services
  • vaulter://keys โ€” List all encryption keys (project + global)
  • vaulter://keys/<name> โ€” Specific key details
  • vaulter://keys/global/<name> โ€” Global key details
  • vaulter://project/env โ€” Environment variables
  • vaulter://project/env/service โ€” Service-specific vars
  • vaulter://compare/env1/env2 โ€” Environment diff

Prompts (5)

  • setup_project โ€” Initialize a new project
  • migrate_dotenv โ€” Migrate existing .env
  • deploy_secrets โ€” Deploy to Kubernetes
  • compare_environments โ€” Compare two environments
  • security_audit โ€” Audit for security issues

Pre-built Binaries

Download from Releases:

Platform Binary
Linux x64 vaulter-linux-x64
Linux ARM64 vaulter-linux-arm64
macOS x64 vaulter-macos-x64
macOS ARM64 vaulter-macos-arm64
Windows x64 vaulter-win-x64.exe

License

MIT ยฉ Forattini