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>
64 lines
2.1 KiB
Bash
Executable file
64 lines
2.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# vault-env.sh — fetch secrets from Vault and run a command with them as env vars
|
|
#
|
|
# Usage:
|
|
# vault-env.sh <vault-path> -- docker compose up -d
|
|
# 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
|
|
#
|
|
# Vault secret paths follow the pattern: kitestacks/<app>
|
|
# Each key in the secret maps directly to an env var name.
|
|
#
|
|
# Example: vault kv put kitestacks/authentik \
|
|
# AUTHENTIK_SECRET_KEY="abc123" \
|
|
# PG_PASS="postgres-pw"
|
|
|
|
set -euo pipefail
|
|
|
|
VAULT_ADDR="${VAULT_ADDR:-http://127.0.0.1:8200}"
|
|
VAULT_TOKEN_FILE="${HOME}/.vault-token"
|
|
|
|
if [[ $# -lt 3 ]] || [[ "$2" != "--" ]]; then
|
|
echo "Usage: vault-env.sh <secret-path> -- <command...>"
|
|
echo "Example: vault-env.sh kitestacks/authentik -- docker compose up -d"
|
|
exit 1
|
|
fi
|
|
|
|
SECRET_PATH="$1"
|
|
shift 2 # remove path and --
|
|
|
|
# Check Vault is reachable
|
|
if ! vault status -address="${VAULT_ADDR}" &>/dev/null; then
|
|
echo "ERROR: Vault is not reachable at ${VAULT_ADDR}"
|
|
echo " Start it: cd apps/vault && docker compose up -d"
|
|
echo " Unseal: VAULT_ADDR=${VAULT_ADDR} vault operator unseal"
|
|
exit 1
|
|
fi
|
|
|
|
# Check we have a token
|
|
if [[ -z "${VAULT_TOKEN:-}" ]] && [[ ! -f "${VAULT_TOKEN_FILE}" ]]; then
|
|
echo "ERROR: No VAULT_TOKEN set and no ~/.vault-token file found"
|
|
echo " Login: vault login -address=${VAULT_ADDR}"
|
|
exit 1
|
|
fi
|
|
|
|
# Fetch the secret as JSON and convert to KEY=VALUE exports
|
|
SECRET_JSON=$(vault kv get -address="${VAULT_ADDR}" -format=json "secret/${SECRET_PATH}" 2>/dev/null) || {
|
|
echo "ERROR: Secret not found at secret/${SECRET_PATH}"
|
|
echo " Create it: vault kv put secret/${SECRET_PATH} KEY=value ..."
|
|
exit 1
|
|
}
|
|
|
|
# Build env from the secret's data map
|
|
declare -a ENV_ARGS=()
|
|
while IFS='=' read -r key value; do
|
|
ENV_ARGS+=("${key}=${value}")
|
|
done < <(echo "${SECRET_JSON}" | python3 -c "
|
|
import json, sys
|
|
data = json.load(sys.stdin)
|
|
for k, v in data['data']['data'].items():
|
|
print(f'{k}={v}')
|
|
")
|
|
|
|
# Execute the command with secrets injected as env vars
|
|
exec env "${ENV_ARGS[@]}" "$@"
|