What is HashiCorp Vault?
Vault is a tool that centrally stores, issues, and audits secrets—API keys, database passwords, certificates, and the like—in a secure way. It addresses the fundamental risk of hardcoding passwords in source code or scattering environment-variable files across systems.
Vault’s strongest differentiator is dynamic secrets. Rather than merely storing static passwords, it creates short-lived database accounts on the fly whenever an application requests them, then automatically revokes those accounts when the TTL expires. Even if a password leaks, the blast radius is limited by the short lifetime, and every issuance is recorded in the audit log—who received credentials, and when.
This guide covers Vault’s core concepts and the main workflows (KV secrets, database dynamic credentials, and AppRole) in a single-node development/staging setup.
The vault server -dev used in this document is for learning only. Data lives in memory, the server auto-unseals, and there is no TLS. Never use it in production. Production requires persistent storage (Integrated Storage/Raft), TLS, and a distributed unseal-key configuration.
Core Concepts
| Concept | Description |
|---|---|
| Seal / Unseal | Vault starts in an encrypted sealed state. You must unseal it with master-key shards before data can be accessed |
| Unseal Key (Shamir) | The master key is split into N shards; K of them are required to decrypt (e.g., 3 of 5) |
| Root Token | The initial token with all privileges. Revoke it after setup |
| Token | Every request is authenticated with a token. Tokens carry a TTL and attached policies |
| Policy | Path-level permissions (capabilities) written in HCL |
| Secrets Engine | Plugins that handle secrets (kv, database, pki, and others) |
| Auth Method | How users/apps authenticate (token, approle, userpass, kubernetes) |
Starting the Server and Unsealing
Dev server for learning:
vault server -dev -dev-root-token-id="root"
# VAULT_ADDR, Root TokenA production-style start (Raft storage) uses a config file.
# /etc/vault.d/vault.hcl
storage "raft" {
path = "/opt/vault/data"
node_id = "node1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/etc/vault.d/tls/vault.crt"
tls_key_file = "/etc/vault.d/tls/vault.key"
}
api_addr = "https://vault.example.com:8200"
ui = trueexport VAULT_ADDR='https://vault.example.com:8200'
vault operator init # unseal 5 + root ( !)
vault operator unseal # 3
vault status # Sealed: false checkThe vault operator init output (unseal keys and root token) is shown only once. Lose it and the data is gone forever. Store key shards with different people / in different safes.
CLI Login
export VAULT_ADDR='http://127.0.0.1:8200'
vault login # (dev root)
vault token lookup # ·TTL· checkKV v2 — Static Secrets
The most basic secrets store. v2 supports versioning and soft delete.
# KV v2
vault secrets enable -path=secret kv-v2
# when save
vault kv put secret/myapp/db username="appuser" password="s3cr3t"
#
vault kv get secret/myapp/db
vault kv get -field=password secret/myapp/db #
#
vault kv get -version=1 secret/myapp/db
vault kv metadata get secret/myapp/db #
# / /
vault kv delete secret/myapp/db
vault kv undelete -versions=2 secret/myapp/db
vault kv destroy -versions=1 secret/myapp/dbNote that KV v2 inserts /data/ into the API path (important when writing policies).
Policies
Permissions are defined as capabilities per path.
# myapp-policy.hcl
# KV v2 path secret/data/...
path "secret/data/myapp/*" {
capabilities = ["read", "list"]
}
path "secret/metadata/myapp/*" {
capabilities = ["list", "read"]
}vault policy write myapp myapp-policy.hcl
vault policy read myappCapabilities are create, read, update, delete, list, sudo, deny. Grant them on a least-privilege basis.
Dynamic Credentials — Database Secrets Engine
Vault connects to PostgreSQL and creates a temporary account on every request.
#
vault secrets enable database
# DB settings (Vault )
vault write database/config/postgres \
plugin_name=postgresql-database-plugin \
allowed_roles="readonly" \
connection_url="postgresql://{{username}}:{{password}}@db.example.com:5432/app?sslmode=require" \
username="vault_admin" \
password="adminpass"
# : when run SQL TTL
vault write database/roles/readonly \
db_name=postgres \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"Requesting credentials then looks like this:
vault read database/creds/readonly
# Key Value
# lease_id database/creds/readonly/abc123
# lease_duration 1h
# username v-token-readonly-x9f2...
# password A1b2-randomgeneratedThe issued account is automatically revoked after one hour. To revoke immediately:
vault lease revoke database/creds/readonly/abc123Using dynamic credentials requires the Vault admin account to have CREATEROLE on the database. Rotate that admin account itself periodically with vault write database/rotate-root/postgres.
AppRole — Application Authentication
The standard way for applications and CI (not humans) to authenticate to Vault.
vault auth enable approle
vault write auth/approle/role/myapp \
token_policies="myapp" \
token_ttl=1h token_max_ttl=4h \
secret_id_ttl=24h
# RoleID + SecretID
vault read auth/approle/role/myapp/role-id
vault write -f auth/approle/role/myapp/secret-id
# →
vault write auth/approle/login \
role_id="<role_id>" secret_id="<secret_id>"A common pattern is to bake the RoleID into the build and inject the SecretID safely at runtime (e.g., as a CI secret).
Audit Logs
vault audit enable file file_path=/var/log/vault/audit.logEvery request and response is recorded in hashed form. This is central to compliance.
Recap
| Item | Key point |
|---|---|
| Seal/Unseal | Sealed at start; unsealed with Shamir K-of-N keys |
| KV v2 | Static secrets, versioning and soft delete, /data/ in the path |
| Policy | Path-level capabilities, least privilege |
| Database engine | Temporary accounts on request, auto-revoked after TTL |
| AppRole | App auth with RoleID + SecretID |
| Audit | Record all requests with vault audit enable |
Vault’s real value goes beyond storing static secrets: it is dynamic, short-lived credentials. The core mindset is “don’t store passwords—issue them briefly when needed.”
AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us
Questions & answers
Ask a question about this guide. We'll review and reply.