# 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/ ├── 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