Documentation Index Fetch the complete documentation index at: https://mintlify.com/twpayne/chezmoi/llms.txt
Use this file to discover all available pages before exploring further.
chezmoi includes support for HashiCorp Vault using the Vault CLI to expose data as template functions.
Setup
Install Vault CLI
Set the required environment variables:
export VAULT_ADDR = 'https://vault.example.com:8200'
export VAULT_TOKEN = 'your-vault-token'
Or add to your shell profile:
export VAULT_ADDR = 'https://vault.example.com:8200'
export VAULT_TOKEN = 'your-vault-token'
Verify Setup
Test that Vault is configured correctly:
vault kv get -format=json secret/test
Template Function
vault
Get structured data from Vault:
{{ (vault "secret/data/myapp").data.data.password }}
This runs vault kv get -format=json secret/data/myapp and returns parsed JSON.
For KV v2 (default), secrets are stored under secret/data/path. The response structure is {"data": {"data": {"key": "value"}}}.
Usage Examples
Simple Secrets (KV v2)
Store in Vault
Use in Templates
vault kv put secret/github token=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
vault kv put secret/aws access_key_id=AKIAIOSFODNN7EXAMPLE secret_access_key=wJalrXUtnFEMI/K7MDENG
Database Credentials
Store in Vault
Use in Template
vault kv put secret/database/production \
host=db.example.com \
port= 5432 \
username=app_user \
password=super_secret_password \
database=production_db
Git Configuration
vault kv put secret/git \
name="John Doe" \
email="john@example.com" \
signing_key="0x1234567890ABCDEF"
[user]
name = {{ (vault "secret/data/git").data.data.name }}
email = {{ (vault "secret/data/git").data.data.email }}
signingkey = {{ (vault "secret/data/git").data.data.signing_key }}
AWS Credentials
vault kv put secret/aws/personal \
access_key_id=AKIAIOSFODNN7EXAMPLE \
secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
region=us-east-1
vault kv put secret/aws/work \
access_key_id=AKIAI44QH8DHBEXAMPLE \
secret_access_key=je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY \
region=us-west-2
[personal]
aws_access_key_id = {{ (vault "secret/data/aws/personal").data.data.access_key_id }}
aws_secret_access_key = {{ (vault "secret/data/aws/personal").data.data.secret_access_key }}
region = {{ (vault "secret/data/aws/personal").data.data.region }}
[work]
aws_access_key_id = {{ (vault "secret/data/aws/work").data.data.access_key_id }}
aws_secret_access_key = {{ (vault "secret/data/aws/work").data.data.secret_access_key }}
region = {{ (vault "secret/data/aws/work").data.data.region }}
Multiple API Keys
vault kv put secret/api-keys \
github=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
gitlab=glpat-xxxxxxxxxxxxxxxxxxxx \
openai=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
stripe=sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
~/.config/api-keys.env.tmpl
GITHUB_TOKEN={{ (vault "secret/data/api-keys").data.data.github }}
GITLAB_TOKEN={{ (vault "secret/data/api-keys").data.data.gitlab }}
OPENAI_API_KEY={{ (vault "secret/data/api-keys").data.data.openai }}
STRIPE_SECRET_KEY={{ (vault "secret/data/api-keys").data.data.stripe }}
SSH Configuration
vault kv put secret/ssh/github user=git
vault kv put secret/ssh/gitlab user=git
vault kv put secret/ssh/work-server user=john.doe host=server.company.com
Host github.com
User {{ (vault "secret/data/ssh/github").data.data.user }}
IdentityFile ~/.ssh/id_ed25519
Host gitlab.com
User {{ (vault "secret/data/ssh/gitlab").data.data.user }}
IdentityFile ~/.ssh/id_rsa
Host work-server
HostName {{ (vault "secret/data/ssh/work-server").data.data.host }}
User {{ (vault "secret/data/ssh/work-server").data.data.user }}
IdentityFile ~/.ssh/work_id_rsa
NPM Configuration
vault kv put secret/npm token=npm_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx email=user@example.com
//registry.npmjs.org/:_authToken={{ (vault "secret/data/npm").data.data.token }}
email={{ (vault "secret/data/npm").data.data.email }}
Vault KV Versions
KV v2 (Default)
KV v2 includes versioning and metadata:
# Write
vault kv put secret/myapp password=secret123
# Read in template
{{ (vault "secret/data/myapp").data.data.password }}
Note the data in the path and nested structure.
KV v1
KV v1 is simpler without versioning:
# Write
vault kv put secret/myapp password=secret123
# Read in template (if using KV v1)
{{ (vault "secret/myapp").data.password }}
Configuration
Custom Command
If vault is not in your PATH:
~/.config/chezmoi/chezmoi.toml
[ vault ]
command = "/custom/path/to/vault"
Environment Variables
Vault CLI respects these environment variables:
export VAULT_ADDR = 'https://vault.example.com:8200'
export VAULT_TOKEN = 'your-vault-token'
export VAULT_NAMESPACE = 'my-namespace' # For Vault Enterprise
export VAULT_SKIP_VERIFY = 'true' # Skip TLS verification (not recommended)
Advanced Usage
Using Vault Namespaces (Enterprise)
export VAULT_NAMESPACE = 'my-namespace'
{{ (vault "secret/data/myapp").data.data.password }}
Dynamic Database Credentials
Vault can generate dynamic database credentials:
# Enable database secrets engine
vault secrets enable database
# Configure
vault write database/config/postgresql \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@localhost:5432/postgres"
# Create role
vault write database/roles/readonly \
db_name=postgresql \
creation_statements="CREATE ROLE \" {{name}} \" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';" \
default_ttl="1h" \
max_ttl="24h"
# Read dynamic credentials
{{ $dbCreds := vault "database/creds/readonly" }}
username: {{ $dbCreds.data.username }}
password: {{ $dbCreds.data.password }}
Vault Auth Methods
Token Auth
AppRole Auth
Kubernetes Auth
export VAULT_TOKEN = 'your-vault-token'
Simplified Access with Variables
~/.config/app/config.yml.tmpl
{{- $db := (vault "secret/data/database").data.data -}}
{{- $api := (vault "secret/data/api-keys").data.data -}}
database:
host: {{ $db.host }}
port: {{ $db.port }}
username: {{ $db.username }}
password: {{ $db.password }}
api_keys:
github: {{ $api.github }}
gitlab: {{ $api.gitlab }}
openai: {{ $api.openai }}
Complete Examples
Multi-Service Configuration
~/.config/services.yml.tmpl
{{- $github := (vault "secret/data/github").data.data -}}
{{- $aws := (vault "secret/data/aws").data.data -}}
{{- $db := (vault "secret/data/database/production").data.data -}}
github:
token: {{ $github.token }}
username: {{ $github.username }}
aws:
access_key_id: {{ $aws.access_key_id }}
secret_access_key: {{ $aws.secret_access_key }}
region: {{ $aws.region }}
database:
host: {{ $db.host }}
port: {{ $db.port }}
username: {{ $db.username }}
password: {{ $db.password }}
database: {{ $db.database }}
Troubleshooting
Connection Refused
Ensure VAULT_ADDR is set correctly:
echo $VAULT_ADDR
vault status
Permission Denied
Verify your token has the required policies:
vault token lookup
vault policy read my-policy
Secret Not Found
List secrets to verify the path:
vault kv list secret/
vault kv get secret/data/myapp
TLS Certificate Errors
For development, you can skip TLS verification (not recommended for production):
export VAULT_SKIP_VERIFY = true
Testing Templates
Test template functions:
chezmoi execute-template '{{ (vault "secret/data/test").data.data.value }}'
Verify Vault CLI
which vault
vault --version
vault status
Best Practices
Use least privilege : Grant minimal required permissions via policies
Rotate tokens : Use short-lived tokens and rotate regularly
Use namespaces : Organize secrets with namespaces (Enterprise)
Enable audit logging : Track all secret access
Use dynamic secrets : Leverage Vault’s dynamic secret generation
Secure communication : Always use TLS in production
Use auth methods : Prefer AppRole or Kubernetes auth over tokens
Organize paths : Use a clear hierarchy for secret paths
Version secrets : Use KV v2 for secret versioning
Monitor access : Set up alerts for suspicious access patterns
See Also