#!/bin/sh # Infisical secret injection entrypoint # Fetches secrets from Infisical API and injects them as env vars before starting the app. # Required env vars: INFISICAL_CLIENT_ID, INFISICAL_CLIENT_SECRET # Optional: INFISICAL_PROJECT_SLUG (default: rspace), INFISICAL_ENV (default: prod), # INFISICAL_URL (default: http://infisical:8080) # Optional: INFISICAL_AI_CLIENT_ID, INFISICAL_AI_CLIENT_SECRET — fetches AI keys # from a second Infisical project (INFISICAL_AI_PROJECT_SLUG, INFISICAL_AI_SECRET_PATH) set -e INFISICAL_URL="${INFISICAL_URL:-http://infisical:8080}" INFISICAL_ENV="${INFISICAL_ENV:-prod}" INFISICAL_PROJECT_SLUG="${INFISICAL_PROJECT_SLUG:-rspace}" fetch_secrets() { # Args: $1=clientId, $2=clientSecret, $3=projectSlug, $4=secretPath, $5=label bun -e " (async () => { try { const base = '$INFISICAL_URL'; const auth = await fetch(base + '/api/v1/auth/universal-auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientId: '$1', clientSecret: '$2' }) }).then(r => r.json()); if (!auth.accessToken) { console.error('[infisical:$5] Auth failed'); process.exit(1); } const secrets = await fetch(base + '/api/v3/secrets/raw?workspaceSlug=$3&environment=$INFISICAL_ENV&secretPath=$4&recursive=true', { headers: { 'Authorization': 'Bearer ' + auth.accessToken } }).then(r => r.json()); if (!secrets.secrets) { console.error('[infisical:$5] No secrets returned'); process.exit(1); } for (const s of secrets.secrets) { const escaped = s.secretValue.replace(/'/g, \"'\\\\''\" ); console.log('export ' + s.secretKey + \"='\" + escaped + \"'\"); } } catch (e) { console.error('[infisical:$5] Error:', e.message); process.exit(1); } })(); " 2>&1 } if [ -z "$INFISICAL_CLIENT_ID" ] || [ -z "$INFISICAL_CLIENT_SECRET" ]; then echo "[infisical] No credentials set, starting without secret injection" exec "$@" fi # ── Primary project secrets (rspace) ── echo "[infisical] Fetching secrets from ${INFISICAL_PROJECT_SLUG}/${INFISICAL_ENV}..." EXPORTS=$(fetch_secrets "$INFISICAL_CLIENT_ID" "$INFISICAL_CLIENT_SECRET" "$INFISICAL_PROJECT_SLUG" "/" "primary") || { echo "[infisical] WARNING: Failed to fetch primary secrets, starting with existing env vars" exec "$@" } if echo "$EXPORTS" | grep -q "^export "; then COUNT=$(echo "$EXPORTS" | grep -c "^export ") eval "$EXPORTS" echo "[infisical] Injected ${COUNT} secrets from ${INFISICAL_PROJECT_SLUG}" else echo "[infisical] WARNING: $EXPORTS" echo "[infisical] Starting with existing env vars" fi # ── AI project secrets (optional second source) ── if [ -n "$INFISICAL_AI_CLIENT_ID" ] && [ -n "$INFISICAL_AI_CLIENT_SECRET" ]; then AI_SLUG="${INFISICAL_AI_PROJECT_SLUG:-claude-ops}" AI_PATH="${INFISICAL_AI_SECRET_PATH:-/ai}" echo "[infisical] Fetching AI secrets from ${AI_SLUG}${AI_PATH}..." AI_EXPORTS=$(fetch_secrets "$INFISICAL_AI_CLIENT_ID" "$INFISICAL_AI_CLIENT_SECRET" "$AI_SLUG" "$AI_PATH" "ai") || true if echo "$AI_EXPORTS" | grep -q "^export "; then AI_COUNT=$(echo "$AI_EXPORTS" | grep -c "^export ") eval "$AI_EXPORTS" echo "[infisical] Injected ${AI_COUNT} AI secrets from ${AI_SLUG}${AI_PATH}" else echo "[infisical] WARNING: Failed to fetch AI secrets: $AI_EXPORTS" fi fi exec "$@"