2026-08-14 12:43:11 +02:00
#!/bin/bash
# deploy.sh - Deploy OSINT Board to the shared gu_common infrastructure
set -e
SKIP_PULL = false
if [ " $1 " = "--skip-pull" ] ; then
SKIP_PULL = true
fi
SERVER = " ${ DEPLOY_SERVER :- root @76.13.144.52 } "
2026-08-22 22:54:18 +02:00
REMOTE_DIR = " ${ DEPLOY_DIR :- /opt/gupi } "
# GUPI runs from its own dir with its own env; the shared services come from gu_common.
COMPOSE = "docker compose -f ${ REMOTE_DIR } /docker-compose.prod.yml --env-file ${ REMOTE_DIR } /.env.prod"
2026-08-14 12:43:11 +02:00
TARGET_HOST = $( echo " ${ SERVER } " | sed 's/.*@//' )
OWN_IP = $( curl -sf --max-time 3 ifconfig.me 2>/dev/null || echo "unknown" )
if [ " $OWN_IP " = " $TARGET_HOST " ] ; then
echo "Error: deploy.sh must be run from your local machine, not the server."
exit 1
fi
REPO_DIR = " $( cd " $( dirname " ${ BASH_SOURCE [0] } " ) " && pwd ) "
echo "==> Deploying OSINT Board to ${ SERVER } : ${ REMOTE_DIR } "
if [ " $SKIP_PULL " = true ] ; then
echo "==> Skipping git pull (--skip-pull flag set)"
else
echo "==> Checking for upstream changes..."
HEAD_BEFORE = $( git -C " $REPO_DIR " rev-parse HEAD)
if ! git -C " $REPO_DIR " pull --ff-only; then
echo "Error: git pull failed. Resolve local state before deploying."
exit 1
fi
HEAD_AFTER = $( git -C " $REPO_DIR " rev-parse HEAD)
if [ " $HEAD_BEFORE " != " $HEAD_AFTER " ] ; then
echo "New upstream commits were pulled. Review and test them before deploying."
git -C " $REPO_DIR " log --oneline " ${ HEAD_BEFORE } .. ${ HEAD_AFTER } "
exit 1
fi
fi
echo "==> Building locally..."
npm run build
echo "==> Syncing files..."
ssh " $SERVER " "mkdir -p ${ REMOTE_DIR } "
rsync -avz --delete \
--exclude 'node_modules' \
--exclude '.git' \
--exclude 'dist' \
--exclude '.env' \
--exclude '.env.local' \
--exclude '.env.prod' \
--exclude '.DS_Store' \
./ " ${ SERVER } : ${ REMOTE_DIR } /"
2026-08-22 22:54:18 +02:00
echo "==> Verifying GUPI environment..."
ssh " $SERVER " "test -f ${ REMOTE_DIR } /.env.prod || { echo 'ERROR: ${ REMOTE_DIR } /.env.prod is missing (copy .env.prod.example and fill it in)'; exit 1; }"
2026-08-14 12:43:11 +02:00
echo "==> Ensuring shared network exists..."
ssh " $SERVER " "docker network create gnommo 2>/dev/null || true"
echo "==> Building application image..."
ssh " $SERVER " "CACHEBUST=\$(date +%s) && $COMPOSE build --build-arg CACHEBUST=\$CACHEBUST app"
echo "==> Waiting for gu_common PostgreSQL..."
for i in $( seq 1 12) ; do
if ssh " $SERVER " "docker exec gnommo-db pg_isready -q" 2>/dev/null; then
echo " PostgreSQL is ready."
break
fi
echo " Not ready yet, waiting... ( $i /12)"
sleep 5
if [ " $i " -eq 12 ] ; then
echo "ERROR: gu_common PostgreSQL did not become ready."
exit 1
fi
done
echo "==> Running osint schema migrations..."
ssh " $SERVER " " $COMPOSE run --rm --no-deps app npm run migrate:up"
echo "==> Starting application..."
ssh " $SERVER " " $COMPOSE up -d app"
echo "==> Waiting for OSINT Board health check..."
for i in $( seq 1 24) ; do
if ssh " $SERVER " "docker exec gnommo-osint-board node -e \"fetch('http://127.0.0.1:8787/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\"" 2>/dev/null; then
echo " OSINT Board is healthy."
break
fi
echo " Not ready yet, waiting... ( $i /24)"
sleep 5
if [ " $i " -eq 24 ] ; then
echo "ERROR: OSINT Board did not become healthy within 2 minutes."
exit 1
fi
done
2026-08-22 23:06:02 +02:00
echo "==> Done! https://gupi.glitch.university"