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:
parent
5b3698191e
commit
dbcf51993d
6 changed files with 321 additions and 0 deletions
74
scripts/vault-init.sh
Executable file
74
scripts/vault-init.sh
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/env bash
|
||||
# vault-init.sh — initialize Vault and save keys securely
|
||||
# Run ONCE after first `docker compose up` in apps/vault/
|
||||
# Keys are GPG-encrypted and stored in ~/.vault-keys.gpg
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
VAULT_ADDR="${VAULT_ADDR:-http://127.0.0.1:8200}"
|
||||
KEYS_FILE="${HOME}/.vault-keys.gpg"
|
||||
GPG_RECIPIENT="${GPG_RECIPIENT:-${USER}}"
|
||||
|
||||
export VAULT_ADDR
|
||||
|
||||
echo "=== KiteStacks Vault Initialization ==="
|
||||
echo "Vault address: ${VAULT_ADDR}"
|
||||
echo ""
|
||||
|
||||
# Check not already initialized
|
||||
if vault status 2>/dev/null | grep -q "Initialized.*true"; then
|
||||
echo "Vault is already initialized."
|
||||
read -rp "Re-initialize? This DESTROYS all secrets. [y/N] " ans
|
||||
[[ "${ans}" == "y" ]] || exit 0
|
||||
fi
|
||||
|
||||
# Initialize
|
||||
echo "Initializing Vault (1 key share, 1 key threshold for homelab simplicity)..."
|
||||
INIT_OUTPUT=$(vault operator init -key-shares=1 -key-threshold=1 -format=json)
|
||||
|
||||
UNSEAL_KEY=$(echo "${INIT_OUTPUT}" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['unseal_keys_b64'][0])")
|
||||
ROOT_TOKEN=$(echo "${INIT_OUTPUT}" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['root_token'])")
|
||||
|
||||
echo ""
|
||||
echo "Encrypting keys with GPG (recipient: ${GPG_RECIPIENT}) ..."
|
||||
echo "${INIT_OUTPUT}" | gpg --encrypt --recipient "${GPG_RECIPIENT}" --output "${KEYS_FILE}"
|
||||
echo "Keys saved to: ${KEYS_FILE}"
|
||||
echo ""
|
||||
|
||||
# Unseal immediately
|
||||
echo "Unsealing Vault ..."
|
||||
vault operator unseal "${UNSEAL_KEY}"
|
||||
echo ""
|
||||
|
||||
# Log in with root token
|
||||
vault login "${ROOT_TOKEN}"
|
||||
echo ""
|
||||
|
||||
# Enable KV v2 secret engine at secret/
|
||||
vault secrets enable -path=secret kv-v2 2>/dev/null || echo "(secret/ already enabled)"
|
||||
echo ""
|
||||
|
||||
# Create a policy for kitestacks apps
|
||||
vault policy write kitestacks - <<'POLICY'
|
||||
path "secret/data/kitestacks/*" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
POLICY
|
||||
|
||||
# Create an app token with limited policy
|
||||
APP_TOKEN=$(vault token create -policy=kitestacks -display-name="kitestacks-apps" -format=json | python3 -c "import json,sys; print(json.load(sys.stdin)['auth']['client_token'])")
|
||||
|
||||
echo ""
|
||||
echo "=== SETUP COMPLETE ==="
|
||||
echo ""
|
||||
echo "Root token: stored in ${KEYS_FILE} (gpg-encrypted)"
|
||||
echo "App token: add to ~/.vault-token OR set VAULT_TOKEN env var"
|
||||
echo ""
|
||||
echo " echo '${APP_TOKEN}' > ~/.vault-token && chmod 600 ~/.vault-token"
|
||||
echo ""
|
||||
echo "Add your first secret:"
|
||||
echo " vault kv put secret/kitestacks/authentik AUTHENTIK_SECRET_KEY=... PG_PASS=..."
|
||||
echo ""
|
||||
echo "Then deploy with:"
|
||||
echo " vault-env.sh kitestacks/authentik -- docker compose -f apps/authentik/docker-compose.yml up -d"
|
||||
echo ""
|
||||
Loading…
Add table
Add a link
Reference in a new issue