HashiCorp Vault
HashiCorp Vault provides advanced secret management with dynamic secrets, leasing, and fine-grained access control.
Prerequisites
- Vault server running (self-hosted or HCP Vault)
- Vault CLI installed
- Vault token with appropriate policies
Installation
# macOS
brew install vault
# Linux
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vaultConfiguration
[providers]
vault = { type = "vault", path = "secret/myapp" } # address and token are optional- address: (Optional) The Vault server address. Falls back to
FNOX_VAULT_ADDRorVAULT_ADDR. - path: (Optional) The base path for secrets in Vault (e.g.,
secret/myapp). Defaults tosecret. - token: (Optional) Vault token. Falls back to
FNOX_VAULT_TOKENorVAULT_TOKEN. - namespace: (Optional) Vault namespace. Falls back to
FNOX_VAULT_NAMESPACEorVAULT_NAMESPACE. - credential_command: (Optional) Shell command that prints a Vault token to stdout when no token is configured. The command is rendered as a Tera template and receives
address,path, andnamespace.
Provider-scoped login
Use credential_command when different Vault/OpenBao providers need different tokens:
[providers.vault_team_a]
type = "vault"
address = "https://vault.example.com"
namespace = "team-a"
path = "secret/team-a"
credential_command = "vault login -method=oidc -token-only"fnox sets VAULT_ADDR and VAULT_NAMESPACE for the command from the provider config. The command runs through the platform shell, so shell features like pipes and redirects work. Output is cached briefly for the current fnox process so resolving multiple secrets from the same provider does not repeat the login.
Setup
1. Configure Vault access
# Set Vault address
export VAULT_ADDR="https://vault.example.com:8200"
# Login and get token
vault login -method=userpass username=myuser
# Or export existing token
export VAULT_TOKEN="hvs.CAESIJ..."2. Create policy
# policy.hcl
path "secret/data/myapp/*" {
capabilities = ["read"]
}
path "secret/metadata/myapp/*" {
capabilities = ["list"]
}vault policy write fnox-policy policy.hcl3. Store secrets in Vault
# KV v2 engine
vault kv put secret/myapp/database url="postgresql://prod.example.com/db"
vault kv put secret/myapp/api-key value="sk_live_abc123"4. Reference in fnox
[secrets]
DATABASE_URL = { provider = "vault", value = "database/url" } # → field "url" of secret/myapp/database
API_KEY = { provider = "vault", value = "api-key" } # → field "value" of secret/myapp/api-keyA reference is secret or secret/field. Without a field, fnox reads the value field of the secret.
Usage
# Set token
export VAULT_TOKEN="hvs.CAESIJ..."
# Get secrets
fnox get DATABASE_URL
# Run commands
fnox exec -- ./appUsage notes
The provider reads KV secrets. Use the separate Vault lease backend for dynamic credentials. The provider token must have access to the configured KV path and namespace.
Next steps
- Vault Documentation
- AWS Secrets Manager - Simpler cloud alternative