vaulter 1.0.1 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +775 -1116
  2. package/dist/cli/commands/audit.d.ts +45 -0
  3. package/dist/cli/commands/audit.d.ts.map +1 -0
  4. package/dist/cli/commands/audit.js +299 -0
  5. package/dist/cli/commands/audit.js.map +1 -0
  6. package/dist/cli/commands/delete.d.ts.map +1 -1
  7. package/dist/cli/commands/delete.js +16 -1
  8. package/dist/cli/commands/delete.js.map +1 -1
  9. package/dist/cli/commands/export.d.ts.map +1 -1
  10. package/dist/cli/commands/export.js +25 -2
  11. package/dist/cli/commands/export.js.map +1 -1
  12. package/dist/cli/commands/get.js +1 -1
  13. package/dist/cli/commands/get.js.map +1 -1
  14. package/dist/cli/commands/integrations/helm.js +1 -1
  15. package/dist/cli/commands/integrations/helm.js.map +1 -1
  16. package/dist/cli/commands/integrations/kubernetes.js +2 -2
  17. package/dist/cli/commands/integrations/kubernetes.js.map +1 -1
  18. package/dist/cli/commands/integrations/terraform.js +2 -2
  19. package/dist/cli/commands/integrations/terraform.js.map +1 -1
  20. package/dist/cli/commands/key.d.ts +7 -1
  21. package/dist/cli/commands/key.d.ts.map +1 -1
  22. package/dist/cli/commands/key.js +789 -142
  23. package/dist/cli/commands/key.js.map +1 -1
  24. package/dist/cli/commands/list.d.ts.map +1 -1
  25. package/dist/cli/commands/list.js +32 -40
  26. package/dist/cli/commands/list.js.map +1 -1
  27. package/dist/cli/commands/pull.js +1 -1
  28. package/dist/cli/commands/pull.js.map +1 -1
  29. package/dist/cli/commands/push.d.ts.map +1 -1
  30. package/dist/cli/commands/push.js +24 -11
  31. package/dist/cli/commands/push.js.map +1 -1
  32. package/dist/cli/commands/rotation.d.ts +25 -0
  33. package/dist/cli/commands/rotation.d.ts.map +1 -0
  34. package/dist/cli/commands/rotation.js +364 -0
  35. package/dist/cli/commands/rotation.js.map +1 -0
  36. package/dist/cli/commands/scan.d.ts +18 -0
  37. package/dist/cli/commands/scan.d.ts.map +1 -0
  38. package/dist/cli/commands/scan.js +80 -0
  39. package/dist/cli/commands/scan.js.map +1 -0
  40. package/dist/cli/commands/set.d.ts.map +1 -1
  41. package/dist/cli/commands/set.js +33 -2
  42. package/dist/cli/commands/set.js.map +1 -1
  43. package/dist/cli/commands/sync.d.ts.map +1 -1
  44. package/dist/cli/commands/sync.js +14 -1
  45. package/dist/cli/commands/sync.js.map +1 -1
  46. package/dist/cli/index.js +198 -9
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cli/lib/audit-helper.d.ts +79 -0
  49. package/dist/cli/lib/audit-helper.d.ts.map +1 -0
  50. package/dist/cli/lib/audit-helper.js +182 -0
  51. package/dist/cli/lib/audit-helper.js.map +1 -0
  52. package/dist/cli/lib/create-client.d.ts +8 -0
  53. package/dist/cli/lib/create-client.d.ts.map +1 -1
  54. package/dist/cli/lib/create-client.js +41 -2
  55. package/dist/cli/lib/create-client.js.map +1 -1
  56. package/dist/cli/ui.d.ts +83 -0
  57. package/dist/cli/ui.d.ts.map +1 -0
  58. package/dist/cli/ui.js +197 -0
  59. package/dist/cli/ui.js.map +1 -0
  60. package/dist/client.d.ts +41 -1
  61. package/dist/client.d.ts.map +1 -1
  62. package/dist/client.js +134 -9
  63. package/dist/client.js.map +1 -1
  64. package/dist/index.d.ts +5 -2
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +5 -2
  67. package/dist/index.js.map +1 -1
  68. package/dist/lib/audit.d.ts +84 -0
  69. package/dist/lib/audit.d.ts.map +1 -0
  70. package/dist/lib/audit.js +342 -0
  71. package/dist/lib/audit.js.map +1 -0
  72. package/dist/lib/config-loader.d.ts +113 -5
  73. package/dist/lib/config-loader.d.ts.map +1 -1
  74. package/dist/lib/config-loader.js +243 -8
  75. package/dist/lib/config-loader.js.map +1 -1
  76. package/dist/lib/crypto.d.ts +74 -0
  77. package/dist/lib/crypto.d.ts.map +1 -0
  78. package/dist/lib/crypto.js +302 -0
  79. package/dist/lib/crypto.js.map +1 -0
  80. package/dist/lib/monorepo-detect.d.ts +72 -0
  81. package/dist/lib/monorepo-detect.d.ts.map +1 -0
  82. package/dist/lib/monorepo-detect.js +503 -0
  83. package/dist/lib/monorepo-detect.js.map +1 -0
  84. package/dist/load.js +1 -1
  85. package/dist/load.js.map +1 -1
  86. package/dist/loader.d.ts.map +1 -1
  87. package/dist/loader.js +3 -1
  88. package/dist/loader.js.map +1 -1
  89. package/dist/mcp/resources.d.ts +2 -0
  90. package/dist/mcp/resources.d.ts.map +1 -1
  91. package/dist/mcp/resources.js +288 -15
  92. package/dist/mcp/resources.js.map +1 -1
  93. package/dist/mcp/tools.d.ts +1 -1
  94. package/dist/mcp/tools.d.ts.map +1 -1
  95. package/dist/mcp/tools.js +709 -21
  96. package/dist/mcp/tools.js.map +1 -1
  97. package/dist/types.d.ts +205 -10
  98. package/dist/types.d.ts.map +1 -1
  99. package/dist/types.js +23 -4
  100. package/dist/types.js.map +1 -1
  101. package/package.json +13 -10
package/README.md CHANGED
@@ -6,32 +6,31 @@
6
6
 
7
7
  **One CLI to manage all your environment variables.**
8
8
 
9
- </div>
10
-
11
- ## Installation
9
+ [![npm version](https://img.shields.io/npm/v/vaulter.svg?style=flat-square&color=F5A623)](https://www.npmjs.com/package/vaulter)
10
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
11
+ [![Node.js](https://img.shields.io/badge/Node.js-22+-339933?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org/)
12
+ [![MCP](https://img.shields.io/badge/MCP-Claude_AI-7C3AED?style=flat-square&logo=anthropic&logoColor=white)](https://modelcontextprotocol.io/)
13
+ [![License](https://img.shields.io/npm/l/vaulter.svg?style=flat-square&color=007AFF)](https://github.com/forattini-dev/vaulter/blob/main/LICENSE)
12
14
 
13
- ### One-liner (recommended)
15
+ Store secrets anywhere: AWS S3, MinIO, R2, Spaces, B2, or local filesystem.
16
+ <br>
17
+ AES-256-GCM encryption. RSA/EC hybrid encryption. Native K8s, Helm & Terraform integration.
14
18
 
15
- ```bash
16
- curl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh
17
- ```
19
+ [Quick Start](#quick-start) · [Security](#security) · [CI/CD](#cicd) · [Commands](#commands)
18
20
 
19
- ### npm
21
+ </div>
20
22
 
21
- ```bash
22
- npm install -g vaulter
23
- ```
23
+ ---
24
24
 
25
- ### Specific version
25
+ ## Installation
26
26
 
27
27
  ```bash
28
- VAULTER_VERSION=v1.0.0 curl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh
29
- ```
30
-
31
- ### Custom directory
28
+ # One-liner (recommended)
29
+ curl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh
32
30
 
33
- ```bash
34
- VAULTER_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh
31
+ # Or via npm/pnpm
32
+ npm install -g vaulter
33
+ pnpm add -g vaulter
35
34
  ```
36
35
 
37
36
  ## Quick Start
@@ -41,10 +40,7 @@ VAULTER_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/forattin
41
40
  vaulter init
42
41
 
43
42
  # Set secrets (encrypted, synced to backend)
44
- vaulter set DATABASE_URL="postgres://localhost/mydb" API_KEY="sk-secret-key" -e dev
45
-
46
- # Set configs (plain text in split mode, synced in unified mode)
47
- vaulter set PORT::3000 LOG_LEVEL::debug -e dev
43
+ vaulter set DATABASE_URL="postgres://localhost/mydb" -e dev
48
44
 
49
45
  # Export to shell
50
46
  eval $(vaulter export -e dev)
@@ -55,1038 +51,476 @@ vaulter k8s:secret -e prd | kubectl apply -f -
55
51
 
56
52
  ---
57
53
 
58
- <div align="center">
59
-
60
- [![npm version](https://img.shields.io/npm/v/vaulter.svg?style=flat-square&color=F5A623)](https://www.npmjs.com/package/vaulter)
61
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
62
- [![Node.js](https://img.shields.io/badge/Node.js-22+-339933?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org/)
63
- [![License](https://img.shields.io/npm/l/vaulter.svg?style=flat-square&color=007AFF)](https://github.com/forattini-dev/vaulter/blob/main/LICENSE)
64
-
65
- Store secrets anywhere: AWS S3, MinIO, R2, Spaces, B2, or local filesystem.
66
- <br>
67
- AES-256-GCM encryption. Native K8s, Helm & Terraform integration.
68
- <br>
69
- MCP server for Claude AI. Zero config for dev, production-ready.
70
-
71
- [📖 Documentation](#configuration) · [🔧 CLI](#commands) · [🚀 Highlights](#highlights)
72
-
73
- </div>
74
-
75
- ---
76
-
77
54
  ## Table of Contents
78
55
 
79
- - [Installation](#installation)
80
- - [Quick Start](#quick-start)
81
- - [What's Inside](#whats-inside)
82
- - [Highlights](#highlights)
83
- - [Commands](#commands)
56
+ - [Why Vaulter?](#why-vaulter)
57
+ - [Security](#security)
58
+ - [Daily Use](#daily-use)
59
+ - [CI/CD](#cicd)
84
60
  - [Configuration](#configuration)
85
- - [Directory Modes](#directory-modes)
86
- - [Backend URLs](#backend-urls)
87
- - [Encryption](#encryption)
88
- - [Running Commands](#running-commands)
89
- - [Shell Scripts](#shell-scripts)
90
- - [Interactive Tools](#interactive-tools)
91
61
  - [Integrations](#integrations)
92
- - [kubectl](#kubectl)
93
- - [Helm & Helmfile](#helm--helmfile)
94
- - [Terraform & Terragrunt](#terraform--terragrunt)
95
62
  - [Monorepo Support](#monorepo-support)
96
- - [NX Monorepo](#nx-monorepo)
97
- - [Turborepo](#turborepo)
98
- - [MCP Server](#mcp-server)
99
- - [MCP Tools](#mcp-tools-14)
100
- - [MCP Resources](#mcp-resources-5)
101
- - [MCP Prompts](#mcp-prompts-5)
102
- - [CI/CD](#cicd)
103
- - [Developer Daily Workflow](#developer-daily-workflow)
104
- - [GitHub Actions](#github-actions)
105
- - [GitLab CI](#gitlab-ci)
106
- - [CircleCI](#circleci)
107
- - [Azure DevOps](#azure-devops)
108
- - [Security Best Practices](#security-best-practices)
109
63
  - [API Usage](#api-usage)
110
- - [Pre-built Binaries](#pre-built-binaries)
64
+ - [MCP Server](#mcp-server)
111
65
 
112
66
  ---
113
67
 
114
- ## What's Inside
68
+ ## Why Vaulter?
115
69
 
116
- | Category | Features |
117
- |:---------|:---------|
118
- | **Backends** | AWS S3, MinIO, Cloudflare R2, DigitalOcean Spaces, Backblaze B2, FileSystem, Memory |
119
- | **Encryption** | AES-256-GCM via s3db.js, field-level encryption |
120
- | **Environments** | dev, stg, prd, sbx, dr (configurable subset) |
121
- | **Integrations** | Kubernetes Secret/ConfigMap, Helm values.yaml, Terraform tfvars |
122
- | **Monorepo** | Service discovery, batch operations, config inheritance |
123
- | **MCP Server** | Claude AI integration via Model Context Protocol |
124
- | **Unix Pipes** | Full stdin/stdout support for scripting |
125
- | **Dotenv** | Drop-in compatible: `import 'vaulter/load'` |
70
+ ### The Problem
126
71
 
127
- ## Highlights
72
+ Environment variables and secrets are scattered across `.env` files, CI/CD settings, cloud consoles, and team Slack messages. This creates:
128
73
 
129
- ### Multi-Backend with Fallback
74
+ - **Security gaps**: Secrets in plaintext files, git history, or shared docs
75
+ - **Sync issues**: "Works on my machine" because `.env` files differ
76
+ - **Deploy friction**: Manual copy-paste between environments
77
+ - **Audit blindness**: No idea who changed what, when
130
78
 
131
- Configure multiple backends - vaulter tries each until one succeeds:
79
+ ### The Solution
132
80
 
133
- ```yaml
134
- backend:
135
- urls:
136
- - s3://bucket/envs?region=us-east-1 # Primary (CI/CD)
137
- - file:///home/user/.vaulter-store # Fallback (local dev)
138
- ```
81
+ Vaulter centralizes all environment variables in encrypted storage (S3-compatible) while maintaining the simplicity of `.env` files:
139
82
 
140
- ### Native Integrations
83
+ | Traditional | With Vaulter |
84
+ |:------------|:-------------|
85
+ | Secrets in plaintext `.env` | Encrypted at rest (AES-256-GCM) |
86
+ | Manual sync between devs | `vaulter pull` / `vaulter push` |
87
+ | Copy-paste to CI/CD | `eval $(vaulter export -e prd)` |
88
+ | No audit trail | Full history via S3 versioning |
89
+ | Different files per machine | Single source of truth |
141
90
 
142
- ```bash
143
- # Kubernetes - deploy secrets directly
144
- vaulter k8s:secret -e prd | kubectl apply -f -
91
+ ### Why Trust Vaulter?
145
92
 
146
- # Helm - generate values file
147
- vaulter helm:values -e prd | helm upgrade myapp ./chart -f -
93
+ 1. **Open source**: All code is auditable
94
+ 2. **No lock-in**: Your data lives in YOUR storage (S3, MinIO, R2, filesystem)
95
+ 3. **Standard encryption**: AES-256-GCM, the same used by AWS, Google, and banks
96
+ 4. **Zero external dependencies**: No SaaS, no API keys, no third-party services
97
+ 5. **Offline capable**: Works with local filesystem backend
148
98
 
149
- # Terraform - export as tfvars
150
- vaulter tf:vars -e prd > terraform.tfvars
151
- ```
99
+ ---
152
100
 
153
- ### Unix Pipes
101
+ ## Security
154
102
 
155
- ```bash
156
- # Import from Vault
157
- vault kv get -format=json secret/app | \
158
- jq -r '.data.data | to_entries | .[] | "\(.key)=\(.value)"' | \
159
- vaulter sync -e prd
160
-
161
- # Export to kubectl
162
- vaulter export -e prd --format=env | \
163
- kubectl create secret generic myapp --from-env-file=/dev/stdin
164
- ```
103
+ ### Encryption Model
165
104
 
166
- ### MCP Server for Claude
105
+ Every secret is encrypted **before** leaving your machine using **AES-256-GCM**:
167
106
 
168
- ```bash
169
- # Start MCP server
170
- vaulter mcp
171
107
  ```
172
-
173
- ```json
174
- {
175
- "mcpServers": {
176
- "vaulter": {
177
- "command": "npx",
178
- "args": ["vaulter", "mcp"]
179
- }
180
- }
181
- }
108
+ ┌─────────────────────────────────────────────────────────────┐
109
+ │ Your Machine │
110
+ │ │
111
+ .env file ──► vaulter encrypt ──► encrypted blob ──► S3 │
112
+ │ (AES-256-GCM) (unreadable) │
113
+ │ │
114
+ │ S3 ──► encrypted blob ──► vaulter decrypt ──► .env file │
115
+ │ (unreadable) (AES-256-GCM) │
116
+ └─────────────────────────────────────────────────────────────┘
182
117
  ```
183
118
 
184
- ### Dotenv Compatible
119
+ **What this means:**
120
+ - The backend (S3, MinIO, etc.) only sees encrypted data
121
+ - Even with S3 access, secrets are unreadable without the key
122
+ - Each value is encrypted individually (field-level encryption)
123
+ - Authenticated encryption prevents tampering (GCM mode)
185
124
 
186
- Drop-in replacement for dotenv - works with your existing setup:
125
+ ### Key Management
187
126
 
188
- ```typescript
189
- // Auto-load .env into process.env
190
- import 'vaulter/load'
127
+ Vaulter stores keys in `~/.vaulter/` directory (outside project) for security:
191
128
 
192
- // Or programmatically with options
193
- import { loader } from 'vaulter'
194
- loader({ path: '.env.local', override: true })
129
+ ```
130
+ ~/.vaulter/
131
+ ├── projects/
132
+ │ └── <project-name>/
133
+ │ └── keys/
134
+ │ ├── master # Private key (mode 600)
135
+ │ └── master.pub # Public key (mode 644)
136
+ └── global/
137
+ └── keys/ # Shared across all projects
138
+ ├── shared
139
+ └── shared.pub
195
140
  ```
196
141
 
197
- ## Commands
198
-
199
- ### Core
200
-
201
- | Command | Description | Example |
202
- |:--------|:------------|:--------|
203
- | `init` | Initialize project | `vaulter init` |
204
- | `get <key>` | Get a variable | `vaulter get DATABASE_URL -e prd` |
205
- | `set KEY=val ...` | Set secrets (batch) | `vaulter set KEY1=v1 KEY2=v2 -e prd` |
206
- | `set KEY::val ...` | Set configs (plain) | `vaulter set PORT::3000 HOST::0.0.0.0 -e dev` |
207
- | `delete <key>` | Delete a variable | `vaulter delete OLD_KEY -e dev` |
208
- | `list` | List all variables | `vaulter list -e prd` |
209
- | `export` | Export for shell | `eval $(vaulter export -e dev)` |
210
-
211
- ### Sync
212
-
213
- | Command | Description | Example |
214
- |:--------|:------------|:--------|
215
- | `sync` | Merge local .env and backend | `vaulter sync -f .env.local -e dev` |
216
- | `pull` | Download to .env | `vaulter pull -e prd -o .env.prd` |
217
- | `push` | Upload from .env | `vaulter push -f .env.local -e dev` |
218
-
219
- ### Integrations
220
-
221
- | Command | Description | Example |
222
- |:--------|:------------|:--------|
223
- | `k8s:secret` | Kubernetes Secret | `vaulter k8s:secret -e prd \| kubectl apply -f -` |
224
- | `k8s:configmap` | Kubernetes ConfigMap | `vaulter k8s:configmap -e prd` |
225
- | `helm:values` | Helm values.yaml | `vaulter helm:values -e prd` |
226
- | `tf:vars` | Terraform .tfvars | `vaulter tf:vars -e prd > terraform.tfvars` |
227
- | `tf:json` | Terraform JSON | `vaulter tf:json -e prd` |
228
-
229
- ### Utilities
230
-
231
- | Command | Description | Example |
232
- |:--------|:------------|:--------|
233
- | `key generate` | Generate encryption key | `vaulter key generate` |
234
- | `services` | List monorepo services | `vaulter services` |
235
- | `mcp` | Start MCP server | `vaulter mcp` |
236
-
237
- ### Set Command Syntax
238
-
239
- HTTPie-style separators for differentiating secrets from configs:
142
+ #### Key Commands
240
143
 
241
144
  ```bash
242
- # Secrets (encrypted, synced to backend)
243
- vaulter set KEY=value # Single secret
244
- vaulter set A=1 B=2 C=3 -e dev # Batch secrets
245
- vaulter set KEY:=123 # Typed secret (number/boolean)
145
+ # Generate keys
146
+ vaulter key generate --name master # Symmetric key
147
+ vaulter key generate --name master --asymmetric # RSA-4096 key pair
148
+ vaulter key generate --name master --asym --alg ec-p256 # EC P-256 key pair
149
+ vaulter key generate --name shared --global # Global key (all projects)
246
150
 
247
- # Configs (plain text, file only in split mode, synced in unified mode)
248
- vaulter set PORT::3000 HOST::localhost # Configs
151
+ # List and show keys
152
+ vaulter key list # List all keys (project + global)
153
+ vaulter key show --name master # Show key details
249
154
 
250
- # With metadata
251
- vaulter set DB_URL=postgres://... @tag:database,sensitive @owner:backend -e prd
155
+ # Export/import for deployment
156
+ vaulter key export --name master -o keys.enc # Export encrypted bundle
157
+ vaulter key import -f keys.enc # Import on another machine
252
158
 
253
- # Legacy syntax (still works)
254
- vaulter set KEY "value" -e dev # Treated as secret
159
+ # Set VAULTER_EXPORT_PASSPHRASE to encrypt the bundle with custom passphrase
255
160
  ```
256
161
 
257
- | Separator | Type | Backend Sync | Encryption (backend) |
258
- |:----------|:-----|:-------------|:-----------|
259
- | `=` | Secret | ✓ | ✓ |
260
- | `:=` | Secret (typed) | ✓ | ✓ |
261
- | `::` | Config | Split: ✗ / Unified: ✓ | ✓ |
262
- | `@key:value` | Metadata | — | — |
162
+ #### Configuration with key_name
263
163
 
264
- Note: Config files remain plain text; backend storage is encrypted for all values.
265
-
266
- ## Global Options
267
-
268
- ```
269
- -p, --project <name> Project name
270
- -s, --service <name> Service name (monorepos)
271
- -e, --env <env> Environment: dev, stg, prd, sbx, dr
272
- -b, --backend <url> Backend URL override
273
- -k, --key <path|value> Encryption key file path or raw key
274
- -v, --verbose Verbose output
275
- --all All services (monorepo batch)
276
- --dry-run Preview without applying
277
- --json JSON output
278
- --force Skip confirmations
279
- ```
280
-
281
- ## Configuration
282
-
283
- ### Basic Config
164
+ The simplest way to use keys is via `key_name` resolution:
284
165
 
285
166
  ```yaml
286
167
  # .vaulter/config.yaml
287
- version: "1"
288
-
289
- project: my-project
290
- service: api # optional
291
-
292
- backend:
293
- # Single URL
294
- url: s3://bucket/envs?region=us-east-1
295
-
296
- # Or multiple with fallback
297
- urls:
298
- - s3://bucket/envs?region=us-east-1
299
- - file:///home/user/.vaulter-store
300
-
301
168
  encryption:
302
- key_source:
303
- - env: VAULTER_KEY # 1. Environment variable
304
- - file: .vaulter/.key # 2. Local file
305
- - s3: s3://keys/vaulter.key # 3. Remote S3
306
-
307
- environments:
308
- - dev
309
- - stg
310
- - prd
311
-
312
- default_environment: dev
313
- ```
314
-
315
- ### Sync Settings
316
-
317
- Sync merges local and remote variables. Conflicts are resolved by `sync.conflict`.
318
-
319
- ```yaml
320
- sync:
321
- conflict: local # local | remote | error
322
- ignore:
323
- - "PUBLIC_*"
324
- required:
325
- dev:
326
- - DATABASE_URL
327
- ```
328
-
329
- Notes:
330
- - `local` (default): Local values win on conflict, remote-only keys are pulled to local
331
- - `remote`: Remote values win on conflict
332
- - `error`: Stop sync if any conflicts are detected
333
- - When reading from stdin, sync only updates the backend (local file is not changed).
334
-
335
- ### Directory Modes
336
-
337
- Vaulter supports two directory structures for organizing environment files:
338
-
339
- #### Unified Mode (Default)
340
-
341
- All environment files in a single directory:
342
-
343
- ```
344
- my-project/
345
- ├── .vaulter/
346
- │ ├── config.yaml
347
- │ └── environments/
348
- │ ├── dev.env # All vars (secrets + configs)
349
- │ ├── stg.env
350
- │ └── prd.env
169
+ mode: asymmetric
170
+ asymmetric:
171
+ algorithm: rsa-4096
172
+ key_name: master # → ~/.vaulter/projects/<project>/keys/master[.pub]
173
+ # Or for global key:
174
+ # key_name: global:master # → ~/.vaulter/global/keys/master[.pub]
351
175
  ```
352
176
 
353
- #### Split Mode
177
+ #### Legacy Key Sources (still supported)
354
178
 
355
- Separate directories for configs (committable) and secrets (gitignored):
356
-
357
- ```
358
- my-project/
359
- ├── .vaulter/
360
- │ └── config.yaml
361
- └── deploy/
362
- ├── configs/ # ✅ Committable (non-sensitive)
363
- │ ├── dev.env # NODE_ENV, PORT, LOG_LEVEL
364
- │ ├── stg.env
365
- │ └── prd.env
366
- └── secrets/ # ❌ Gitignored (sensitive)
367
- ├── dev.env # DATABASE_URL, JWT_SECRET
368
- ├── stg.env
369
- └── prd.env
370
- ```
371
-
372
- Configure split mode in `config.yaml`:
179
+ You can also specify explicit key sources:
373
180
 
374
181
  ```yaml
375
- directories:
376
- mode: split # "unified" (default) or "split"
377
- configs: deploy/configs # Non-sensitive vars (committable)
378
- secrets: deploy/secrets # Sensitive vars (gitignored)
182
+ encryption:
183
+ key_source:
184
+ - env: VAULTER_KEY # 1. Environment variable (CI/CD)
185
+ - file: .vaulter/.key # 2. Local file (development)
186
+ - s3: s3://keys/vaulter.key # 3. Remote S3 (shared teams)
379
187
  ```
380
188
 
381
- Tip: scaffold split mode with `vaulter init --split`.
382
-
383
- **Behavior in split mode:**
384
- - `sync`, `pull`, `push` operate on the **secrets** directory
385
- - `k8s:secret` reads from local **secrets** file (no backend fetch)
386
- - `k8s:configmap` reads from local **configs** file (no backend fetch)
387
- - Configs are managed via git, secrets via vaulter
388
-
389
- **When to use split mode:**
390
- - Monorepos with deploy directories per service
391
- - Teams that want configs reviewed in PRs
392
- - Environments where non-sensitive configs should be in git
189
+ ##### Option 1: Environment Variable (Recommended for CI/CD)
393
190
 
394
- ### Hooks
191
+ ```bash
192
+ # Generate a key
193
+ vaulter key generate --name master
395
194
 
396
- ```yaml
397
- hooks:
398
- pre_sync: "echo pre sync"
399
- post_sync: "echo post sync"
400
- pre_pull: "echo pre pull"
401
- post_pull: "echo post pull"
195
+ # Set in CI/CD secrets from the generated key
196
+ export VAULTER_KEY=$(cat ~/.vaulter/projects/myproject/keys/master)
402
197
  ```
403
198
 
404
- ### Environment Variable Expansion
199
+ **Pros**: Key never in project directory, rotates easily via CI/CD secret rotation
200
+ **Use case**: GitHub Actions, GitLab CI, Jenkins
405
201
 
406
- Config values support `${VAR}`, `${VAR:-default}`, and `$VAR`:
202
+ ##### Option 2: key_name Resolution (Recommended for Development)
407
203
 
408
204
  ```yaml
409
- backend:
410
- url: s3://${AWS_ACCESS_KEY_ID}:${AWS_SECRET_ACCESS_KEY}@bucket/envs
411
- # Or
412
- url: ${VAULTER_BACKEND_URL}
205
+ encryption:
206
+ mode: asymmetric
207
+ asymmetric:
208
+ key_name: master # Auto-resolves to ~/.vaulter/projects/<project>/keys/
413
209
  ```
414
210
 
415
- ### Local Override (config.local.yaml)
211
+ **Pros**: Simple, keys stored securely outside project
212
+ **Use case**: Local development, team workflows
416
213
 
417
- For credentials that should **never** be committed:
214
+ ##### Option 3: Remote S3 (Team Shared)
418
215
 
419
216
  ```yaml
420
- # .vaulter/config.local.yaml (gitignored)
421
- backend:
422
- url: s3://real-key:real-secret@bucket/envs?region=us-east-1
217
+ encryption:
218
+ key_source:
219
+ - s3: s3://company-keys/vaulter/project.key?region=us-east-1
423
220
  ```
424
221
 
425
- ## Backend URLs
426
-
427
- | Provider | URL Format |
428
- |:---------|:-----------|
429
- | **AWS S3** | `s3://bucket/path?region=us-east-1` |
430
- | **AWS S3 + Profile** | `s3://bucket/path?region=us-east-1&profile=myprofile` |
431
- | **AWS S3 + Credentials** | `s3://${KEY}:${SECRET}@bucket/path` |
432
- | **MinIO** | `http://${KEY}:${SECRET}@localhost:9000/bucket` |
433
- | **Cloudflare R2** | `https://${KEY}:${SECRET}@${ACCOUNT}.r2.cloudflarestorage.com/bucket` |
434
- | **DigitalOcean Spaces** | `https://${KEY}:${SECRET}@nyc3.digitaloceanspaces.com/bucket` |
435
- | **Backblaze B2** | `https://${KEY}:${SECRET}@s3.us-west-002.backblazeb2.com/bucket` |
436
- | **FileSystem** | `file:///path/to/storage` |
437
- | **Memory** | `memory://bucket-name` |
438
-
439
- ## Encryption
440
-
441
- All secrets are encrypted with **AES-256-GCM** before storage.
222
+ **Pros**: Centralized key management, IAM-controlled access
223
+ **Use case**: Teams, multiple developers needing same key
442
224
 
443
- ### Key Sources
225
+ ### Asymmetric Key Encryption (RSA/EC)
444
226
 
445
- ```bash
446
- # 1. Environment variable (CI/CD)
447
- export VAULTER_KEY="base64-encoded-32-byte-key"
448
- vaulter export -e prd
449
-
450
- # 2. Local file (development)
451
- vaulter key generate -o .vaulter/.key
452
-
453
- # 3. Remote S3 (production)
454
- # Configured in config.yaml
455
- ```
227
+ For enhanced security with separate encrypt/decrypt permissions, Vaulter supports hybrid encryption using RSA or Elliptic Curve key pairs.
456
228
 
457
- You can also pass a key directly:
229
+ #### How It Works
458
230
 
459
- ```bash
460
- vaulter list -e prd --key .vaulter/.key
461
231
  ```
462
-
463
- ### Security Settings
464
-
465
- ```yaml
466
- security:
467
- paranoid: true # Fail if no encryption key is found
468
- auto_encrypt:
469
- patterns:
470
- - "*_KEY"
471
- - "*_SECRET"
472
- - "DATABASE_URL"
232
+ ┌────────────────────────────────────────────────────────────────┐
233
+ │ Hybrid Encryption │
234
+ │ │
235
+ │ Your secret ──► AES-256-GCM ──► Encrypted data │
236
+ │ │ │
237
+ │ │ (random AES key) │
238
+ │ ▼ │
239
+ │ Public key ──► RSA/EC encrypt ──► Encrypted AES key │
240
+ │ │
241
+ │ Stored: { encrypted_key + encrypted_data + metadata } │
242
+ │ │
243
+ │ Decryption requires: Private key + Encrypted blob │
244
+ └────────────────────────────────────────────────────────────────┘
473
245
  ```
474
246
 
475
- `auto_encrypt.patterns` is used to classify secrets for integrations (K8s/Helm).
476
-
477
- ## Running Commands
478
-
479
- Load environment variables into any command using `eval $(vaulter export)`.
480
-
481
- ### Shell Scripts
482
-
483
- ```bash
484
- # Run a script with environment variables
485
- eval $(vaulter export -e dev) ./myscript.sh
486
-
487
- # Or in two steps
488
- eval $(vaulter export -e dev)
489
- ./myscript.sh
247
+ **Benefits:**
248
+ - **Separation of duties**: Public key can only encrypt, private key can decrypt
249
+ - **CI/CD security**: Give CI/CD only the public key - it can write but not read secrets
250
+ - **Production isolation**: Only production has the private key for decryption
490
251
 
491
- # One-liner with subshell (vars don't persist after)
492
- (eval $(vaulter export -e prd) && ./deploy.sh)
493
-
494
- # Using env command (cleaner syntax)
495
- env $(vaulter export -e dev --format=shell) ./myscript.sh
496
- ```
497
-
498
- ### Interactive Tools
252
+ #### Generate Key Pair
499
253
 
500
254
  ```bash
501
- # k9s with production credentials
502
- eval $(vaulter export -e prd) k9s
503
-
504
- # psql with database URL
505
- eval $(vaulter export -e dev) psql $DATABASE_URL
255
+ # RSA 4096-bit (default, most compatible)
256
+ vaulter key generate --name master --asymmetric
506
257
 
507
- # redis-cli
508
- eval $(vaulter export -e dev) redis-cli -u $REDIS_URL
258
+ # RSA 2048-bit (faster, less secure)
259
+ vaulter key generate --name master --asym --algorithm rsa-2048
509
260
 
510
- # AWS CLI with credentials
511
- eval $(vaulter export -e prd) aws s3 ls
261
+ # Elliptic Curve P-256 (modern, fast)
262
+ vaulter key generate --name master --asym --alg ec-p256
512
263
 
513
- # Docker run with env vars
514
- eval $(vaulter export -e dev) docker run --env-file <(vaulter export -e dev --format=env) myapp
264
+ # Elliptic Curve P-384 (stronger EC)
265
+ vaulter key generate --name master --asym --alg ec-p384
515
266
 
516
- # Any Node.js app
517
- eval $(vaulter export -e dev) node server.js
518
-
519
- # Python app
520
- eval $(vaulter export -e dev) python app.py
267
+ # Global key (shared across all projects)
268
+ vaulter key generate --name shared --global --asymmetric
521
269
  ```
522
270
 
523
- ### Shell Alias (Recommended)
524
-
525
- Add to your `~/.bashrc` or `~/.zshrc`:
526
-
527
- ```bash
528
- # Quick alias for common environments
529
- alias vdev='eval $(vaulter export -e dev)'
530
- alias vstg='eval $(vaulter export -e stg)'
531
- alias vprd='eval $(vaulter export -e prd)'
532
-
533
- # Usage
534
- vdev ./myscript.sh
535
- vprd k9s
536
- vstg psql $DATABASE_URL
537
- ```
538
-
539
- ### One-liner Pattern
540
-
541
- ```bash
542
- # Pattern: eval $(vaulter export -e ENV) COMMAND
543
- eval $(vaulter export -e dev) npm run dev
544
- eval $(vaulter export -e prd) kubectl get pods
545
- eval $(vaulter export -e stg) terraform plan
546
- ```
547
-
548
- ## Integrations
549
-
550
- ### kubectl
551
-
552
- ```bash
553
- # Create Secret from vaulter
554
- vaulter k8s:secret -e prd | kubectl apply -f -
555
-
556
- # Create ConfigMap (non-secret vars)
557
- vaulter k8s:configmap -e prd | kubectl apply -f -
558
-
559
- # With custom name and namespace
560
- vaulter k8s:secret -e prd -n my-namespace --name my-app-secrets | kubectl apply -f -
561
-
562
- # Dry-run to see YAML
563
- vaulter k8s:secret -e prd --dry-run
564
-
565
- # Create secret from export (alternative)
566
- vaulter export -e prd --format=env | \
567
- kubectl create secret generic myapp --from-env-file=/dev/stdin --dry-run=client -o yaml | \
568
- kubectl apply -f -
569
-
570
- # Run kubectl with vaulter vars
571
- eval $(vaulter export -e prd) kubectl exec -it deploy/myapp -- env | grep DATABASE
271
+ Output:
572
272
  ```
273
+ ✓ Generated rsa-4096 key pair: master
274
+ Private: ~/.vaulter/projects/my-project/keys/master (mode 600 - keep secret!)
275
+ Public: ~/.vaulter/projects/my-project/keys/master.pub (mode 644)
573
276
 
574
- ### Helm & Helmfile
575
-
576
- #### Helm
577
-
578
- ```bash
579
- # Generate values.yaml and pipe to helm
580
- vaulter helm:values -e prd | helm upgrade myapp ./chart -f -
581
-
582
- # Save values to file
583
- vaulter helm:values -e prd > values.prd.yaml
584
- helm upgrade myapp ./chart -f values.prd.yaml
585
-
586
- # With secrets separated (uses auto_encrypt.patterns)
587
- vaulter helm:values -e prd --secrets # Only secret vars
588
- vaulter helm:values -e prd --config # Only non-secret vars
589
-
590
- # Install with inline values
591
- helm install myapp ./chart \
592
- --set-string DATABASE_URL="$(vaulter get DATABASE_URL -e prd)" \
593
- --set-string API_KEY="$(vaulter get API_KEY -e prd)"
277
+ To use these keys in config.yaml:
278
+ encryption:
279
+ mode: asymmetric
280
+ asymmetric:
281
+ algorithm: rsa-4096
282
+ key_name: master
594
283
  ```
595
284
 
596
- #### Helmfile
285
+ #### Configuration
597
286
 
598
287
  ```yaml
599
- # helmfile.yaml
600
- repositories:
601
- - name: bitnami
602
- url: https://charts.bitnami.com/bitnami
603
-
604
- releases:
605
- - name: myapp
606
- namespace: production
607
- chart: ./charts/myapp
608
- values:
609
- - values.yaml
610
- - values.prd.yaml # Generated by: vaulter helm:values -e prd > values.prd.yaml
611
- ```
612
-
613
- ```bash
614
- # Generate values before helmfile sync
615
- vaulter helm:values -e prd > values.prd.yaml
616
- helmfile sync
617
-
618
- # Or use process substitution
619
- helmfile sync --values <(vaulter helm:values -e prd)
620
-
621
- # With environment variables for helmfile
622
- eval $(vaulter export -e prd) helmfile apply
623
- ```
624
-
625
- ### Terraform & Terragrunt
626
-
627
- #### Terraform
628
-
629
- ```bash
630
- # Generate .tfvars file
631
- vaulter tf:vars -e prd > terraform.tfvars
632
- terraform plan
633
-
634
- # Generate JSON format
635
- vaulter tf:json -e prd > terraform.tfvars.json
636
- terraform plan -var-file=terraform.tfvars.json
637
-
638
- # Pass vars inline
639
- terraform plan \
640
- -var="database_url=$(vaulter get DATABASE_URL -e prd)" \
641
- -var="api_key=$(vaulter get API_KEY -e prd)"
642
-
643
- # Use TF_VAR_* environment variables
644
- eval $(vaulter export -e prd --format=tfvars)
645
- terraform plan
646
-
647
- # Pipe directly (requires bash process substitution)
648
- terraform plan -var-file=<(vaulter tf:vars -e prd)
649
- ```
650
-
651
- #### Terragrunt
652
-
653
- ```bash
654
- # Set env vars for terragrunt
655
- eval $(vaulter export -e prd) terragrunt plan
656
-
657
- # Generate inputs file
658
- vaulter tf:vars -e prd > inputs.tfvars
659
- terragrunt plan --terragrunt-config terragrunt.hcl
660
-
661
- # In terragrunt.hcl - use environment variables
662
- # terragrunt.hcl
663
- inputs = {
664
- database_url = get_env("DATABASE_URL", "")
665
- api_key = get_env("API_KEY", "")
666
- }
667
-
668
- # Then run:
669
- eval $(vaulter export -e prd) terragrunt apply
670
-
671
- # Or with inputs file
672
- # terragrunt.hcl
673
- terraform {
674
- extra_arguments "custom_vars" {
675
- commands = get_terraform_commands_that_need_vars()
676
- arguments = [
677
- "-var-file=inputs.tfvars"
678
- ]
679
- }
680
- }
681
- ```
682
-
683
- ```bash
684
- # Full workflow with terragrunt
685
- vaulter pull -e prd # Get latest vars
686
- vaulter tf:vars -e prd > inputs.tfvars # Generate tfvars
687
- terragrunt plan # Plan with vars
688
- terragrunt apply # Apply
689
- ```
690
-
691
- ### Integration Summary
692
-
693
- | Tool | Command |
694
- |:-----|:--------|
695
- | **kubectl** | `vaulter k8s:secret -e prd \| kubectl apply -f -` |
696
- | **helm** | `vaulter helm:values -e prd \| helm upgrade app ./chart -f -` |
697
- | **helmfile** | `vaulter helm:values -e prd > values.prd.yaml && helmfile sync` |
698
- | **terraform** | `vaulter tf:vars -e prd > terraform.tfvars && terraform plan` |
699
- | **terragrunt** | `eval $(vaulter export -e prd) terragrunt apply` |
700
- | **any command** | `eval $(vaulter export -e ENV) COMMAND` |
701
-
702
- ## Monorepo Support
703
-
704
- Vaulter auto-discovers services with `.vaulter/` directories and supports config inheritance.
705
-
706
- ### NX Monorepo
707
-
708
- ```
709
- my-nx-workspace/
710
- ├── .vaulter/
711
- │ ├── config.yaml # Shared config (backend, encryption)
712
- │ └── environments/
713
- │ └── dev.env # Shared dev vars
714
- ├── apps/
715
- │ ├── web/
716
- │ │ └── .vaulter/
717
- │ │ ├── config.yaml # extends: ../../../.vaulter/config.yaml
718
- │ │ └── environments/
719
- │ │ └── dev.env # App-specific vars
720
- │ └── api/
721
- │ └── .vaulter/
722
- │ ├── config.yaml
723
- │ └── environments/
724
- ├── libs/ # No .vaulter needed for libs
725
- ├── nx.json
726
- └── package.json
727
- ```
728
-
729
- ```bash
730
- # From workspace root
731
- vaulter services # List: web, api
732
-
733
- # Sync all apps
734
- vaulter sync -e dev --all
735
-
736
- # Sync single app (from root or app dir)
737
- vaulter sync -e dev -s api
738
- cd apps/api && vaulter sync -e dev
739
-
740
- # NX run with env vars
741
- eval $(vaulter export -e dev -s api) && nx serve api
742
- ```
743
-
744
- ### Turborepo
745
-
746
- ```
747
- my-turbo-monorepo/
748
- ├── .vaulter/
749
- │ ├── config.yaml # Root config
750
- │ └── environments/
751
- ├── apps/
752
- │ ├── web/
753
- │ │ ├── .vaulter/
754
- │ │ │ ├── config.yaml # extends: ../../../.vaulter/config.yaml
755
- │ │ │ └── environments/
756
- │ │ └── package.json
757
- │ └── docs/
758
- │ └── .vaulter/
759
- ├── packages/ # Shared packages (no .vaulter)
760
- ├── turbo.json
761
- └── package.json
762
- ```
763
-
764
- ```bash
765
- # List discovered services
766
- vaulter services
767
-
768
- # Batch sync before turbo build
769
- vaulter sync -e prd --all && turbo build
770
-
771
- # Export for specific app
772
- cd apps/web && eval $(vaulter export -e dev)
773
-
774
- # Turbo with env passthrough (turbo.json)
775
- # { "pipeline": { "build": { "env": ["DATABASE_URL", "API_KEY"] } } }
776
- vaulter export -e prd -s web --format=shell >> apps/web/.env
777
- turbo build --filter=web
778
- ```
779
-
780
- ### Service Config Inheritance
288
+ # .vaulter/config.yaml
289
+ encryption:
290
+ mode: asymmetric # Enable asymmetric mode
291
+ asymmetric:
292
+ algorithm: rsa-4096 # or rsa-2048, ec-p256, ec-p384
293
+ key_name: master # Uses ~/.vaulter/projects/<project>/keys/master[.pub]
294
+ # Or for global keys:
295
+ # key_name: global:master # Uses ~/.vaulter/global/keys/master[.pub]
296
+
297
+ # Alternative: explicit key sources (for CI/CD or custom paths)
298
+ # encryption:
299
+ # mode: asymmetric
300
+ # asymmetric:
301
+ # algorithm: rsa-4096
302
+ # public_key:
303
+ # - file: /path/to/master.pub
304
+ # - env: VAULTER_PUBLIC_KEY
305
+ # private_key:
306
+ # - file: /path/to/master
307
+ # - env: VAULTER_PRIVATE_KEY
308
+ ```
309
+
310
+ #### Supported Algorithms
311
+
312
+ | Algorithm | Key Size | Performance | Use Case |
313
+ |:----------|:---------|:------------|:---------|
314
+ | `rsa-4096` | 4096 bits | Slower | Maximum security, wide compatibility |
315
+ | `rsa-2048` | 2048 bits | Medium | Good balance, legacy systems |
316
+ | `ec-p256` | 256 bits | Fast | Modern systems, smaller keys |
317
+ | `ec-p384` | 384 bits | Medium | Higher security EC |
318
+
319
+ #### Use Case: Secure CI/CD Pipeline
320
+
321
+ ```
322
+ ┌─────────────────────────────────────────────────────────────┐
323
+ Development │
324
+ │ Developers have BOTH keys can read and write secrets │
325
+ │ vaulter set API_KEY="..." -e dev │
326
+ └──────────────────────────┬──────────────────────────────────┘
327
+
328
+
329
+ ┌─────────────────────────────────────────────────────────────┐
330
+ │ CI/CD (GitHub Actions, Jenkins, etc.)
331
+ │ Only PUBLIC key → can write NEW secrets, cannot read │
332
+ │ Useful for automated secret rotation scripts │
333
+ │ │
334
+ │ env: │
335
+ │ VAULTER_PUBLIC_KEY: ${{ secrets.VAULTER_PUBLIC_KEY }} │
336
+ └──────────────────────────┬──────────────────────────────────┘
337
+
338
+
339
+ ┌─────────────────────────────────────────────────────────────┐
340
+ Production │
341
+ │ Only PRIVATE key → can read secrets at runtime │
342
+ │ │
343
+ env: │
344
+ │ VAULTER_PRIVATE_KEY: ${{ secrets.VAULTER_PRIVATE_KEY }}
345
+ │ │
346
+ # Application reads secrets at startup │
347
+ │ eval $(vaulter export -e prd) │
348
+ └─────────────────────────────────────────────────────────────┘
349
+ ```
350
+
351
+ #### Environment Variables
352
+
353
+ | Variable | Purpose |
354
+ |:---------|:--------|
355
+ | `VAULTER_PUBLIC_KEY` | Public key PEM content (for encryption) |
356
+ | `VAULTER_PRIVATE_KEY` | Private key PEM content (for decryption) |
357
+
358
+ ### Advanced Security Configurations
359
+
360
+ #### AWS KMS Integration (Planned)
361
+
362
+ For enterprises requiring HSM-backed keys:
781
363
 
782
364
  ```yaml
783
- # apps/api/.vaulter/config.yaml
784
- extends: ../../../.vaulter/config.yaml # Inherit root config
785
-
786
- service: api # Override service name
787
-
788
- # Override or add service-specific settings
789
- sync:
790
- required:
791
- prd:
792
- - DATABASE_URL
793
- - REDIS_URL
365
+ encryption:
366
+ kms:
367
+ key_id: arn:aws:kms:us-east-1:123456789:key/abc-123
368
+ # Key never leaves AWS KMS
369
+ # Envelope encryption: KMS encrypts the data key
794
370
  ```
795
371
 
796
- ### Commands
372
+ **How it works:**
373
+ 1. Vaulter generates a data encryption key (DEK)
374
+ 2. DEK encrypts your secrets locally
375
+ 3. AWS KMS encrypts the DEK (envelope encryption)
376
+ 4. Only encrypted DEK + encrypted secrets are stored
377
+ 5. Decryption requires both KMS access AND S3 access
797
378
 
798
- ```bash
799
- # List services
800
- vaulter services
379
+ ### Threat Model
801
380
 
802
- # Sync all services
803
- vaulter sync -e dev --all
804
-
805
- # Sync specific services (glob supported)
806
- vaulter sync -e dev -s api,worker
807
- vaulter sync -e dev -s "svc-*"
381
+ | Threat | Protection |
382
+ |:-------|:-----------|
383
+ | S3 bucket breach | Data encrypted, key required |
384
+ | Key file leaked | Rotate key, re-encrypt |
385
+ | Man-in-middle | TLS + authenticated encryption |
386
+ | Malicious insider | Audit logs via S3 versioning |
387
+ | Accidental git commit | Secrets encrypted in .env |
808
388
 
809
- # Batch export
810
- vaulter export -e prd --all --format=json
811
- ```
812
-
813
- ## MCP Server
814
-
815
- Vaulter includes a full-featured **Model Context Protocol (MCP)** server for AI assistant integration. Works with Claude, ChatGPT, and any MCP-compatible client.
816
-
817
- ### Quick Setup
389
+ ### Security Best Practices
818
390
 
819
391
  ```bash
820
- # Start MCP server
821
- vaulter mcp
822
- ```
823
-
824
- Add to your Claude config (`~/.config/claude/claude_desktop_config.json`):
392
+ # DO
393
+ vaulter key generate # Random 256-bit key
394
+ echo ".vaulter/.key" >> .gitignore # Never commit keys
395
+ export VAULTER_KEY="${{ secrets.KEY }}" # CI/CD secrets
825
396
 
826
- ```json
827
- {
828
- "mcpServers": {
829
- "vaulter": {
830
- "command": "npx",
831
- "args": ["vaulter", "mcp"]
832
- }
833
- }
834
- }
835
- ```
836
-
837
- Or with the binary:
838
-
839
- ```json
840
- {
841
- "mcpServers": {
842
- "vaulter": {
843
- "command": "/usr/local/bin/vaulter",
844
- "args": ["mcp"]
845
- }
846
- }
847
- }
397
+ # ❌ DON'T
398
+ echo "password123" > .vaulter/.key # Weak key
399
+ git add .vaulter/.key # Exposed key
400
+ vaulter set KEY=val --key "hardcoded" # Key in command history
848
401
  ```
849
402
 
850
- ### MCP Tools (14)
851
-
852
- The MCP server exposes 14 tools organized into categories:
853
-
854
- #### Core Tools
855
-
856
- | Tool | Description | Example Use |
857
- |:-----|:------------|:------------|
858
- | `vaulter_get` | Get a single variable | "Get the DATABASE_URL for production" |
859
- | `vaulter_set` | Set a variable with tags | "Set API_KEY to sk-xxx for dev" |
860
- | `vaulter_delete` | Delete a variable | "Remove the old LEGACY_KEY" |
861
- | `vaulter_list` | List all variables | "Show all vars in staging" |
862
- | `vaulter_export` | Export in various formats | "Export prod vars as JSON" |
863
-
864
- #### Sync Tools
865
-
866
- | Tool | Description | Example Use |
867
- |:-----|:------------|:------------|
868
- | `vaulter_sync` | Bidirectional sync | "Sync local .env with dev backend" |
869
- | `vaulter_pull` | Download from backend | "Pull production vars to .env.prd" |
870
- | `vaulter_push` | Upload to backend | "Push .env.local to dev" |
871
-
872
- #### Analysis Tools
873
-
874
- | Tool | Description | Example Use |
875
- |:-----|:------------|:------------|
876
- | `vaulter_compare` | Compare two environments | "What's different between stg and prd?" |
877
- | `vaulter_search` | Search by key pattern | "Find all vars containing DATABASE" |
878
-
879
- #### Monorepo Tools
880
-
881
- | Tool | Description | Example Use |
882
- |:-----|:------------|:------------|
883
- | `vaulter_services` | List discovered services | "What services are in this monorepo?" |
884
-
885
- #### Kubernetes Tools
886
-
887
- | Tool | Description | Example Use |
888
- |:-----|:------------|:------------|
889
- | `vaulter_k8s_secret` | Generate K8s Secret YAML | "Generate a K8s secret for prod" |
890
- | `vaulter_k8s_configmap` | Generate K8s ConfigMap | "Create a ConfigMap for non-secrets" |
891
-
892
- #### Setup Tools
893
-
894
- | Tool | Description | Example Use |
895
- |:-----|:------------|:------------|
896
- | `vaulter_init` | Initialize new project | "Set up vaulter in this project" |
897
-
898
- ### MCP Resources (5)
899
-
900
- Resources provide read-only views of your secrets and configuration:
901
-
902
- | Resource URI | Description | Content |
903
- |:-------------|:------------|:--------|
904
- | `vaulter://config` | Project configuration | YAML from .vaulter/config.yaml |
905
- | `vaulter://services` | Monorepo services | JSON list of discovered services |
906
- | `vaulter://project/env` | Environment variables | .env format for project/env |
907
- | `vaulter://project/env/service` | Service-specific vars | .env format for service |
908
- | `vaulter://compare/env1/env2` | Environment comparison | Diff between two environments |
909
-
910
- **Example resource access:**
911
- - `vaulter://config` → Current config.yaml content
912
- - `vaulter://my-app/prd` → Production vars for my-app
913
- - `vaulter://compare/dev/prd` → What's different between dev and prod
914
-
915
- ### MCP Prompts (5)
916
-
917
- Pre-configured workflow prompts guide AI through complex operations:
918
-
919
- | Prompt | Description | Arguments |
920
- |:-------|:------------|:----------|
921
- | `setup_project` | Initialize a new vaulter project | `project_name`, `mode?`, `backend?` |
922
- | `migrate_dotenv` | Migrate existing .env to vaulter | `file_path`, `environment`, `dry_run?` |
923
- | `deploy_secrets` | Deploy secrets to Kubernetes | `environment`, `namespace?`, `secret_name?` |
924
- | `compare_environments` | Compare two environments | `source_env`, `target_env`, `show_values?` |
925
- | `security_audit` | Audit secrets for security issues | `environment`, `strict?` |
926
-
927
- **Example prompt usage in Claude:**
928
- - "Use the setup_project prompt to create a new project called api-service"
929
- - "Run the migrate_dotenv prompt for .env.local to dev environment"
930
- - "Execute security_audit for production in strict mode"
931
-
932
- ### MCP Capabilities Summary
933
-
934
- | Category | Count | Features |
935
- |:---------|------:|:---------|
936
- | **Tools** | 14 | CRUD, sync, compare, K8s, init |
937
- | **Resources** | 5 | Config, services, vars, comparison |
938
- | **Prompts** | 5 | Setup, migrate, deploy, compare, audit |
939
- | **Formats** | 5 | shell, json, yaml, env, tfvars |
940
-
941
- ### Example AI Conversations
942
-
943
- **Setting up a new project:**
944
- > "Help me set up vaulter for my new api-service project using S3 backend"
945
-
946
- The AI will use `vaulter_init`, guide through backend config, and set up encryption.
947
-
948
- **Migrating from dotenv:**
949
- > "I have a .env.production file with 50 variables. Help me migrate to vaulter"
950
-
951
- The AI will analyze the file, identify secrets vs configs, and sync to backend.
952
-
953
- **Deploying to Kubernetes:**
954
- > "Generate Kubernetes secrets for production and show me how to deploy them"
955
-
956
- The AI will use `vaulter_k8s_secret` and provide kubectl commands.
957
-
958
- **Comparing environments:**
959
- > "What variables are in staging but missing from production?"
960
-
961
- The AI will use `vaulter_compare` and show the differences.
962
-
963
- **Security review:**
964
- > "Audit my production secrets for security issues"
965
-
966
- The AI will analyze variable patterns, check for weak values, and provide recommendations.
967
-
968
- ## CI/CD
969
-
970
- ### Developer Daily Workflow
403
+ ---
971
404
 
972
- A typical day with vaulter:
405
+ ## Daily Use
973
406
 
974
- #### 1. Morning Setup
407
+ ### Workflow Overview
975
408
 
976
409
  ```bash
977
- # Pull latest secrets to your local .env
410
+ # Morning: sync with team's changes
978
411
  vaulter pull -e dev
979
412
 
980
- # Start development with loaded vars
981
- eval $(vaulter export -e dev) npm run dev
413
+ # During development: add new variable
414
+ vaulter set NEW_API_KEY="sk-xxx" -e dev
982
415
 
983
- # Or use the alias (add to ~/.bashrc)
984
- alias vdev='eval $(vaulter export -e dev)'
985
- vdev npm run dev
416
+ # End of day: push changes
417
+ vaulter push -e dev
418
+
419
+ # Deploy: export to production
420
+ vaulter k8s:secret -e prd | kubectl apply -f -
986
421
  ```
987
422
 
988
- #### 2. Adding New Variables
423
+ ### Commands Reference
989
424
 
990
- ```bash
991
- # Add a new secret (encrypted, synced to backend)
992
- vaulter set NEW_API_KEY="sk-xxx" -e dev
425
+ #### Core Commands
993
426
 
994
- # Add a config (plain text)
995
- vaulter set LOG_LEVEL::debug -e dev
427
+ | Command | Description | Example |
428
+ |:--------|:------------|:--------|
429
+ | `init` | Initialize project | `vaulter init` |
430
+ | `get <key>` | Get a variable | `vaulter get DATABASE_URL -e prd` |
431
+ | `set KEY=val` | Set secrets (batch) | `vaulter set A=1 B=2 -e prd` |
432
+ | `set KEY::val` | Set configs (plain) | `vaulter set PORT::3000 -e dev` |
433
+ | `delete <key>` | Delete a variable | `vaulter delete OLD_KEY -e dev` |
434
+ | `list` | List all variables | `vaulter list -e prd` |
435
+ | `list --all-envs` | List across all envs | `vaulter list --all-envs` |
436
+ | `export` | Export for shell | `eval $(vaulter export -e dev)` |
996
437
 
997
- # Batch add multiple vars
998
- vaulter set DB_HOST::localhost DB_PORT::5432 DB_PASSWORD="secret123" -e dev
438
+ #### Sync Commands
999
439
 
1000
- # Check what you have
1001
- vaulter list -e dev
1002
- ```
440
+ | Command | Description | Example |
441
+ |:--------|:------------|:--------|
442
+ | `sync` | Merge local and backend | `vaulter sync -e dev` |
443
+ | `pull` | Download from backend | `vaulter pull -e prd` |
444
+ | `push` | Upload to backend | `vaulter push -e dev` |
1003
445
 
1004
- #### 3. Syncing with Team
446
+ #### Integration Commands
1005
447
 
1006
- ```bash
1007
- # Your teammate added new vars - pull them
1008
- vaulter pull -e dev
448
+ | Command | Description | Example |
449
+ |:--------|:------------|:--------|
450
+ | `k8s:secret` | Kubernetes Secret | `vaulter k8s:secret -e prd` |
451
+ | `k8s:configmap` | Kubernetes ConfigMap | `vaulter k8s:configmap -e prd` |
452
+ | `helm:values` | Helm values.yaml | `vaulter helm:values -e prd` |
453
+ | `tf:vars` | Terraform .tfvars | `vaulter tf:vars -e prd` |
454
+ | `scan` | Scan monorepo | `vaulter scan` |
1009
455
 
1010
- # You made changes - push to backend
1011
- vaulter push -e dev
456
+ ### Set Command Syntax
1012
457
 
1013
- # Two-way sync (recommended)
1014
- vaulter sync -e dev
458
+ ```bash
459
+ # Secrets (encrypted, synced to backend)
460
+ vaulter set KEY=value # Single secret
461
+ vaulter set A=1 B=2 C=3 -e dev # Batch secrets
462
+ vaulter set KEY:=123 # Typed (number/boolean)
1015
463
 
1016
- # Preview before sync
1017
- vaulter sync -e dev --dry-run
464
+ # Configs (plain text in split mode)
465
+ vaulter set PORT::3000 HOST::localhost # Configs
1018
466
  ```
1019
467
 
1020
- #### 4. Testing Different Environments
1021
-
1022
- ```bash
1023
- # Run with staging config
1024
- eval $(vaulter export -e stg) npm test
468
+ | Separator | Type | Backend Sync | Encrypted |
469
+ |:----------|:-----|:-------------|:----------|
470
+ | `=` | Secret | ✓ | ✓ |
471
+ | `:=` | Secret (typed) | ✓ | ✓ |
472
+ | `::` | Config | Split: ✗ / Unified: ✓ | ✓ |
1025
473
 
1026
- # Compare what's different in production
1027
- vaulter compare -e dev -e prd
474
+ ### Global Options
1028
475
 
1029
- # One-liner to check production
1030
- vdev npm run dev # dev
1031
- vstg npm test # stg
1032
- vprd npm run build # prd (be careful!)
476
+ ```
477
+ -p, --project <name> Project name
478
+ -s, --service <name> Service name (monorepos)
479
+ -e, --env <env> Environment name (as defined in config)
480
+ -b, --backend <url> Backend URL override
481
+ -k, --key <path|value> Encryption key
482
+ -f, --file <path> Input file path
483
+ -o, --output <path> Output file path
484
+ -n, --namespace <name> Kubernetes namespace
485
+ --format <fmt> Output format (shell/json/yaml/env/tfvars/docker-args)
486
+ -v, --verbose Verbose output (shows values)
487
+ --dry-run Preview without applying
488
+ --json JSON output
489
+ --force Skip confirmations
490
+ --all Apply to all services in monorepo
1033
491
  ```
1034
492
 
1035
- #### 5. Before Code Review
1036
-
1037
- ```bash
1038
- # Make sure all required vars are documented
1039
- vaulter list -e dev --json | jq 'keys'
493
+ ### Flexible Environment Names
1040
494
 
1041
- # Check nothing sensitive is in wrong place
1042
- vaulter search "*PASSWORD*" -e dev
1043
- vaulter search "*SECRET*" -e dev
1044
- ```
495
+ Vaulter lets you define your own environment names. Use whatever convention fits your workflow:
1045
496
 
1046
- #### 6. Deployment Prep
497
+ ```yaml
498
+ # Short names (default)
499
+ environments: [dev, stg, prd]
1047
500
 
1048
- ```bash
1049
- # Generate K8s secret and review
1050
- vaulter k8s:secret -e prd --dry-run
501
+ # Full names
502
+ environments: [development, staging, production]
1051
503
 
1052
- # Generate and apply
1053
- vaulter k8s:secret -e prd | kubectl apply -f -
504
+ # Custom names
505
+ environments: [local, homolog, qa, uat, prod]
1054
506
 
1055
- # Or export for Helm
1056
- vaulter helm:values -e prd > values.prd.yaml
1057
- helm upgrade myapp ./chart -f values.prd.yaml
507
+ # Brazilian pattern
508
+ environments: [dev, homolog, prd]
1058
509
  ```
1059
510
 
1060
- ### Shell Aliases (Recommended)
1061
-
1062
- Add to `~/.bashrc` or `~/.zshrc`:
511
+ All commands use `-e` with your custom names:
1063
512
 
1064
513
  ```bash
1065
- # Quick environment loading
1066
- alias vdev='eval $(vaulter export -e dev)'
1067
- alias vstg='eval $(vaulter export -e stg)'
1068
- alias vprd='eval $(vaulter export -e prd)'
1069
-
1070
- # Common operations
1071
- alias vpull='vaulter pull -e dev'
1072
- alias vpush='vaulter push -e dev'
1073
- alias vsync='vaulter sync -e dev'
1074
- alias vlist='vaulter list -e dev'
1075
-
1076
- # K8s shortcuts
1077
- alias vk8s='vaulter k8s:secret'
1078
- alias vhelm='vaulter helm:values'
1079
-
1080
- # Usage
1081
- vdev npm run dev # Dev with env vars
1082
- vstg npm test # Test with staging
1083
- vpull && vdev npm run dev # Pull latest, then run
1084
- vk8s -e prd | kubectl apply -f - # Deploy secrets
514
+ vaulter list -e homolog
515
+ vaulter pull -e development
516
+ vaulter k8s:secret -e uat | kubectl apply -f -
1085
517
  ```
1086
518
 
1087
- ### GitHub Actions
519
+ ---
520
+
521
+ ## CI/CD
1088
522
 
1089
- #### Basic Deploy Secrets
523
+ ### GitHub Actions (Quick Start)
1090
524
 
1091
525
  ```yaml
1092
526
  name: Deploy
@@ -1100,7 +534,7 @@ jobs:
1100
534
  steps:
1101
535
  - uses: actions/checkout@v4
1102
536
 
1103
- - name: Deploy secrets to K8s
537
+ - name: Deploy secrets to Kubernetes
1104
538
  env:
1105
539
  VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
1106
540
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
@@ -1109,233 +543,437 @@ jobs:
1109
543
  npx vaulter k8s:secret -e prd | kubectl apply -f -
1110
544
  ```
1111
545
 
1112
- #### Multi-Environment Deploy
546
+ ### GitHub Actions (Complete Example)
1113
547
 
1114
548
  ```yaml
1115
- name: Deploy to Environment
549
+ name: Deploy to Kubernetes
1116
550
  on:
551
+ push:
552
+ branches: [main, develop]
1117
553
  workflow_dispatch:
1118
554
  inputs:
1119
555
  environment:
1120
- description: 'Environment to deploy'
556
+ description: 'Target environment'
1121
557
  required: true
558
+ default: 'dev'
1122
559
  type: choice
1123
560
  options: [dev, stg, prd]
1124
561
 
562
+ env:
563
+ VAULTER_VERSION: '1.0.1'
564
+
1125
565
  jobs:
1126
566
  deploy:
1127
567
  runs-on: ubuntu-latest
1128
- environment: ${{ inputs.environment }}
568
+ environment: ${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'prd') || 'dev' }}
569
+
1129
570
  steps:
1130
571
  - uses: actions/checkout@v4
1131
572
 
1132
- - name: Deploy secrets
573
+ - name: Setup Node.js
574
+ uses: actions/setup-node@v4
575
+ with:
576
+ node-version: '22'
577
+ cache: 'npm'
578
+
579
+ - name: Install Vaulter
580
+ run: npm install -g vaulter@${{ env.VAULTER_VERSION }}
581
+
582
+ - name: Configure kubectl
583
+ uses: azure/k8s-set-context@v4
584
+ with:
585
+ kubeconfig: ${{ secrets.KUBECONFIG }}
586
+
587
+ - name: Deploy Secrets
1133
588
  env:
1134
589
  VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
1135
590
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
1136
591
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
1137
592
  run: |
1138
- npx vaulter k8s:secret -e ${{ inputs.environment }} | kubectl apply -f -
1139
- npx vaulter k8s:configmap -e ${{ inputs.environment }} | kubectl apply -f -
593
+ ENV=${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'prd') || 'dev' }}
594
+
595
+ # Deploy K8s Secret
596
+ vaulter k8s:secret -e $ENV -n my-namespace | kubectl apply -f -
597
+
598
+ # Deploy ConfigMap (non-sensitive config)
599
+ vaulter k8s:configmap -e $ENV -n my-namespace | kubectl apply -f -
600
+
601
+ # Verify deployment
602
+ kubectl get secret,configmap -n my-namespace
603
+
604
+ - name: Restart Deployment
605
+ run: |
606
+ kubectl rollout restart deployment/my-app -n my-namespace
607
+ kubectl rollout status deployment/my-app -n my-namespace --timeout=120s
1140
608
  ```
1141
609
 
1142
- #### Monorepo with Matrix
610
+ ### GitHub Actions (Monorepo with Services)
1143
611
 
1144
612
  ```yaml
1145
- name: Deploy Services
613
+ name: Deploy Service
1146
614
  on:
1147
615
  push:
1148
616
  branches: [main]
617
+ paths:
618
+ - 'apps/svc-*/**'
1149
619
 
1150
620
  jobs:
621
+ detect-changes:
622
+ runs-on: ubuntu-latest
623
+ outputs:
624
+ services: ${{ steps.changes.outputs.services }}
625
+ steps:
626
+ - uses: actions/checkout@v4
627
+ - id: changes
628
+ run: |
629
+ # Detect which services changed
630
+ SERVICES=$(git diff --name-only HEAD~1 | grep '^apps/svc-' | cut -d'/' -f2 | sort -u | jq -R -s -c 'split("\n")[:-1]')
631
+ echo "services=$SERVICES" >> $GITHUB_OUTPUT
632
+
1151
633
  deploy:
634
+ needs: detect-changes
1152
635
  runs-on: ubuntu-latest
1153
636
  strategy:
1154
637
  matrix:
1155
- service: [api, web, worker]
638
+ service: ${{ fromJson(needs.detect-changes.outputs.services) }}
1156
639
  steps:
1157
640
  - uses: actions/checkout@v4
1158
641
 
1159
- - name: Deploy ${{ matrix.service }} secrets
642
+ - name: Deploy ${{ matrix.service }}
1160
643
  env:
1161
644
  VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
1162
645
  run: |
1163
- cd apps/${{ matrix.service }}
1164
- npx vaulter k8s:secret -e prd | kubectl apply -f -
646
+ # Deploy secrets for specific service
647
+ vaulter k8s:secret -e prd -s ${{ matrix.service }} | kubectl apply -f -
1165
648
  ```
1166
649
 
1167
- #### PR Preview Environment
650
+ ### GitHub Actions (Using Binary for Speed)
1168
651
 
1169
652
  ```yaml
1170
- name: PR Preview
1171
- on:
1172
- pull_request:
1173
- types: [opened, synchronize]
653
+ name: Deploy (Fast)
654
+ on: [push]
1174
655
 
1175
656
  jobs:
1176
- preview:
657
+ deploy:
1177
658
  runs-on: ubuntu-latest
1178
659
  steps:
1179
660
  - uses: actions/checkout@v4
1180
661
 
1181
- - name: Create preview secrets
662
+ - name: Download Vaulter Binary
663
+ run: |
664
+ curl -sL https://github.com/forattini-dev/vaulter/releases/latest/download/vaulter-linux -o vaulter
665
+ chmod +x vaulter
666
+ sudo mv vaulter /usr/local/bin/
667
+
668
+ - name: Deploy
1182
669
  env:
1183
670
  VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
1184
671
  run: |
1185
- # Use dev secrets for PR previews
1186
- npx vaulter k8s:secret -e dev -n preview-pr-${{ github.event.number }} | \
1187
- kubectl apply -f -
672
+ vaulter k8s:secret -e prd | kubectl apply -f -
1188
673
  ```
1189
674
 
1190
- #### Validate Secrets Exist
675
+ ### GitHub Actions (Matrix Deploy)
1191
676
 
1192
677
  ```yaml
1193
- name: Validate Secrets
678
+ name: Deploy All Environments
1194
679
  on:
1195
- pull_request:
1196
- paths:
1197
- - '.vaulter/**'
1198
- - 'deploy/**'
680
+ workflow_dispatch:
681
+ inputs:
682
+ environment:
683
+ type: choice
684
+ options: [dev, stg, prd]
1199
685
 
1200
686
  jobs:
1201
- validate:
687
+ deploy:
1202
688
  runs-on: ubuntu-latest
689
+ environment: ${{ inputs.environment }}
1203
690
  steps:
1204
691
  - uses: actions/checkout@v4
1205
692
 
1206
- - name: Check required secrets exist
693
+ - name: Deploy secrets
1207
694
  env:
1208
695
  VAULTER_KEY: ${{ secrets.VAULTER_KEY }}
1209
696
  run: |
1210
- # List and verify required secrets are set
1211
- npx vaulter list -e prd --json | jq -e '.DATABASE_URL and .API_KEY'
697
+ npx vaulter k8s:secret -e ${{ inputs.environment }} | kubectl apply -f -
698
+
699
+ - name: Deploy configmaps
700
+ run: |
701
+ npx vaulter k8s:configmap -e ${{ inputs.environment }} | kubectl apply -f -
1212
702
  ```
1213
703
 
1214
704
  ### GitLab CI
1215
705
 
1216
706
  ```yaml
1217
707
  stages:
1218
- - validate
1219
708
  - deploy
1220
709
 
1221
- variables:
1222
- VAULTER_KEY: $VAULTER_KEY
1223
-
1224
- validate-secrets:
1225
- stage: validate
1226
- script:
1227
- - npx vaulter list -e $CI_ENVIRONMENT_NAME --json | jq -e 'keys | length > 0'
1228
- rules:
1229
- - if: $CI_PIPELINE_SOURCE == "merge_request_event"
1230
-
1231
710
  deploy-secrets:
1232
711
  stage: deploy
712
+ image: node:22-alpine
1233
713
  script:
1234
- - npx vaulter k8s:secret -e prd | kubectl apply -f -
714
+ - npx vaulter k8s:secret -e ${CI_ENVIRONMENT_NAME} | kubectl apply -f -
1235
715
  environment:
1236
- name: production
716
+ name: $CI_COMMIT_REF_NAME
1237
717
  rules:
1238
718
  - if: $CI_COMMIT_BRANCH == "main"
719
+ variables:
720
+ CI_ENVIRONMENT_NAME: prd
721
+ - if: $CI_COMMIT_BRANCH == "develop"
722
+ variables:
723
+ CI_ENVIRONMENT_NAME: dev
1239
724
  ```
1240
725
 
1241
- ### CircleCI
726
+ ### Jenkins Pipeline
1242
727
 
1243
- ```yaml
1244
- version: 2.1
1245
- jobs:
1246
- deploy:
1247
- docker:
1248
- - image: cimg/node:20.0
1249
- steps:
1250
- - checkout
1251
- - run:
1252
- name: Deploy secrets
1253
- command: |
1254
- npx vaulter k8s:secret -e prd | kubectl apply -f -
1255
- environment:
1256
- VAULTER_KEY: ${VAULTER_KEY}
1257
-
1258
- workflows:
1259
- deploy:
1260
- jobs:
1261
- - deploy:
1262
- filters:
1263
- branches:
1264
- only: main
728
+ ```groovy
729
+ pipeline {
730
+ agent any
731
+
732
+ environment {
733
+ VAULTER_KEY = credentials('vaulter-key')
734
+ AWS_ACCESS_KEY_ID = credentials('aws-access-key')
735
+ AWS_SECRET_ACCESS_KEY = credentials('aws-secret-key')
736
+ }
737
+
738
+ stages {
739
+ stage('Deploy Secrets') {
740
+ steps {
741
+ sh 'npx vaulter k8s:secret -e prd | kubectl apply -f -'
742
+ }
743
+ }
744
+ }
745
+ }
746
+ ```
747
+
748
+ ### Docker Integration
749
+
750
+ ```bash
751
+ # Recommended: Use --env-file for production (handles all values safely)
752
+ vaulter export -e prd --format=env > .env.prd
753
+ docker run --env-file .env.prd myapp
754
+
755
+ # For simple values only: command substitution (no spaces/newlines in values)
756
+ docker run $(vaulter export -e prd --format=docker-args) myapp
757
+ ```
758
+
759
+ > **Note**: The `docker-args` format outputs `-e "KEY=VALUE"` flags. Due to shell word-splitting,
760
+ > values containing spaces or special characters won't work correctly with `$(...)` substitution.
761
+ > Use `--env-file` for complex values or production deployments.
762
+
763
+ For `docker build` with build args, use shell format:
764
+
765
+ ```bash
766
+ # Export to shell and use in build
767
+ eval $(vaulter export -e prd)
768
+ docker build \
769
+ --build-arg DATABASE_URL="$DATABASE_URL" \
770
+ --build-arg API_KEY="$API_KEY" \
771
+ -t myapp .
772
+ ```
773
+
774
+ ### Terraform Integration
775
+
776
+ ```bash
777
+ # Generate tfvars
778
+ vaulter tf:vars -e prd > secrets.auto.tfvars
779
+
780
+ # Or inline
781
+ terraform plan -var-file=<(vaulter tf:vars -e prd)
782
+ ```
783
+
784
+ ### Helm Integration
785
+
786
+ ```bash
787
+ # Upgrade with secrets as values
788
+ vaulter helm:values -e prd | helm upgrade myapp ./chart -f -
789
+
790
+ # Or save to file
791
+ vaulter helm:values -e prd > values.secrets.yaml
792
+ helm upgrade myapp ./chart -f values.yaml -f values.secrets.yaml
793
+ ```
794
+
795
+ ### Shell Aliases (Development)
796
+
797
+ ```bash
798
+ # Add to ~/.bashrc or ~/.zshrc
799
+ alias vdev='eval $(vaulter export -e dev)'
800
+ alias vstg='eval $(vaulter export -e stg)'
801
+ alias vprd='eval $(vaulter export -e prd)'
802
+
803
+ # Usage
804
+ vdev npm run dev
805
+ vstg npm run test:integration
1265
806
  ```
1266
807
 
1267
- ### Azure DevOps
808
+ ---
809
+
810
+ ## Configuration
811
+
812
+ ### Basic Config
1268
813
 
1269
814
  ```yaml
1270
- trigger:
1271
- - main
815
+ # .vaulter/config.yaml
816
+ version: "1"
1272
817
 
1273
- pool:
1274
- vmImage: 'ubuntu-latest'
818
+ project: my-project
819
+ service: api # optional, for monorepos
1275
820
 
1276
- steps:
1277
- - task: NodeTool@0
1278
- inputs:
1279
- versionSpec: '20.x'
1280
-
1281
- - script: |
1282
- npx vaulter k8s:secret -e prd | kubectl apply -f -
1283
- displayName: 'Deploy secrets'
1284
- env:
1285
- VAULTER_KEY: $(VAULTER_KEY)
1286
- AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)
1287
- AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
821
+ backend:
822
+ url: s3://bucket/envs?region=us-east-1
823
+ # Or multiple with fallback
824
+ urls:
825
+ - s3://bucket/envs?region=us-east-1
826
+ - file:///home/user/.vaulter-store
827
+
828
+ encryption:
829
+ key_source:
830
+ - env: VAULTER_KEY
831
+ - file: .vaulter/.key
832
+
833
+ environments:
834
+ - dev
835
+ - stg
836
+ - prd
837
+
838
+ default_environment: dev
839
+ ```
840
+
841
+ ### Directory Modes
842
+
843
+ #### Unified Mode (Default)
844
+
845
+ ```
846
+ my-project/
847
+ ├── .vaulter/
848
+ │ ├── config.yaml
849
+ │ └── environments/
850
+ │ ├── dev.env
851
+ │ ├── stg.env
852
+ │ └── prd.env
853
+ ```
854
+
855
+ #### Split Mode
856
+
857
+ Separates configs (committable) from secrets (gitignored):
858
+
859
+ ```
860
+ my-project/
861
+ ├── .vaulter/config.yaml
862
+ └── deploy/
863
+ ├── configs/ # ✅ Committable (PORT, HOST, LOG_LEVEL)
864
+ │ ├── dev.env
865
+ │ └── prd.env
866
+ └── secrets/ # ❌ Gitignored (DATABASE_URL, API_KEY)
867
+ ├── dev.env
868
+ └── prd.env
869
+ ```
870
+
871
+ ```yaml
872
+ directories:
873
+ mode: split
874
+ configs: deploy/configs
875
+ secrets: deploy/secrets
1288
876
  ```
1289
877
 
1290
- ### CI/CD Best Practices
878
+ Initialize with: `vaulter init --split`
879
+
880
+ ### Backend URLs
881
+
882
+ | Provider | URL Format |
883
+ |:---------|:-----------|
884
+ | AWS S3 | `s3://bucket/path?region=us-east-1` |
885
+ | AWS S3 + Profile | `s3://bucket/path?profile=myprofile` |
886
+ | MinIO | `http://KEY:SECRET@localhost:9000/bucket` |
887
+ | Cloudflare R2 | `https://KEY:SECRET@ACCOUNT.r2.cloudflarestorage.com/bucket` |
888
+ | DigitalOcean Spaces | `https://KEY:SECRET@nyc3.digitaloceanspaces.com/bucket` |
889
+ | Backblaze B2 | `https://KEY:SECRET@s3.us-west-002.backblazeb2.com/bucket` |
890
+ | FileSystem | `file:///path/to/storage` |
891
+ | Memory | `memory://bucket-name` |
892
+
893
+ ---
894
+
895
+ ## Integrations
896
+
897
+ ### Kubernetes
1291
898
 
1292
- | Practice | Recommendation |
1293
- |:---------|:---------------|
1294
- | **Store VAULTER_KEY securely** | Use CI provider's secret management |
1295
- | **Use IAM roles when possible** | Prefer roles over hardcoded credentials |
1296
- | **Different keys per environment** | Don't share prd key with dev |
1297
- | **Validate before deploy** | Run `--dry-run` first in pipelines |
1298
- | **Use environment protection** | Require approval for prd deploys |
1299
- | **Cache vaulter binary** | Download once per pipeline, not per job |
899
+ ```bash
900
+ # Deploy Secret
901
+ vaulter k8s:secret -e prd -n my-namespace | kubectl apply -f -
902
+
903
+ # Deploy ConfigMap
904
+ vaulter k8s:configmap -e prd | kubectl apply -f -
905
+ ```
1300
906
 
1301
- ### Caching Vaulter Binary
907
+ Note: Custom secret/configmap names are configured in `.vaulter/config.yaml`:
1302
908
 
1303
909
  ```yaml
1304
- # GitHub Actions
1305
- - uses: actions/cache@v3
1306
- with:
1307
- path: ~/.npm
1308
- key: vaulter-${{ runner.os }}
1309
-
1310
- # Or use the installer script
1311
- - name: Install vaulter
1312
- run: |
1313
- curl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh
1314
- echo "$HOME/.local/bin" >> $GITHUB_PATH
910
+ integrations:
911
+ kubernetes:
912
+ secret_name: my-app-secrets
913
+ configmap_name: my-app-config
914
+ ```
915
+
916
+ ### Helm
917
+
918
+ ```bash
919
+ # Pass as values
920
+ vaulter helm:values -e prd | helm upgrade myapp ./chart -f -
921
+
922
+ # Save to file
923
+ vaulter helm:values -e prd > values.secrets.yaml
924
+ ```
925
+
926
+ ### Terraform
927
+
928
+ ```bash
929
+ # Generate tfvars
930
+ vaulter tf:vars -e prd > terraform.tfvars
931
+
932
+ # Generate JSON
933
+ vaulter tf:json -e prd > terraform.tfvars.json
934
+ ```
935
+
936
+ ---
937
+
938
+ ## Monorepo Support
939
+
940
+ Vaulter auto-detects all major monorepo tools:
941
+
942
+ | Tool | Detection File | Workspace Config |
943
+ |:-----|:---------------|:-----------------|
944
+ | NX | `nx.json` | `workspaceLayout` |
945
+ | Turborepo | `turbo.json` | Uses pnpm/yarn workspaces |
946
+ | Lerna | `lerna.json` | `packages` array |
947
+ | pnpm | `pnpm-workspace.yaml` | `packages` array |
948
+ | Yarn | `package.json` | `workspaces` field |
949
+ | Rush | `rush.json` | `projects[].projectFolder` |
950
+
951
+ ### Scan Command
952
+
953
+ ```bash
954
+ # Discover all packages
955
+ vaulter scan
956
+
957
+ # Output:
958
+ # Monorepo: NX
959
+ # Found 17 package(s):
960
+ # ✓ Initialized: 3
961
+ # ○ Not initialized: 14
962
+ # 📄 With .env files: 11
1315
963
  ```
1316
964
 
1317
- ## Security Best Practices
1318
-
1319
- | Practice | How |
1320
- |:---------|:----|
1321
- | Never commit credentials | Use `config.local.yaml` or env vars |
1322
- | Never commit encryption keys | Add `.vaulter/.key` to `.gitignore` |
1323
- | Use env var expansion | `${AWS_ACCESS_KEY_ID}` instead of hardcoding |
1324
- | Use AWS credential chain | No credentials in URL, use IAM roles |
1325
- | Separate keys per environment | Different keys for dev/stg/prd |
1326
- | Restrict S3 bucket access | IAM policies to limit readers |
1327
-
1328
- ### Files to .gitignore
1329
-
1330
- ```gitignore
1331
- .vaulter/.key
1332
- .vaulter/config.local.yaml
1333
- **/config.local.yaml
1334
- deploy/secrets/
1335
- .env
1336
- .env.*
965
+ ### Batch Operations
966
+
967
+ ```bash
968
+ # Sync all services
969
+ vaulter sync -e dev --all
970
+
971
+ # Sync specific services
972
+ vaulter sync -e dev -s api,worker
1337
973
  ```
1338
974
 
975
+ ---
976
+
1339
977
  ## API Usage
1340
978
 
1341
979
  ```typescript
@@ -1346,93 +984,114 @@ const client = new VaulterClient({ config })
1346
984
 
1347
985
  await client.connect()
1348
986
 
1349
- // Get
987
+ // CRUD operations
1350
988
  const value = await client.get('DATABASE_URL', 'my-project', 'prd')
989
+ await client.set({ key: 'API_KEY', value: 'sk-xxx', project: 'my-project', environment: 'prd' })
990
+ const vars = await client.list({ project: 'my-project', environment: 'prd' })
1351
991
 
1352
- // Set
1353
- await client.set({
1354
- key: 'API_KEY',
1355
- value: 'sk-secret',
1356
- project: 'my-project',
1357
- environment: 'prd'
1358
- })
992
+ await client.disconnect()
993
+ ```
1359
994
 
1360
- // List
1361
- const vars = await client.list({
1362
- project: 'my-project',
1363
- environment: 'prd'
1364
- })
995
+ ### Dotenv Compatible
1365
996
 
1366
- // Export
1367
- const envVars = await client.export('my-project', 'prd')
997
+ ```typescript
998
+ // Auto-load .env into process.env
999
+ import 'vaulter/load'
1368
1000
 
1369
- await client.disconnect()
1001
+ // Or with options
1002
+ import { loader } from 'vaulter'
1003
+ loader({ path: '.env.local', override: true })
1370
1004
  ```
1371
1005
 
1372
- ## Comparison
1373
-
1374
- | Feature | vaulter | dotenv | doppler | vault |
1375
- |:--------|:-------:|:------:|:-------:|:-----:|
1376
- | Multi-backend | ✅ | ❌ | ❌ | ❌ |
1377
- | Encryption | AES-256-GCM | ❌ | ✅ | ✅ |
1378
- | K8s integration | Native | ❌ | Plugin | Plugin |
1379
- | Self-hosted | ✅ | N/A | ❌ | ✅ |
1380
- | Monorepo | Native | ❌ | Limited | ❌ |
1381
- | MCP/AI | ✅ | ❌ | ❌ | ❌ |
1382
- | Complexity | Low | Low | Medium | High |
1383
-
1384
- ## Numbers
1385
-
1386
- | Metric | Value |
1387
- |:-------|:------|
1388
- | Backends | 7 (S3, MinIO, R2, Spaces, B2, FileSystem, Memory) |
1389
- | Environments | 5 (dev, stg, prd, sbx, dr) |
1390
- | Export Formats | 5 (shell, json, yaml, env, tfvars) |
1391
- | MCP Tools | 14 (core, sync, analysis, monorepo, k8s, setup) |
1392
- | MCP Resources | 5 (config, services, vars, service vars, compare) |
1393
- | MCP Prompts | 5 (setup, migrate, deploy, compare, audit) |
1394
- | Integrations | 5 (K8s Secret, K8s ConfigMap, Helm, Terraform, tfvars) |
1006
+ ---
1395
1007
 
1396
- ## Pre-built Binaries
1008
+ ## MCP Server
1397
1009
 
1398
- ### Automatic Installation
1010
+ Vaulter includes a **Model Context Protocol (MCP)** server for AI assistant integration.
1011
+
1012
+ ### Setup
1399
1013
 
1400
1014
  ```bash
1401
- # Installs to ~/.local/bin by default
1402
- curl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh
1403
- ```
1015
+ # Start server
1016
+ vaulter mcp
1404
1017
 
1405
- The installer auto-detects your OS and architecture.
1018
+ # Test with MCP Inspector
1019
+ npx @anthropic-ai/mcp-inspector vaulter mcp
1020
+ ```
1406
1021
 
1407
- ### Manual Download
1022
+ ### Claude Desktop Config
1408
1023
 
1409
- Download from [Releases](https://github.com/forattini-dev/vaulter/releases):
1024
+ ```json
1025
+ {
1026
+ "mcpServers": {
1027
+ "vaulter": {
1028
+ "command": "vaulter",
1029
+ "args": ["mcp"]
1030
+ }
1031
+ }
1032
+ }
1033
+ ```
1410
1034
 
1411
- | Platform | Binary | Install |
1412
- |:---------|:-------|:--------|
1413
- | Linux x64 | `vaulter-linux-x64` | `chmod +x vaulter-linux-x64 && mv vaulter-linux-x64 ~/.local/bin/vaulter` |
1414
- | Linux ARM64 | `vaulter-linux-arm64` | `chmod +x vaulter-linux-arm64 && mv vaulter-linux-arm64 ~/.local/bin/vaulter` |
1415
- | macOS x64 | `vaulter-macos-x64` | `chmod +x vaulter-macos-x64 && mv vaulter-macos-x64 /usr/local/bin/vaulter` |
1416
- | macOS ARM64 | `vaulter-macos-arm64` | `chmod +x vaulter-macos-arm64 && mv vaulter-macos-arm64 /usr/local/bin/vaulter` |
1417
- | Windows x64 | `vaulter-win-x64.exe` | Add to PATH |
1035
+ ### Available Tools (19)
1036
+
1037
+ | Tool | Description |
1038
+ |:-----|:------------|
1039
+ | `vaulter_get` | Get a variable |
1040
+ | `vaulter_set` | Set a variable |
1041
+ | `vaulter_delete` | Delete a variable |
1042
+ | `vaulter_list` | List variables |
1043
+ | `vaulter_export` | Export in various formats |
1044
+ | `vaulter_sync` | Bidirectional sync |
1045
+ | `vaulter_pull` | Download from backend |
1046
+ | `vaulter_push` | Upload to backend |
1047
+ | `vaulter_compare` | Compare environments |
1048
+ | `vaulter_search` | Search by pattern |
1049
+ | `vaulter_scan` | Scan monorepo |
1050
+ | `vaulter_services` | List services |
1051
+ | `vaulter_k8s_secret` | Generate K8s Secret |
1052
+ | `vaulter_k8s_configmap` | Generate K8s ConfigMap |
1053
+ | `vaulter_init` | Initialize project |
1054
+ | `vaulter_key_generate` | Generate encryption key (symmetric or asymmetric) |
1055
+ | `vaulter_key_list` | List all keys (project + global) |
1056
+ | `vaulter_key_show` | Show key details |
1057
+ | `vaulter_key_export` | Export key to encrypted bundle |
1058
+ | `vaulter_key_import` | Import key from encrypted bundle |
1059
+
1060
+ ### Resources (7)
1061
+
1062
+ - `vaulter://config` — Project configuration
1063
+ - `vaulter://services` — Monorepo services
1064
+ - `vaulter://keys` — List all encryption keys (project + global)
1065
+ - `vaulter://keys/<name>` — Specific key details
1066
+ - `vaulter://keys/global/<name>` — Global key details
1067
+ - `vaulter://project/env` — Environment variables
1068
+ - `vaulter://project/env/service` — Service-specific vars
1069
+ - `vaulter://compare/env1/env2` — Environment diff
1070
+
1071
+ ### Prompts (5)
1072
+
1073
+ - `setup_project` — Initialize a new project
1074
+ - `migrate_dotenv` — Migrate existing .env
1075
+ - `deploy_secrets` — Deploy to Kubernetes
1076
+ - `compare_environments` — Compare two environments
1077
+ - `security_audit` — Audit for security issues
1418
1078
 
1419
- ### CI/CD Installation
1079
+ ---
1420
1080
 
1421
- ```bash
1422
- # GitHub Actions / GitLab CI / CircleCI
1423
- curl -fsSL https://raw.githubusercontent.com/forattini-dev/vaulter/main/install.sh | sh
1424
- export PATH="$HOME/.local/bin:$PATH"
1425
- vaulter --version
1426
- ```
1081
+ ## Pre-built Binaries
1427
1082
 
1428
- ## License
1083
+ Download from [Releases](https://github.com/forattini-dev/vaulter/releases):
1429
1084
 
1430
- MIT © [Forattini](https://github.com/forattini-dev)
1085
+ | Platform | Binary |
1086
+ |:---------|:-------|
1087
+ | Linux x64 | `vaulter-linux-x64` |
1088
+ | Linux ARM64 | `vaulter-linux-arm64` |
1089
+ | macOS x64 | `vaulter-macos-x64` |
1090
+ | macOS ARM64 | `vaulter-macos-arm64` |
1091
+ | Windows x64 | `vaulter-win-x64.exe` |
1431
1092
 
1432
1093
  ---
1433
1094
 
1434
- <div align="center">
1435
-
1436
- **[Documentation](#configuration)** · **[Issues](https://github.com/forattini-dev/vaulter/issues)** · **[Releases](https://github.com/forattini-dev/vaulter/releases)**
1095
+ ## License
1437
1096
 
1438
- </div>
1097
+ MIT © [Forattini](https://github.com/forattini-dev)