HashiCorp Vault β KV Version 1
KV (Key-Value) version 1 is the simplest secrets engine. It stores arbitrary key-value pairs without versioning β each write replaces the previous value entirely.
Enable KV v1
# Enable KV v1 at a custom path
vault secrets enable -path=kv-v1 -version=1 kv
# Verify
vault secrets list
Expected output:
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_abc123 per-token private secret storage
identity/ identity identity_abc123 identity store
kv-v1/ kv kv_def456 n/a
secret/ kv kv_ghi789 key/value secret storage
sys/ system system_jkl012 system endpoints
Write and Read Secrets
Write a Secret
# Write key-value pairs
vault kv put kv-v1/myapp username="admin" password="s3cur3!"
Expected output:
Success! Data written to: kv-v1/myapp
Read a Secret
vault kv get kv-v1/myapp
Expected output:
====== Data ======
Key Value
--- -----
password s3cur3!
username admin
Read a Single Field
vault kv get -field=password kv-v1/myapp
Expected output:
s3cur3!
KV v1 API Paths
KV v1 uses a flat API path β the path you write to is the exact API path:
# CLI
vault kv put kv-v1/myapp key=value
# Equivalent API call
curl --header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"username": "admin", "password": "s3cur3!"}' \
"$VAULT_ADDR/v1/kv-v1/myapp"
# Read via API
curl --header "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/kv-v1/myapp" | jq
API response:
{
"request_id": "abc123",
"data": {
"username": "admin",
"password": "s3cur3!"
}
}
π‘ Note: KV v1 API paths are simpler than KV v2. Thereβs no
/data/or/metadata/prefix.
Overwrite Behavior
KV v1 replaces the entire secret on every write. Thereβs no versioning:
# Initial write
vault kv put kv-v1/myapp username="admin" password="old-pass" env="prod"
# Overwrite β the entire secret is replaced
vault kv put kv-v1/myapp password="new-pass"
# Read β username and env are GONE
vault kv get kv-v1/myapp
Expected output:
====== Data ======
Key Value
--- -----
password new-pass
β οΈ Warning: The previous
usernameandenvfields are permanently lost. KV v1 has no undo.
List Secrets
# Create multiple secrets
vault kv put kv-v1/app/dev db_host="dev-db.local"
vault kv put kv-v1/app/staging db_host="staging-db.local"
vault kv put kv-v1/app/prod db_host="prod-db.local"
# List secrets at a path
vault kv list kv-v1/app/
Expected output:
Keys
----
dev
prod
staging
Delete Secrets
Deleting in KV v1 is permanent β thereβs no soft-delete or undelete:
# Delete a secret
vault kv delete kv-v1/app/dev
# Try to read it
vault kv get kv-v1/app/dev
# No value found at kv-v1/app/dev
When to Use KV v1
| Use Case | KV v1 | KV v2 |
|---|---|---|
| Simple secret storage | β | β |
| Need version history | β | β |
| Need soft-delete/undelete | β | β |
| Need custom metadata | β | β |
| Lower storage overhead | β | β |
| Simpler API paths | β | β |
Rule of thumb: Use KV v2 unless you have a specific reason to use v1 (storage constraints, simpler API integration).
Quick Reference
| Command | Description |
|---|---|
vault secrets enable -path=kv-v1 -version=1 kv |
Enable KV v1 |
vault kv put kv-v1/path key=value |
Write secret |
vault kv get kv-v1/path |
Read secret |
vault kv get -field=key kv-v1/path |
Read single field |
vault kv list kv-v1/path/ |
List secrets |
vault kv delete kv-v1/path |
Delete (permanent) |
Next: KV Version 2