#!/bin/sh # seed-infisical.sh — Add missing rApp secrets to the rspace Infisical project. # Run from inside the rspace container: # docker exec -it rspace-online /app/scripts/seed-infisical.sh # # Uses INFISICAL_CLIENT_ID, INFISICAL_CLIENT_SECRET, INFISICAL_URL, # INFISICAL_PROJECT_SLUG, and INFISICAL_ENV from the container environment. set -e INFISICAL_URL="${INFISICAL_URL:-http://infisical:8080}" INFISICAL_ENV="${INFISICAL_ENV:-prod}" INFISICAL_PROJECT_SLUG="${INFISICAL_PROJECT_SLUG:-rspace}" if [ -z "$INFISICAL_CLIENT_ID" ] || [ -z "$INFISICAL_CLIENT_SECRET" ]; then echo "ERROR: INFISICAL_CLIENT_ID and INFISICAL_CLIENT_SECRET must be set." exit 1 fi echo "Authenticating with Infisical at ${INFISICAL_URL}..." TOKEN=$(bun -e " (async () => { const r = await fetch('${INFISICAL_URL}/api/v1/auth/universal-auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientId: process.env.INFISICAL_CLIENT_ID, clientSecret: process.env.INFISICAL_CLIENT_SECRET }) }).then(r => r.json()); if (!r.accessToken) { console.error('Auth failed:', JSON.stringify(r)); process.exit(1); } console.log(r.accessToken); })(); ") || { echo "Authentication failed"; exit 1; } echo "Authenticated. Fetching existing secrets..." EXISTING=$(bun -e " (async () => { const r = await fetch('${INFISICAL_URL}/api/v3/secrets/raw?workspaceSlug=${INFISICAL_PROJECT_SLUG}&environment=${INFISICAL_ENV}&secretPath=/&recursive=true', { headers: { 'Authorization': 'Bearer ${TOKEN}' } }).then(r => r.json()); if (!r.secrets) { console.error('Failed to list secrets'); process.exit(1); } console.log(r.secrets.map(s => s.secretKey).join('\n')); })(); ") || { echo "Failed to list secrets"; exit 1; } # Secrets to seed: NAME|MODULE|DESCRIPTION SECRETS=" DATABASE_URL|core|Full Postgres connection string (e.g. postgres://rspace:PASS@rspace-db:5432/rspace) ADMIN_DIDS|core|Comma-separated admin DIDs R2_ENDPOINT|rTube|Cloudflare R2 S3 endpoint URL R2_BUCKET|rTube|R2 bucket name (default: rtube-videos) R2_ACCESS_KEY_ID|rTube|R2 API key ID R2_SECRET_ACCESS_KEY|rTube|R2 API secret key R2_PUBLIC_URL|rTube|R2 public CDN URL RPHOTOS_IMMICH_URL|rPhotos|Internal Immich URL (e.g. http://immich-server:2283) RPHOTOS_API_KEY|rPhotos|Immich API key RPHOTOS_IMMICH_PUBLIC_URL|rPhotos|Public Immich URL TWENTY_API_TOKEN|rNetwork|Twenty CRM API token HETZNER_API_TOKEN|rForum|Hetzner Cloud API token (Discourse VM provisioning) CLOUDFLARE_API_TOKEN|rForum|Cloudflare API token (Discourse DNS management) CLOUDFLARE_FORUM_ZONE_ID|rForum|Cloudflare zone ID for Discourse forum DNS DISCOURSE_API_KEY|rForum|Discourse admin API key DISCOURSE_URL|rForum|Discourse instance URL (e.g. https://forum.rforum.online) FAL_KEY|AI/MI|Fal.ai API key RUNPOD_API_KEY|AI/MI|RunPod API key X402_PAY_TO|payments|Payment recipient address MAILCOW_API_KEY|EncryptID|Mailcow admin API key ENCRYPTID_DEMO_SPACES|EncryptID|Comma-separated demo space slugs " ADDED=0 SKIPPED=0 echo "" echo "=== Seeding rspace Infisical secrets ===" echo "" echo "$SECRETS" | while IFS='|' read -r NAME MODULE DESC; do # Skip blank lines [ -z "$NAME" ] && continue # Trim whitespace NAME=$(echo "$NAME" | xargs) MODULE=$(echo "$MODULE" | xargs) DESC=$(echo "$DESC" | xargs) # Check if already exists if echo "$EXISTING" | grep -qx "$NAME"; then echo "[skip] $NAME (already exists)" continue fi printf "[%s] %s — %s\n" "$MODULE" "$NAME" "$DESC" printf " Enter value (or press Enter to skip): " read -r VALUE if [ -z "$VALUE" ]; then echo " Skipped." continue fi # Create the secret via Infisical API RESULT=$(bun -e " (async () => { const r = await fetch('${INFISICAL_URL}/api/v3/secrets/raw/$(echo "$NAME" | sed 's/ /%20/g')', { method: 'POST', headers: { 'Authorization': 'Bearer ${TOKEN}', 'Content-Type': 'application/json' }, body: JSON.stringify({ workspaceSlug: '${INFISICAL_PROJECT_SLUG}', environment: '${INFISICAL_ENV}', secretPath: '/', secretValue: $(printf '%s' "$VALUE" | bun -e "process.stdout.write(JSON.stringify(await Bun.stdin.text()))") }) }); if (r.ok) console.log('OK'); else console.log('FAIL: ' + (await r.text())); })(); ") || RESULT="FAIL: bun error" if [ "$RESULT" = "OK" ]; then echo " Added." else echo " ERROR: $RESULT" fi done echo "" echo "Done. Restart the container to pick up new secrets:" echo " docker compose restart rspace"