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

113
docs/vault-setup.md Normal file
View file

@ -0,0 +1,113 @@
# HashiCorp Vault: Secrets Management
Vault replaces `.env` files across all KiteStacks apps. Secrets live in Vault's encrypted storage; nothing sensitive is ever written to disk in plaintext or committed to git.
## Architecture
```
monk (T14s)
└── Docker: hashicorp/vault:1.17
├── Bound to 127.0.0.1:8200 only (never public)
├── Storage: vault_data Docker volume (encrypted at rest)
└── secret/kitestacks/<app>
├── kitestacks/authentik → AUTHENTIK_SECRET_KEY, PG_PASS
├── kitestacks/cloudflared → TUNNEL_TOKEN
├── kitestacks/kite-ai → WEBUI_SECRET_KEY, ...
└── kitestacks/openproject → OPENPROJECT_OIDC_SECRET
scripts/vault-env.sh pulls secrets at deploy time and injects them as env vars.
No .env files. No secrets in git.
```
## One-time setup
### 1. Install Vault CLI on monk
```bash
curl -fsSL 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 -y vault
```
### 2. Start Vault
```bash
cd ~/kitestacks-homelab/apps/vault
docker compose up -d
```
### 3. Initialize and unseal
```bash
export VAULT_ADDR=http://127.0.0.1:8200
# Needs GPG key set up: gpg --gen-key if you don't have one
GPG_RECIPIENT=kenpat7177@gmail.com bash ~/kitestacks-homelab/scripts/vault-init.sh
```
This saves encrypted keys to `~/.vault-keys.gpg` and creates a `kitestacks` policy token.
### 4. Write your first secrets
```bash
export VAULT_ADDR=http://127.0.0.1:8200
# Use the app token created by vault-init.sh
# (or root token from: gpg --decrypt ~/.vault-keys.gpg | python3 -c "import json,sys; print(json.load(sys.stdin)['root_token'])")
vault kv put secret/kitestacks/authentik \
AUTHENTIK_SECRET_KEY="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 64)" \
PG_PASS="your-postgres-password"
vault kv put secret/kitestacks/cloudflared \
TUNNEL_TOKEN="your-cf-tunnel-token"
vault kv put secret/kitestacks/openproject \
OPENPROJECT_OIDC_SECRET="your-oidc-secret"
```
### 5. Write app token to ~/.vault-token
```bash
# The app token was printed by vault-init.sh — paste it here:
echo "hvs.YOURTOKEN" > ~/.vault-token
chmod 600 ~/.vault-token
```
## Deploying apps with Vault
Instead of `docker compose up -d`, use vault-env.sh:
```bash
# Add scripts/ to PATH or use full path
PATH="$HOME/kitestacks-homelab/scripts:$PATH"
vault-env.sh kitestacks/authentik -- \
docker compose -f apps/authentik/docker-compose.yml up -d
vault-env.sh kitestacks/cloudflared -- \
docker compose -f apps/cloudflared/docker-compose.yml up -d
```
## After a reboot (unseal)
Vault is sealed after every restart. Unseal it before any deployments:
```bash
export VAULT_ADDR=http://127.0.0.1:8200
bash ~/kitestacks-homelab/scripts/vault-unseal.sh
```
Or add to a post-boot script / systemd unit that runs after docker.
## Verifying secrets
```bash
vault kv get secret/kitestacks/authentik
vault kv list secret/kitestacks/
```
## Why not just use Docker secrets?
Docker Swarm secrets are great but require Swarm mode. For a single-node compose setup, Vault gives you:
- Central secret versioning and audit log
- Rotation without touching compose files
- Same pattern you'd use in a real Kubernetes/Nomad environment