HashiCorp Vault — Installation Exercises
Practice what you’ve learned about installing and configuring Vault with these hands-on exercises.
Exercise 1 — Start and Explore Dev Server
Task: Start a dev server, explore the defaults, and store your first secret.
- Start a dev server with root token
lab-token - In another terminal, set
VAULT_ADDRandVAULT_TOKEN - Run
vault statusand note the storage type and seal status - List all secrets engines
- Store a secret at
secret/exercise1withcolor=blueandnumber=42 - Read back just the
colorfield
Show Answer
# Terminal 1: Start dev server
vault server -dev -dev-root-token-id="lab-token"
# Terminal 2: Configure environment
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='lab-token'
# Check status
vault status
# Storage Type: inmem
# Sealed: false
# List secrets engines
vault secrets list
# cubbyhole/, identity/, secret/, sys/
# Store a secret
vault kv put secret/exercise1 color=blue number=42
# Read the color field
vault kv get -field=color secret/exercise1
# Output: blue
Exercise 2 — Docker Compose Dev Lab
Task: Create a Docker Compose file for a Vault dev server and interact with it.
- Write a
docker-compose.ymlthat runs Vault 1.15 in dev mode - Set the root token to
docker-lab-token - Start the container
- Use
curlandjqto check Vault’s health endpoint - Use
curlto write a secret via the API - Use the CLI to read the secret back
Show Answer
# docker-compose.yml
services:
vault:
image: hashicorp/vault:1.15
container_name: vault-lab
ports:
- "8200:8200"
environment:
VAULT_DEV_ROOT_TOKEN_ID: docker-lab-token
VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200
cap_add:
- IPC_LOCK
# Start
docker compose up -d
# Check health
curl -s http://127.0.0.1:8200/v1/sys/health | jq
# Set environment
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='docker-lab-token'
# Write via API
curl -s \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"data": {"exercise": "2", "tool": "docker"}}' \
"$VAULT_ADDR/v1/secret/data/exercise2" | jq
# Read via CLI
vault kv get secret/exercise2
# Clean up
docker compose down
Exercise 3 — Production Configuration
Task: Write a production Vault configuration file (without actually running it).
Write a vault.hcl that includes:
- Raft storage at
/opt/vault/datawith node IDprod-vault-1 - TCP listener on all interfaces, port 8200, with TLS
- API address and cluster address
- UI enabled
- Memory lock enabled
- Prometheus telemetry with 24h retention
Show Answer
# vault.hcl — Production configuration
storage "raft" {
path = "/opt/vault/data"
node_id = "prod-vault-1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/opt/vault/tls/vault-cert.pem"
tls_key_file = "/opt/vault/tls/vault-key.pem"
}
api_addr = "https://prod-vault-1.example.com:8200"
cluster_addr = "https://prod-vault-1.example.com:8201"
ui = true
disable_mlock = false
telemetry {
prometheus_retention_time = "24h"
disable_hostname = true
}
Key points:
disable_mlock = falseensures secrets aren’t swapped to disk- TLS is mandatory in production
api_addris what clients use;cluster_addris for inter-node traffic- Telemetry enables Prometheus scraping at
/v1/sys/metrics
Exercise 4 — CLI Mastery
Task: Complete these CLI operations against a dev server:
- Create three secrets:
secret/app/dev,secret/app/staging,secret/app/prod - List all secrets under
secret/app/ - Read
secret/app/prodas JSON and pipe throughjq - Delete
secret/app/dev - Check that the delete was a soft-delete (metadata still exists)
- Permanently destroy
secret/app/devversion 1
Show Answer
# Create secrets
vault kv put secret/app/dev db_host="dev-db.local" db_pass="dev123"
vault kv put secret/app/staging db_host="staging-db.local" db_pass="stage456"
vault kv put secret/app/prod db_host="prod-db.local" db_pass="pr0d789!"
# List secrets
vault kv list secret/app/
# Keys
# ----
# dev
# prod
# staging
# Read as JSON
vault kv get -format=json secret/app/prod | jq '.data.data'
# {
# "db_host": "prod-db.local",
# "db_pass": "pr0d789!"
# }
# Soft-delete
vault kv delete secret/app/dev
# Check metadata still exists
vault kv metadata get secret/app/dev
# Shows metadata with deletion_time set
# Permanently destroy version 1
vault kv destroy -versions=1 secret/app/dev
Exercise 5 — API Exploration
Task: Use only curl (no Vault CLI) to:
- Check if Vault is initialized and unsealed
- List all secrets engines
- Write a secret to
secret/data/api-testwithmethod=curl - Read the secret back
- Delete the secret
Show Answer
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='my-root-token'
# 1. Health check
curl -s "$VAULT_ADDR/v1/sys/health" | jq '{initialized, sealed}'
# {"initialized": true, "sealed": false}
# 2. List secrets engines
curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/sys/mounts" | jq 'keys'
# 3. Write a secret
curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"data": {"method": "curl"}}' \
"$VAULT_ADDR/v1/secret/data/api-test" | jq
# 4. Read the secret
curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/secret/data/api-test" | jq '.data.data'
# {"method": "curl"}
# 5. Delete the secret
curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
--request DELETE \
"$VAULT_ADDR/v1/secret/data/api-test"
What’s Next?
You’ve installed Vault, explored the dev server, and mastered the CLI and API. Next, we’ll dive into secrets engines.
Next Chapter: Secrets Engines