#!/bin/bash # ============================================================================= # Migrate Postiz spaces from plaintext .env to Infisical secret injection # ============================================================================= # # Run this ON the Netcup server as root: # ssh netcup-full # bash /path/to/migrate-to-infisical.sh # # What it does: # 1. Extracts POSTGRES_PASSWORD from each existing .env # 2. Backs up old docker-compose.yml and .env # 3. Copies new Infisical-wired compose files into place # 4. Creates minimal .env (INFISICAL_CLIENT_ID/SECRET + POSTGRES_PASSWORD) # 5. Restarts each space one at a time # 6. Verifies containers come up healthy # 7. Moves old .env to .env.removed (you delete after confirming) # # Prerequisites: # - Machine identities created in Infisical for each project # - /opt/infisical/entrypoint-wrapper.sh exists # - This script is in the same directory as docker-compose.{cc,p2pf,bcrg}.yml # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" POSTIZ_BASE="/opt/postiz" TIMESTAMP=$(date +%Y%m%d-%H%M%S) # Color output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' log() { echo -e "${CYAN}[migrate]${NC} $*"; } ok() { echo -e "${GREEN}[ OK ]${NC} $*"; } warn() { echo -e "${YELLOW}[ WARN ]${NC} $*"; } err() { echo -e "${RED}[ERROR ]${NC} $*"; } # ── Preflight checks ────────────────────────────────────────────────────────── log "Preflight checks..." if [ "$(id -u)" -ne 0 ]; then err "Must run as root (ssh netcup-full)" exit 1 fi if [ ! -f /opt/infisical/entrypoint-wrapper.sh ]; then err "Infisical entrypoint wrapper not found at /opt/infisical/entrypoint-wrapper.sh" exit 1 fi for slug in cc p2pf bcrg; do if [ ! -f "$SCRIPT_DIR/docker-compose.${slug}.yml" ]; then err "Missing $SCRIPT_DIR/docker-compose.${slug}.yml" exit 1 fi done ok "Preflight passed" # ── Space definitions ───────────────────────────────────────────────────────── declare -A SPACE_DIR SPACE_DIR[cc]="crypto-commons" SPACE_DIR[p2pf]="p2pfoundation" SPACE_DIR[bcrg]="bondingcurve" declare -A SPACE_INFISICAL_SLUG SPACE_INFISICAL_SLUG[cc]="postiz-crypto-commons" SPACE_INFISICAL_SLUG[p2pf]="postiz-p2pfoundation" SPACE_INFISICAL_SLUG[bcrg]="postiz-bondingcurve" # ── Collect Infisical credentials ───────────────────────────────────────────── # You can either enter them interactively or set them as env vars before running: # export INFISICAL_CC_CLIENT_ID=... INFISICAL_CC_CLIENT_SECRET=... # export INFISICAL_P2PF_CLIENT_ID=... INFISICAL_P2PF_CLIENT_SECRET=... # export INFISICAL_BCRG_CLIENT_ID=... INFISICAL_BCRG_CLIENT_SECRET=... declare -A INF_CLIENT_ID declare -A INF_CLIENT_SECRET for slug in cc p2pf bcrg; do upper=$(echo "$slug" | tr '[:lower:]' '[:upper:]') id_var="INFISICAL_${upper}_CLIENT_ID" secret_var="INFISICAL_${upper}_CLIENT_SECRET" if [ -n "${!id_var:-}" ] && [ -n "${!secret_var:-}" ]; then INF_CLIENT_ID[$slug]="${!id_var}" INF_CLIENT_SECRET[$slug]="${!secret_var}" ok "Using env var credentials for ${SPACE_DIR[$slug]}" else echo "" log "Enter Infisical machine identity for ${SPACE_DIR[$slug]} (${SPACE_INFISICAL_SLUG[$slug]}):" read -rp " Client ID: " INF_CLIENT_ID[$slug] read -rp " Client Secret: " INF_CLIENT_SECRET[$slug] if [ -z "${INF_CLIENT_ID[$slug]}" ] || [ -z "${INF_CLIENT_SECRET[$slug]}" ]; then err "Missing credentials for ${SPACE_DIR[$slug]}" exit 1 fi fi done echo "" log "Starting migration..." echo "" # ── Migrate each space ──────────────────────────────────────────────────────── for slug in cc p2pf bcrg; do dir="${POSTIZ_BASE}/${SPACE_DIR[$slug]}" log "━━━ Migrating ${SPACE_DIR[$slug]} (postiz-${slug}) ━━━" # 1. Extract POSTGRES_PASSWORD from existing .env if [ -f "$dir/.env" ]; then PG_PASS=$(grep '^POSTGRES_PASSWORD=' "$dir/.env" | cut -d'=' -f2- | tr -d '"' | tr -d "'") if [ -z "$PG_PASS" ]; then err "Could not extract POSTGRES_PASSWORD from $dir/.env" err "Check the file manually and set it in the new .env" exit 1 fi ok "Extracted POSTGRES_PASSWORD from existing .env" else err "No .env found at $dir/.env" exit 1 fi # 2. Backup old files log "Backing up old files..." cp "$dir/docker-compose.yml" "$dir/docker-compose.yml.pre-infisical-${TIMESTAMP}" cp "$dir/.env" "$dir/.env.pre-infisical-${TIMESTAMP}" ok "Backed up to *.pre-infisical-${TIMESTAMP}" # 3. Copy new compose file log "Installing new Infisical-wired compose..." cp "$SCRIPT_DIR/docker-compose.${slug}.yml" "$dir/docker-compose.yml" ok "Installed new docker-compose.yml" # 4. Create minimal .env log "Creating minimal .env (3 values only)..." cat > "$dir/.env" << ENVEOF # Infisical machine identity (fetches all other secrets at container start) INFISICAL_CLIENT_ID=${INF_CLIENT_ID[$slug]} INFISICAL_CLIENT_SECRET=${INF_CLIENT_SECRET[$slug]} # Postgres password (needed at compose interpolation time for DB containers) POSTGRES_PASSWORD=${PG_PASS} ENVEOF chmod 600 "$dir/.env" ok "Created minimal .env (600 perms)" # 5. Restart containers log "Restarting ${SPACE_DIR[$slug]}..." cd "$dir" docker compose down 2>&1 | sed 's/^/ /' docker compose up -d 2>&1 | sed 's/^/ /' # 6. Wait for health log "Waiting for postiz-${slug} to be healthy (up to 90s)..." healthy=false for i in $(seq 1 18); do sleep 5 state=$(docker inspect --format='{{.State.Running}}' "postiz-${slug}" 2>/dev/null || echo "false") if [ "$state" = "true" ]; then # Check if the entrypoint wrapper ran successfully by looking at logs if docker logs "postiz-${slug}" 2>&1 | grep -q "\[infisical-wrapper\] Fetching secrets"; then healthy=true break fi fi echo -n "." done echo "" if $healthy; then ok "postiz-${slug} is running with Infisical secrets" else warn "postiz-${slug} may not be healthy yet. Check logs:" warn " docker logs postiz-${slug} 2>&1 | head -30" warn "Continuing with next space..." fi # 7. Move old .env backup to .removed mv "$dir/.env.pre-infisical-${TIMESTAMP}" "$dir/.env.REMOVED-${TIMESTAMP}" ok "Old .env renamed to .env.REMOVED-${TIMESTAMP}" echo "" done # ── Summary ─────────────────────────────────────────────────────────────────── echo "" log "━━━ Migration Complete ━━━" echo "" log "Verify each space is working:" echo " curl -s https://socials.crypto-commons.org | head -5" echo " curl -s https://p2pf.rsocials.online | head -5" echo " curl -s https://bondingcurve.rsocials.online | head -5" echo "" log "Check container logs:" echo " docker logs postiz-cc 2>&1 | grep infisical" echo " docker logs postiz-p2pf 2>&1 | grep infisical" echo " docker logs postiz-bcrg 2>&1 | grep infisical" echo "" log "Once confirmed working, delete the old .env backups:" echo " rm /opt/postiz/crypto-commons/.env.REMOVED-*" echo " rm /opt/postiz/p2pfoundation/.env.REMOVED-*" echo " rm /opt/postiz/bondingcurve/.env.REMOVED-*" echo " rm /opt/postiz/*/docker-compose.yml.pre-infisical-*" echo "" ok "Done! Secrets are now managed by Infisical."