ops: add HashiCorp Vault for secrets management

Replaces .env files across all KiteStacks apps. Vault runs as a Docker
container bound to 127.0.0.1:8200 with file storage backend.

- apps/vault/: compose file + vault.hcl config (TLS disabled, localhost only)
- scripts/vault-env.sh: fetches secret from Vault KV and injects as env
  vars before running docker compose (drops the .env pattern entirely)
- scripts/vault-init.sh: one-time init — GPG-encrypts unseal keys to
  ~/.vault-keys.gpg, creates kitestacks policy + limited app token
- scripts/vault-unseal.sh: post-restart unseal via GPG-decrypted key
- docs/vault-setup.md: full setup guide including secret migration steps

Usage: vault-env.sh kitestacks/authentik -- docker compose up -d

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kenpat 2026-06-19 03:01:12 -05:00
parent 5b3698191e
commit dbcf51993d
6 changed files with 321 additions and 0 deletions

View file

@ -0,0 +1,15 @@
storage "file" {
path = "/vault/data"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = true
}
# Only accept connections from localhost and internal Docker network.
# Vault is NOT exposed on a public port access via SSH tunnel or from monk only.
api_addr = "http://127.0.0.1:8200"
cluster_addr = "http://127.0.0.1:8201"
ui = true

View file

@ -0,0 +1,26 @@
services:
vault:
image: hashicorp/vault:1.17
container_name: vault
restart: unless-stopped
ports:
# Bound to localhost only — never expose Vault to the internet
- "127.0.0.1:8200:8200"
environment:
VAULT_ADDR: "http://127.0.0.1:8200"
cap_add:
- IPC_LOCK
volumes:
- vault_data:/vault/data
- ./config/vault.hcl:/vault/config/vault.hcl:ro
command: server -config=/vault/config/vault.hcl
healthcheck:
test: ["CMD", "vault", "status", "-address=http://127.0.0.1:8200"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes:
vault_data:
name: vault_data