Secrets Management — HashiCorp Vault
Centralized secrets management with HA Raft storage, Kubernetes authentication, Transit encryption, and fine-grained RBAC policies.
Why Vault?
Vault Architecture#
┌─────────────────────────────────────────────────────┐
│ lobstack-vault namespace │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ vault-0 │ │ vault-1 │ │ vault-2 │ HA Raft │
│ │ (leader) │◄─┤(follower)│◄─┤(follower)│ Cluster │
│ └────┬─────┘ └──────────┘ └──────────┘ │
│ │ │
│ ┌────▼───────────────────────────────────┐ │
│ │ Vault Agent Injector │ │
│ │ (Sidecar injection for pods) │ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ Secrets Store CSI Driver │ │
│ │ (Volume-mounted secrets for K8s) │ │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘| Component | Replicas | Purpose |
|---|---|---|
| Vault Server | 3 (5 in production) | Secret storage, Transit engine, auth |
| Agent Injector | 2 | Sidecar injection for automatic secret delivery |
| CSI Provider | DaemonSet | Volume-mounted secrets for K8s integration |
| Audit Storage | 10 GB PVC | Immutable audit trail of all operations |
| Data Storage | 20 GB PVC (encrypted) | Raft integrated storage for all secrets |
Secrets Engines#
KV v2 (Key-Value Store)#
The primary secrets engine stores all Lobstack credentials as versioned key-value pairs. KV v2 provides version history, soft delete, and check-and-set for safe concurrent updates.
# Platform-wide API keys (read by the Lobstack API)
secret/data/lobstack/api-keys
├── anthropic_api_key
├── openai_api_key
├── google_api_key
├── xai_api_key
├── moonshot_api_key
├── hetzner_api_token
├── do_api_token
├── vultr_api_key
├── stripe_secret_key
├── supabase_service_key
└── agent_api_secret
# Per-agent secrets (one path per agent)
secret/data/lobstack/agent/{agent-id}
├── ai_api_key
├── ai_api_key_env_var
├── openclaw_model
├── telegram_token
└── agent_api_secretTransit Engine (Encryption-as-a-Service)#
The Transit engine provides AES-256-GCM encryption without exposing keys. Applications send plaintext → Vault returns ciphertext. Keys are managed entirely within Vault with 90-day automatic rotation.
| Key Name | Algorithm | Auto-Rotation | Used By |
|---|---|---|---|
| lobstack | AES-256-GCM | 90 days | API key encryption, sensitive config |
| agent-data | AES-256-GCM | 90 days | Agent workspace data, user tokens |
Authentication#
Vault uses the Kubernetes auth method — pods authenticate using their ServiceAccount JWT tokens. No static tokens or passwords are needed. Each service role gets a scoped Vault token with limited TTL.
# Lobstack API — can read all platform secrets + manage agent secrets
vault write auth/kubernetes/role/lobstack-api \
bound_service_account_names=lobstack-api \
bound_service_account_namespaces=lobstack-control-plane \
policies=lobstack-api \
ttl=1h \
max_ttl=4h
# Agent pods — can ONLY read their own agent secret
vault write auth/kubernetes/role/lobstack-agent \
bound_service_account_names=lobstack-agent \
bound_service_account_namespaces=lobstack-agents \
policies=lobstack-agent \
ttl=1h \
max_ttl=4hAccess Policies#
Vault policies define exactly what each service can access. The agent policy uses templated paths — each agent can only read secrets for its own agent ID, enforced cryptographically by Vault.
# Agent Policy (templated — each agent reads ONLY its own secrets)
path "secret/data/lobstack/agent/{{identity.entity.metadata.agent_id}}" {
capabilities = ["read"]
}
# Agents can encrypt/decrypt their workspace data
path "transit/encrypt/agent-data" {
capabilities = ["update"]
}
path "transit/decrypt/agent-data" {
capabilities = ["update"]
}# API Policy — full platform secret access + agent management
path "secret/data/lobstack/api-keys" {
capabilities = ["read"]
}
path "secret/data/lobstack/agent/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "transit/encrypt/lobstack" {
capabilities = ["update"]
}
path "transit/decrypt/lobstack" {
capabilities = ["update"]
}Secret Delivery#
Secrets are delivered to pods via two mechanisms, used together for defense-in-depth:
Vault Agent Injector
A sidecar container is injected into each pod. It authenticates to Vault, fetches secrets, and writes them as environment variable files. Secrets are refreshed every 5 minutes.
Secrets Store CSI Driver
Mounts Vault secrets as files in the pod's filesystem. Syncs to Kubernetes Secrets for envFrom usage. Supports automatic rotation.
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "lobstack-api"
vault.hashicorp.com/agent-inject-secret-api-keys: "secret/data/lobstack/api-keys"
vault.hashicorp.com/agent-inject-template-api-keys: |
{{- with secret "secret/data/lobstack/api-keys" -}}
export ANTHROPIC_API_KEY="{{ .Data.data.anthropic_api_key }}"
export OPENAI_API_KEY="{{ .Data.data.openai_api_key }}"
export STRIPE_SECRET_KEY="{{ .Data.data.stripe_secret_key }}"
{{- end -}}Application Client#
The src/lib/vault.ts module provides a TypeScript client that handles authentication, secret retrieval, encryption, and caching with automatic environment variable fallback.
import { getApiKeys, setAgentSecret, deleteAgentSecret, encrypt, decrypt } from "@/lib/vault";
// Get all platform API keys (cached, falls back to env vars)
const keys = await getApiKeys();
keys.anthropicApiKey; // From Vault or ANTHROPIC_API_KEY env
// Store agent-specific secrets
await setAgentSecret("agent-abc123", {
ai_api_key: "sk-ant-...",
telegram_token: "123456:ABC-...",
});
// Clean up on agent teardown
await deleteAgentSecret("agent-abc123");
// Encrypt/decrypt via Transit engine
const cipher = await encrypt("sensitive-data"); // vault:v1:...
const plain = await decrypt(cipher); // sensitive-dataAudit Logging#
Every Vault operation is logged — secret reads, writes, encryptions, decryptions, authentication events, and policy changes. Audit logs are written to persistent storage and retained for 2+ years, aligned with SOC 2 requirements.
Initialization
infra/kubernetes/vault/vault-init.sh after deploying Vault to configure engines, policies, and Kubernetes auth. See Compliance Readiness for the full audit trail requirements.