Your single stop for using the vlt CLI to work with HashiCorp Vault. This guide consolidates the previous authentication, completion, file handling, JSON, and dependency docs into one place.
- Install and configure Vault (
kvv2 andtransitengines enabled) and make sureVAULT_ADDRplus your auth credentials are available in the environment. - Install
vlt(e.g.,go install ./cmd/clior download a release) and confirm the binary is on your PATH. - Export a few common variables before you start:
export VAULT_ADDR="https://vault.example.com:8200" export VAULT_TOKEN="hvs.xxxxxxxxxxxxx" # or other supported auth inputs
- Use
vlt putto write secrets,vlt getto read them back,vlt syncto materialise .env files, andvlt jsonto produce JSON payloads.
vlt auto-detects Vault authentication based on the credentials you provide, checking in this order:
- Token –
VAULT_TOKEN - AppRole –
VAULT_ROLE_ID+VAULT_SECRET_ID - GitHub –
VAULT_GITHUB_TOKEN - Kubernetes –
VAULT_K8S_ROLE
Override detection with VAULT_AUTH_METHOD (token, approle, github, kubernetes). Examples:
# AppRole
export VAULT_ROLE_ID="00275ac3-734f-49fc-0f46-5e9a76fbf304"
export VAULT_SECRET_ID="282cb405-42e9-c709-bd9f-030998e3f8e8"
vlt get --path secrets/app
# GitHub
export VAULT_GITHUB_TOKEN="ghp_xxxxxxxxxxxxx"
vlt get --path secrets/app
# Kubernetes
export VAULT_K8S_ROLE="my-app-role"
vlt get --path secrets/appReference Vault setup commands:
# Enable auth methods
vault auth enable approle
vault auth enable github
vault auth enable kubernetes
# Retrieve ids / configure mappings
vault read auth/approle/role/vlt-app/role-id
vault write -f auth/approle/role/vlt-app/secret-id
vault write auth/github/config organization=myorg
vault write auth/kubernetes/role/vlt-app \
bound_service_account_names=vlt \
bound_service_account_namespaces=default \
policies=vlt-policy \
ttl=24hYou can also provide most values via CLI flags (e.g., vlt --vault-addr ... get --path ...).
- Store values:
vlt put --path myapp/config --env-file production.envorvlt put --path myapp/ssh --from-file ~/.ssh/id_rsa. - Retrieve values:
vlt get --path myapp/config --jsonorvlt get --path myapp/kv --key cert.pem. - Copy values:
vlt copy --from myapp/config --to backups/myapp/configorvlt copy --from myapp --to backups/myapp --recursive. - Generate .env:
vlt sync --config .vlt.yaml --output .env.
Transit encryption follows TRANSIT/ENCRYPTION_KEY/TRANSIT_MOUNT rules: set TRANSIT=true to force encryption (defaults key to app-secrets and mount to transit).
vlt copy can write to another Vault instance by supplying destination-specific flags or env vars:
vlt copy \
--from myapp \
--to backups/myapp \
--recursive \
--kv-mount source \
--dest-kv-mount dr-secrets \
--dest-vault-addr https://vault-dr.example.com:8200 \
--dest-vault-token hvs.dr-tokenEquivalent destination env vars are available: DEST_VAULT_ADDR, DEST_VAULT_TOKEN, DEST_VAULT_NAMESPACE, DEST_VAULT_AUTH_METHOD, DEST_VAULT_ROLE_ID, DEST_VAULT_SECRET_ID, DEST_VAULT_GITHUB_TOKEN, DEST_VAULT_K8S_ROLE, and DEST_KV_MOUNT.
Behavior notes:
- Missing destination mounts are created automatically as KV v2.
- Recursive copy preserves relative paths under the destination root.
- Values are copied raw; encrypted ciphertext is not decrypted or re-encrypted.
- Without
--force, copy stops at the first destination conflict. Recursive copy is not transactional, so earlier writes are not rolled back.
vlt get supports saving Vault keys to disk when told to do so either by config or metadata.
files:
output_dir: "./secrets" # defaults to current directory
default_mode: "0600" # defaults to "0600"
create_dirs: true # defaults to truesecrets:
- path: myapp/config # regular env vars
- path: myapp/ssh
key: private.pem
file:
path: "~/ssh/wp.pem"
mode: "0600"
create_dir: true
- path: ssl/certificates
key: server.crt
file: {} # inherits global defaultsWhen a matching config exists, vlt get --config ... or vlt get --path ... --key ... writes the key to the configured location, creating directories if allowed. Without config, metadata created by vlt put --from-file keeps compatibility by saving in the current directory.
- Relative paths resolve against
files.output_dir. - Use restrictive modes (
0600,0400) for sensitive material. - Created directories default to
0700when enabled. - The command prints where files land, e.g.
File saved: ./secrets/server.crt (mode: 0600).
vlt json [FILE] converts a .env file to JSON. Encryption is controlled by TRANSIT and optional overrides:
# Plaintext JSON from default .env
vlt json
# Plaintext from specific file
vlt json example.env
# Encrypted JSON using defaults (key "app-secrets", mount "transit")
TRANSIT=true vlt json
# Custom key / mount
TRANSIT=true ENCRYPTION_KEY=mykey TRANSIT_MOUNT=custom-transit vlt json example.env
# Force plaintext even when key is present
TRANSIT=false ENCRYPTION_KEY=mykey vlt jsonUse cases: feeding configuration systems, CI/CD pipelines, or generating encrypted payloads for backup.
Generate shell completion scripts with vlt completion <shell>:
# Fish
vlt completion fish > ~/.config/fish/completions/vlt.fish
source ~/.config/fish/completions/vlt.fish
# Bash
mkdir -p ~/.bash_completion.d
vlt completion bash > ~/.bash_completion.d/vlt
echo 'source ~/.bash_completion.d/vlt' >> ~/.bashrc
# Zsh
mkdir -p ~/.zsh/completions
vlt completion zsh > ~/.zsh/completions/_vlt
echo 'fpath=(~/.zsh/completions $fpath)' >> ~/.zshrc
echo 'autoload -U compinit && compinit' >> ~/.zshrc
# PowerShell
vlt completion powershell > vlt-completion.ps1
Add-Content $PROFILE ". path/to/vlt-completion.ps1"Troubleshooting tips:
- Fish: verify
~/.config/fish/completions/vlt.fish, reload withsource. - Bash: ensure
bash-completionis installed; checkcomplete -p vlt. - Zsh: rebuild cache via
rm -f ~/.zcompdump; compinit. - PowerShell: confirm execution policy allows scripts and
$PROFILEreferences the script.
go.mod pins the following key dependencies (Go 1.25.0):
github.com/hashicorp/vault/apiv1.22.0github.com/urfave/cli/v2v2.27.7github.com/joho/godotenvv1.5.1
The Vault API depends on a forked HCL version (v1.0.1-vault-7). To avoid conflicts:
# Update non-Vault dependencies first
go get -u github.com/urfave/cli/v2 github.com/joho/godotenv
# Then update the Vault API allowing it to pick compatible transitive deps
go get -u github.com/hashicorp/vault/api@latest
go mod tidyValidate with:
make build
make test
./vlt --versionKeep an eye on security advisories, and log the Go toolchain version used for releases.
- If
go testfails due to module proxy access, setGOPROXY=director populate a local module cache. - Run
TRANSIT=truewhenever you want encryption by default; useTRANSIT=falseto force plaintext. - Metadata is preserved when using
vlt put --from-file, so older secrets continue to download as files even without explicit config.
Need something that is not covered here? Open an issue or check README.md for architectural details.