#!/usr/bin/env bash # bootstrap_glitchtip.sh # One-shot bootstrap for GlitchTip on the VPS. # # Run ONCE manually after merging feat/204-glitchtip-infra. # Do NOT add to deploy.yml — this is idempotent setup, not a recurring step. # # Usage (on VPS via SSH): # cd /opt/gendesign # # Ensure GLITCHTIP_DB_PASS and GLITCHTIP_SECRET are set in .env # bash scripts/bootstrap_glitchtip.sh # # After running: # 1. docker compose -p gendesign -f docker-compose.prod.yml exec glitchtip-web ./manage.py createsuperuser # 2. Log in to https://errors.gendsgn.ru → create org "gendesign" # 3. Create projects: "backend", "frontend" # 4. Copy DSNs → add to /opt/gendesign/backend/.env (GLITCHTIP_DSN) # and /opt/gendesign/frontend/.env or .env.runtime (NEXT_PUBLIC_GLITCHTIP_DSN) # 5. Recreate affected containers: # docker compose -p gendesign -f docker-compose.prod.yml up -d --force-recreate --no-deps backend set -euo pipefail COMPOSE_FILE="docker-compose.prod.yml" COMPOSE_PROJECT="gendesign" COMPOSE="docker compose -p $COMPOSE_PROJECT -f $COMPOSE_FILE" # ── Load .env.runtime for GLITCHTIP_DB_PASS / POSTGRES_* ────────────────── if [ -f ".env" ]; then set -a; source .env; set +a fi if [ -f "backend/.env.runtime" ]; then set -a; source backend/.env.runtime; set +a fi : "${GLITCHTIP_DB_PASS:?GLITCHTIP_DB_PASS not set — add to .env or export}" : "${POSTGRES_USER:?POSTGRES_USER not set}" : "${POSTGRES_PASSWORD:?POSTGRES_PASSWORD not set}" : "${POSTGRES_DB:?POSTGRES_DB not set}" echo "==> Ensuring postgres service is healthy..." for i in $(seq 1 30); do if $COMPOSE exec -T postgres pg_isready -U "$POSTGRES_USER" -q; then break fi echo " Waiting for postgres... ($i/30)" sleep 2 done # ── Create glitchtip DB + user (idempotent) ──────────────────────────────── # psql var :'gt_pass' НЕ подставляется внутри DO $$..$$ — тело dollar-quote # уходит на сервер as-is. Используем \gexec в psql-стриме client-side. # # \gexec builds SQL client-side via quote_literal(:'gt_pass'), then executes it. # quote_literal escapes apostrophes and backslashes — no SQL injection possible. # If WHERE NOT EXISTS filters the row, \gexec receives no input → no-op, no error. # ON_ERROR_STOP=1 ensures \gexec-executed statements also cause psql to exit non-zero. echo "==> Creating glitchtip database and user (idempotent)..." $COMPOSE exec -T postgres \ psql -U "$POSTGRES_USER" -d postgres \ -v ON_ERROR_STOP=1 \ -v "gt_pass=$GLITCHTIP_DB_PASS" <<'SQL' SELECT 'CREATE ROLE glitchtip LOGIN PASSWORD ' || quote_literal(:'gt_pass') || ';' WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'glitchtip') \gexec SELECT 'CREATE DATABASE glitchtip OWNER glitchtip;' WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'glitchtip') \gexec GRANT ALL PRIVILEGES ON DATABASE glitchtip TO glitchtip; SQL # ── Start GlitchTip containers ───────────────────────────────────────────── # glitchtip-web and glitchtip-worker carry `profiles: ["glitchtip"]` in compose, # so plain `up -d` skips them. Activate the profile explicitly here. # After bootstrap succeeds, add COMPOSE_PROFILES=glitchtip to /opt/gendesign/.env # so that future automatic deploys also bring these services up. echo "==> Pulling glitchtip image..." $COMPOSE --profile glitchtip pull glitchtip-web glitchtip-worker echo "==> Starting glitchtip-web and glitchtip-worker..." $COMPOSE --profile glitchtip up -d glitchtip-web glitchtip-worker echo "" echo "NOTE: Add the following line to /opt/gendesign/.env so future deploys" echo " keep GlitchTip running:" echo " COMPOSE_PROFILES=glitchtip" # ── Wait for glitchtip-web to become healthy ─────────────────────────────── # Use wget (available in glitchtip image) matching the compose healthcheck probe. echo "==> Waiting for glitchtip-web to become healthy (up to 60s)..." for i in $(seq 1 30); do if $COMPOSE exec -T glitchtip-web wget -q --spider http://localhost:8080/api/0/ >/dev/null 2>&1; then echo " glitchtip-web is healthy." break fi echo " Waiting... ($i/30)" sleep 2 done echo "" echo "==> Bootstrap complete." echo "" echo "Next steps:" echo " 1. Create superuser:" echo " $COMPOSE exec glitchtip-web ./manage.py createsuperuser" echo "" echo " 2. Log in to https://errors.gendsgn.ru" echo " - Create organization: gendesign" echo " - Create project: backend (Platform: Python)" echo " - Create project: frontend (Platform: JavaScript / Browser)" echo "" echo " 3. Copy DSNs from each project's Settings → DSN" echo " - Add GLITCHTIP_DSN= to /opt/gendesign/backend/.env" echo " - Add NEXT_PUBLIC_GLITCHTIP_DSN= to /opt/gendesign/backend/.env or .env" echo "" echo " 4. Recreate services to pick up new DSNs:" echo " $COMPOSE up -d --force-recreate --no-deps backend" echo " $COMPOSE up -d --force-recreate --no-deps worker beat" echo "" echo " 5. Verify: trigger a test exception and confirm it appears in GlitchTip."