#!/usr/bin/env bash # deploy.sh — build and deploy PWA + backend to Uberspace 8 # Usage: ./deploy.sh [uberspace-user@host] (default: serve) set -euo pipefail # activate mise so tool versions (bun, etc.) from .mise.toml are on $PATH eval "$(mise activate bash --shims)" REMOTE="${1:-serve}" LOCAL_DIR="$(cd "$(dirname "$0")" && pwd)" # reuse a single SSH connection to avoid rate limiting SSH_SOCK="/tmp/deploy-ssh-$$" ssh -fNM -o ControlMaster=yes -S "$SSH_SOCK" "$REMOTE" trap 'ssh -S "$SSH_SOCK" -O exit "$REMOTE" 2>/dev/null' EXIT r() { ssh -S "$SSH_SOCK" "$REMOTE" "$@"; } REMOTE_USER=$(r 'echo $USER') REMOTE_AGW_DIR="/var/www/virtual/$REMOTE_USER/html/agw" REMOTE_SERVICE_DIR="/home/$REMOTE_USER/services/agw-backend" SERVICE_NAME="agw-backend" BACKEND_PORT=3002 # --- PWA --- echo "==> Building PWA" cd "$LOCAL_DIR" bun install --frozen-lockfile bun run build echo "==> Deploying static files to $REMOTE:$REMOTE_AGW_DIR" r "mkdir -p $REMOTE_AGW_DIR" rsync -avz --delete -e "ssh -S $SSH_SOCK" \ "$LOCAL_DIR/dist/" "$REMOTE:$REMOTE_AGW_DIR/" # --- Backend --- echo "==> Deploying backend to $REMOTE:$REMOTE_SERVICE_DIR" r "mkdir -p $REMOTE_SERVICE_DIR" rsync -avz --delete -e "ssh -S $SSH_SOCK" \ --exclude='.git/' \ --exclude='.env' \ --exclude='dist/' \ --exclude='node_modules/' \ --exclude='.DS_Store' \ "$LOCAL_DIR/" "$REMOTE:$REMOTE_SERVICE_DIR/" echo "==> Installing backend dependencies" r "cd $REMOTE_SERVICE_DIR && bun install" echo "==> Checking .env exists" r "test -f $REMOTE_SERVICE_DIR/.env || { echo 'ERROR: $REMOTE_SERVICE_DIR/.env not found — create it first'; exit 1; }" echo "==> Running database migrations" r "cd $REMOTE_SERVICE_DIR && set -a && source .env && set +a && bunx drizzle-kit migrate" # --- systemd user service (Uberspace 8) --- echo "==> Configuring systemd user service" r "mkdir -p ~/.config/systemd/user && cat > ~/.config/systemd/user/$SERVICE_NAME.service << EOF [Unit] Description=Abgeordnetenwatch Backend After=network.target postgresql.service [Service] Type=simple WorkingDirectory=$REMOTE_SERVICE_DIR EnvironmentFile=$REMOTE_SERVICE_DIR/.env ExecStart=/usr/bin/bun run src/server/index.ts Restart=on-failure RestartSec=5 [Install] WantedBy=default.target EOF" echo "==> Restarting backend service" r "systemctl --user daemon-reload && systemctl --user enable $SERVICE_NAME && systemctl --user restart $SERVICE_NAME" sleep 2 r "systemctl --user status $SERVICE_NAME --no-pager" || true # --- Web backend (reverse proxy) --- echo "==> Configuring web backend for /agw/api/" r "uberspace web backend add /agw/api PORT $BACKEND_PORT --remove-prefix --force --wait" 2>/dev/null || true echo "" echo "Done." echo " PWA: https://$REMOTE_USER.uber.space/agw/" echo " Backend: https://$REMOTE_USER.uber.space/agw/api/"