disclosure-bureau/infra/disclosure-stack/scripts/bootstrap.sh

114 lines
5.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# Full first-time bootstrap on the VPS.
# Idempotent — safe to re-run; rsync only ships diffs, docker compose only restarts changed services.
#
# Steps:
# 1. mkdir /data/disclosure on VPS
# 2. rsync compose files + web/ source + wiki/ + processing/png + processing/crops
# 3. SSH: docker compose up -d db
# 4. Wait for db healthy
# 5. Apply Supabase init + chat schema
# 6. docker compose up -d (everything else)
# 7. Report URLs
set -euo pipefail
source "$(dirname "$0")/_lib.sh"
LAPTOP_UFO_ROOT="${LAPTOP_UFO_ROOT:-/Users/guto/ufo}"
STACK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
echo "================================================================"
echo " STAGE A — create deploy dir + sync code (fast)"
echo "================================================================"
vps_ssh "mkdir -p ${VPS_DEPLOY_ROOT}/{web,wiki,processing,raw,migrations}"
echo ""
echo "→ Syncing infra/disclosure-stack/ (compose + kong + .env + scripts)"
vps_rsync "${STACK_DIR}/docker-compose.yml" "${VPS_DEPLOY_ROOT}/docker-compose.yml"
vps_rsync "${STACK_DIR}/kong.yml" "${VPS_DEPLOY_ROOT}/kong.yml"
vps_rsync "${STACK_DIR}/init-db.sql" "${VPS_DEPLOY_ROOT}/migrations/00-init.sql"
vps_rsync "${STACK_DIR}/../supabase/migrations/0001_chat_schema.sql" "${VPS_DEPLOY_ROOT}/migrations/01-chat-schema.sql"
vps_rsync "${STACK_DIR}/../supabase/migrations/0002_chunks_retrieval.sql" "${VPS_DEPLOY_ROOT}/migrations/02-chunks-retrieval.sql"
vps_rsync "${STACK_DIR}/.env" "${VPS_DEPLOY_ROOT}/.env"
echo ""
echo "→ Syncing web/ (Next.js source, excl. node_modules/.next)"
if [ "$VPS_AUTH" = "password" ]; then
SSHPASS="$VPS_PASSWORD" sshpass -e rsync -avz --delete \
--exclude node_modules --exclude .next --exclude .env.local \
-e "ssh -o StrictHostKeyChecking=accept-new -p $VPS_PORT" \
"${LAPTOP_UFO_ROOT}/web/" "${VPS_USER}@${VPS_HOST}:${VPS_DEPLOY_ROOT}/web/"
else
rsync -avz --delete \
--exclude node_modules --exclude .next --exclude .env.local \
-e "ssh -o StrictHostKeyChecking=accept-new -p $VPS_PORT -i ${VPS_SSH_KEY/#\~/$HOME}" \
"${LAPTOP_UFO_ROOT}/web/" "${VPS_USER}@${VPS_HOST}:${VPS_DEPLOY_ROOT}/web/"
fi
echo ""
echo "================================================================"
echo " STAGE B — sync wiki + processing (data — can be slow first time)"
echo "================================================================"
echo "→ Syncing wiki/ (markdown)"
vps_rsync "${LAPTOP_UFO_ROOT}/wiki/" "${VPS_DEPLOY_ROOT}/wiki/"
echo ""
echo "→ Syncing processing/png/ (page images — large)"
vps_rsync "${LAPTOP_UFO_ROOT}/processing/png/" "${VPS_DEPLOY_ROOT}/processing/png/"
echo ""
echo "→ Syncing processing/ocr/ (text)"
vps_rsync "${LAPTOP_UFO_ROOT}/processing/ocr/" "${VPS_DEPLOY_ROOT}/processing/ocr/"
echo ""
echo "→ Syncing processing/crops/ + processing/tables/ + processing/uap-frames/"
vps_rsync "${LAPTOP_UFO_ROOT}/processing/crops/" "${VPS_DEPLOY_ROOT}/processing/crops/" 2>&1 || true
vps_rsync "${LAPTOP_UFO_ROOT}/processing/tables/" "${VPS_DEPLOY_ROOT}/processing/tables/" 2>&1 || true
vps_rsync "${LAPTOP_UFO_ROOT}/processing/case-images/" "${VPS_DEPLOY_ROOT}/processing/case-images/" 2>&1 || true
vps_rsync "${LAPTOP_UFO_ROOT}/processing/uap-frames/" "${VPS_DEPLOY_ROOT}/processing/uap-frames/" 2>&1 || true
vps_rsync "${LAPTOP_UFO_ROOT}/processing/video-analysis/" "${VPS_DEPLOY_ROOT}/processing/video-analysis/" 2>&1 || true
echo ""
echo "================================================================"
echo " STAGE C — start stack on VPS"
echo "================================================================"
vps_ssh "set -e
cd ${VPS_DEPLOY_ROOT}
echo '→ docker compose up -d db'
docker compose up -d db
echo '→ Waiting for db healthy…'
for i in {1..30}; do
STATUS=\$(docker inspect --format='{{.State.Health.Status}}' disclosure-db 2>/dev/null || echo starting)
if [ \"\$STATUS\" = healthy ]; then echo ' ✓ db healthy'; break; fi
sleep 2
done
echo ''
echo '→ Applying init-db.sql (roles + schemas)'
docker exec -i disclosure-db psql -U postgres < migrations/00-init.sql 2>&1 | tail -5 || true
echo ''
echo '→ Applying chat schema'
docker exec -i disclosure-db psql -U postgres < migrations/01-chat-schema.sql 2>&1 | tail -5 || true
echo ''
echo '→ Applying chunks retrieval schema (pgvector + hybrid_search)'
docker exec -i disclosure-db psql -U postgres < migrations/02-chunks-retrieval.sql 2>&1 | tail -5 || true
echo ''
echo '→ docker compose up -d (entire stack incl. embed-service)'
docker compose up -d
echo ''
echo '→ Status:'
docker compose ps
"
echo ""
echo "================================================================"
echo " ✓ Bootstrap complete"
echo "================================================================"
echo ""
echo "URLs (give DNS + TLS issuance ~5 min):"
echo " Main app: https://${DOMAIN_MAIN}"
echo " Studio: https://${DOMAIN_STUDIO}"
echo " Supa API: https://${DOMAIN_API}"
echo " Search: https://${DOMAIN_SEARCH}"
echo ""
echo "Tail container logs: ./scripts/logs.sh <service>"
echo "Service list: ./scripts/ssh.sh 'cd ${VPS_DEPLOY_ROOT} && docker compose ps'"