pingql/deploy.sh

208 lines
5.9 KiB
Bash
Executable File

#!/bin/bash
# PingQL Deploy Script
# Usage: ./deploy.sh [web|api|pay|status|monitor|db|nuke-db|all] [...]
# Example: ./deploy.sh web api
# Example: ./deploy.sh all
# Example: ./deploy.sh nuke-db (wipes all data — NOT included in "all")
#
set -e
SSH="ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_ed25519"
DB_HOST="root@142.132.190.209"
API_HOST="root@88.99.123.102"
WEB_HOST="root@78.47.43.36"
STATUS_HOST="root@46.225.155.167"
MONITOR_HOSTS=("root@5.78.178.12" "root@49.13.118.44")
deploy_db() {
echo "[db] Restarting PostgreSQL on database-eu-central..."
$SSH $DB_HOST "systemctl restart postgresql && echo 'PostgreSQL restarted'"
}
nuke_db() {
echo "⚠️ This will drop all tables in the pingql database, deleting ALL data."
echo " Tables will be recreated on next API/web restart via migrate()."
read -p "Type 'yes' to confirm: " confirm
if [ "$confirm" != "yes" ]; then
echo "Aborted."
return
fi
echo "[nuke-db] Dropping all tables on database-eu-central..."
$SSH $DB_HOST bash << 'REMOTE'
sudo -u postgres psql -d pingql -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public; GRANT ALL ON SCHEMA public TO public;"
echo "All tables dropped"
REMOTE
echo "[nuke-db] Done. Tables will be recreated on next API/web restart."
}
deploy_api() {
echo "[api] Deploying to api-eu-central..."
$SSH $API_HOST bash << 'REMOTE'
cd /opt/pingql
git fetch origin && git reset --hard origin/main
cd apps/api
/root/.bun/bin/bun install
systemctl restart pingql-api
systemctl restart caddy
echo "API deployed and restarted"
REMOTE
}
deploy_pay() {
echo "[pay] Deploying to api-eu-central..."
$SSH $API_HOST bash << 'REMOTE'
cd /opt/pingql
git fetch origin && git reset --hard origin/main
cd apps/pay
/root/.bun/bin/bun install
systemctl restart pingql-pay
systemctl restart caddy
echo "Pay deployed and restarted"
REMOTE
}
deploy_web() {
echo "[web] Deploying to web-eu-central..."
$SSH $WEB_HOST bash << 'REMOTE'
cd /opt/pingql
git checkout -- apps/web/src/dashboard/tailwind.css
git fetch origin && git reset --hard origin/main
cd apps/web
/root/.bun/bin/bun install
/root/.bun/bin/bun run css
systemctl restart pingql-web
systemctl restart caddy
echo "Web deployed and restarted"
REMOTE
}
deploy_status() {
echo "[status] Deploying to status-eu-central..."
$SSH $STATUS_HOST bash << 'REMOTE'
cd /opt/pingql
git fetch origin && git reset --hard origin/main
cd apps/status
/root/.bun/bin/bun install
systemctl restart pingql-status
systemctl restart caddy
echo "Status deployed and restarted"
REMOTE
}
deploy_monitor() {
echo "[monitor] Deploying to all 4 monitors in parallel..."
for host in "${MONITOR_HOSTS[@]}"; do
(
echo "[monitor] Starting deploy on $host..."
$SSH $host bash << 'REMOTE'
cd /opt/pingql
git fetch origin && git reset --hard origin/main
cd apps/monitor
/root/.cargo/bin/cargo build --release
systemctl restart pingql-monitor
echo "Monitor deployed and restarted on $(hostname)"
REMOTE
) &
done
wait
echo "[monitor] All monitors deployed"
}
stop_app() {
local app="$1"
case "$app" in
api)
echo "[stop] Stopping pingql-api on api-eu-central..."
$SSH $API_HOST "systemctl stop pingql-api && echo 'pingql-api stopped'"
;;
pay)
echo "[stop] Stopping pingql-pay on api-eu-central..."
$SSH $API_HOST "systemctl stop pingql-pay && echo 'pingql-pay stopped'"
;;
web)
echo "[stop] Stopping pingql-web on web-eu-central..."
$SSH $WEB_HOST "systemctl stop pingql-web && echo 'pingql-web stopped'"
;;
status)
echo "[stop] Stopping pingql-status on status-eu-central..."
$SSH $STATUS_HOST "systemctl stop pingql-status && echo 'pingql-status stopped'"
;;
monitor)
echo "[stop] Stopping monitors on all hosts..."
for host in "${MONITOR_HOSTS[@]}"; do
($SSH "$host" 'systemctl stop pingql-monitor && echo "pingql-monitor stopped on $(hostname)"') &
done
wait
;;
all)
stop_app api; stop_app pay; stop_app web; stop_app status; stop_app monitor
;;
*)
echo "Unknown app: $app (valid: api, pay, web, status, monitor, all)"
return 1
;;
esac
}
# Parse args — supports both "./deploy.sh web api" and "./deploy.sh web,api"
if [ $# -eq 0 ]; then
echo "Usage: $0 [web|api|pay|status|monitor|db|all] [...]"
echo " $0 stop [api|pay|web|status|monitor|all]"
echo " $0 web,api,status (comma-separated)"
exit 1
fi
# Handle "stop" action
if [ "$1" = "stop" ]; then
shift
if [ $# -eq 0 ]; then
echo "Usage: $0 stop [api|pay|web|status|monitor|all]"
exit 1
fi
for arg in "$@"; do
IFS=',' read -ra targets <<< "$arg"
for target in "${targets[@]}"; do
stop_app "$target"
done
done
echo "Stop complete."
exit 0
fi
sync_time() {
echo "[sync] Syncing time on all servers..."
ALL_HOSTS=("$DB_HOST" "$API_HOST" "$WEB_HOST" "$STATUS_HOST" "${MONITOR_HOSTS[@]}")
for host in "${ALL_HOSTS[@]}"; do
(
$SSH "$host" "chronyc makestep 2>/dev/null || ntpdate -s pool.ntp.org 2>/dev/null || timedatectl set-ntp true 2>/dev/null; echo \"$(hostname 2>/dev/null || echo $host): $(date -u +%H:%M:%S.%N)\""
) &
done
wait
echo "[sync] All servers synced"
}
deploy_target() {
case "$1" in
db) deploy_db ;;
api) deploy_api ;;
pay) deploy_pay ;;
web) deploy_web ;;
status) deploy_status ;;
monitor) deploy_monitor ;;
nuke-db) nuke_db ;;
sync) sync_time ;;
all) deploy_db; deploy_api; deploy_pay; deploy_web; deploy_status; deploy_monitor ;;
*) echo "Unknown target: $1 (valid: web, api, pay, status, monitor, db, nuke-db, sync, all)"; exit 1 ;;
esac
}
for arg in "$@"; do
IFS=',' read -ra targets <<< "$arg"
for target in "${targets[@]}"; do
deploy_target "$target"
done
done
echo "Deploy complete."