llm-gateway/deploy/setup-erik.sh
Rene Fichtmueller 200cc7f2dc fix: Correct Cloudflare tunnel and setup script to use port 3103
The LLM Gateway is configured to run on port 3103 in ecosystem.config.cjs,
but the Cloudflare tunnel configuration and setup script were referencing port
3100, causing 502 Bad Gateway errors.

Updates:
- cloudflare-tunnel.md: Changed tunnel ingress from localhost:3100 to localhost:3103
- setup-erik.sh: Updated health check URL and output messages to port 3103
- This fixes the Cloudflare tunnel connection that was causing public HTTPS access to fail

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-26 21:04:36 +02:00

196 lines
6.8 KiB
Bash
Executable File

#!/bin/bash
# ============================================================
# LLM Gateway — Full server setup for Erik (82.165.222.127)
#
# Run ONCE on a fresh server. Idempotent: safe to re-run.
# Prerequisites: PostgreSQL 17, Node.js 22, git, pm2
# ============================================================
set -euo pipefail
GATEWAY_DIR="/opt/llm-gateway"
LOG_DIR="/var/log/llm-gateway"
GITEA_REPO="http://gitea.context-x.org/rene/llm-gateway.git"
DB_NAME="llm_gateway"
DB_USER="llm"
DB_PASS="llm_secure_password"
PM2_USER="${SUDO_USER:-root}"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
section() { echo -e "\n${GREEN}==============================${NC}"; echo -e "${GREEN}$*${NC}"; echo -e "${GREEN}==============================${NC}"; }
# -------------------------------------------------------
# 0. Preflight checks
# -------------------------------------------------------
section "0. Preflight checks"
[[ $EUID -eq 0 ]] || error "Run as root: sudo bash deploy/setup-erik.sh"
command -v node >/dev/null || error "Node.js not found. Install Node.js 22 first."
command -v npm >/dev/null || error "npm not found."
command -v psql >/dev/null || error "psql not found. Install PostgreSQL 17 first."
command -v pm2 >/dev/null || error "pm2 not found. Run: npm install -g pm2"
command -v git >/dev/null || error "git not found."
NODE_VER=$(node --version | cut -d. -f1 | tr -d 'v')
[[ $NODE_VER -ge 22 ]] || warn "Node.js 22+ recommended. Found: $(node --version)"
info "All preflight checks passed."
# -------------------------------------------------------
# 1. Create application directory
# -------------------------------------------------------
section "1. Creating application directory"
if [[ -d "$GATEWAY_DIR" ]]; then
warn "$GATEWAY_DIR already exists — skipping git clone (will pull later)"
else
git clone "$GITEA_REPO" "$GATEWAY_DIR"
info "Cloned repository to $GATEWAY_DIR"
fi
cd "$GATEWAY_DIR"
# -------------------------------------------------------
# 2. Create log directory
# -------------------------------------------------------
section "2. Creating log directory"
mkdir -p "$LOG_DIR"
chown -R "$PM2_USER:$PM2_USER" "$LOG_DIR" 2>/dev/null || true
info "Log directory: $LOG_DIR"
# -------------------------------------------------------
# 3. PostgreSQL — database + user + migrations
# -------------------------------------------------------
section "3. Setting up PostgreSQL"
# Create user if not exists
if sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" | grep -q 1; then
info "PostgreSQL user '$DB_USER' already exists."
else
sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASS';"
info "Created PostgreSQL user '$DB_USER'."
fi
# Create database if not exists
if sudo -u postgres psql -tAc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" | grep -q 1; then
info "Database '$DB_NAME' already exists."
else
sudo -u postgres psql -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;"
info "Created database '$DB_NAME'."
fi
# Run migrations
info "Running migrations..."
MIGRATION_DIR="$GATEWAY_DIR/packages/gateway/src/db/migrations"
if [[ -d "$MIGRATION_DIR" ]]; then
for sql_file in "$MIGRATION_DIR"/*.sql; do
[[ -f "$sql_file" ]] || continue
filename=$(basename "$sql_file")
info " Applying migration: $filename"
PGPASSWORD="$DB_PASS" psql -U "$DB_USER" -d "$DB_NAME" -h localhost -f "$sql_file" \
&& info "$filename" \
|| warn " Migration $filename may have already been applied (ignoring error)"
done
else
warn "Migration directory not found at $MIGRATION_DIR — skipping migrations"
fi
# Learning engine migrations
LEARNING_MIGRATION_DIR="$GATEWAY_DIR/packages/learning/src/db/migrations"
if [[ -d "$LEARNING_MIGRATION_DIR" ]]; then
for sql_file in "$LEARNING_MIGRATION_DIR"/*.sql; do
[[ -f "$sql_file" ]] || continue
filename=$(basename "$sql_file")
info " Applying learning migration: $filename"
PGPASSWORD="$DB_PASS" psql -U "$DB_USER" -d "$DB_NAME" -h localhost -f "$sql_file" \
&& info "$filename" \
|| warn " Migration $filename may have already been applied (ignoring error)"
done
fi
# -------------------------------------------------------
# 4. npm install + build
# -------------------------------------------------------
section "4. Installing dependencies and building"
cd "$GATEWAY_DIR"
npm install
npm run build
info "Build complete."
# -------------------------------------------------------
# 5. PM2 — register and start processes
# -------------------------------------------------------
section "5. Starting PM2 processes"
# If already registered, reload; otherwise start fresh
if pm2 list | grep -q "llm-gateway"; then
info "PM2 process 'llm-gateway' exists — reloading..."
pm2 reload llm-gateway
else
info "Starting PM2 processes from ecosystem config..."
pm2 start "$GATEWAY_DIR/deploy/ecosystem.config.cjs"
fi
# Save PM2 state so it survives reboots
pm2 save
# Register PM2 startup script (only if not already done)
if ! systemctl is-enabled pm2-root &>/dev/null 2>&1 && ! systemctl is-enabled "pm2-$PM2_USER" &>/dev/null 2>&1; then
info "Registering PM2 startup hook..."
pm2 startup systemd -u "$PM2_USER" --hp "/root" | tail -1 | bash || true
fi
# -------------------------------------------------------
# 6. Health check
# -------------------------------------------------------
section "6. Health check"
info "Waiting 5s for gateway to start..."
sleep 5
MAX_RETRIES=10
RETRY_DELAY=3
HEALTH_URL="http://localhost:3103/health"
for i in $(seq 1 $MAX_RETRIES); do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$HEALTH_URL" 2>/dev/null || echo "000")
if [[ "$STATUS" == "200" ]]; then
info "Health check PASSED (HTTP 200)"
break
fi
if [[ $i -eq $MAX_RETRIES ]]; then
warn "Health check did not return 200 after ${MAX_RETRIES} attempts (got: $STATUS)"
warn "Check logs: pm2 logs llm-gateway"
else
info " Attempt $i/$MAX_RETRIES — got HTTP $STATUS, retrying in ${RETRY_DELAY}s..."
sleep $RETRY_DELAY
fi
done
# -------------------------------------------------------
# 7. Summary
# -------------------------------------------------------
section "Setup complete"
echo ""
echo " Gateway: http://localhost:3103"
echo " Health: http://localhost:3103/health"
echo " Logs: pm2 logs llm-gateway"
echo " PM2 UI: pm2 monit"
echo ""
echo " Next steps:"
echo " 1. Add Cloudflare tunnel ingress (see deploy/cloudflare-tunnel.md)"
echo " 2. Pull Ollama models: bash scripts/pull-models.sh"
echo " 3. Verify: curl http://localhost:3103/health"
echo ""