diff --git a/deployment/setup-pve201.sh b/deployment/setup-pve201.sh new file mode 100755 index 00000000..ed485e69 --- /dev/null +++ b/deployment/setup-pve201.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +# setup-pve201.sh — one-shot Phase B host setup. Run on pve-201 from the repo root. +# +# Usage (run on pve-201, in the repo root, on branch chore/tim-tunnel-routing): +# BASIC_AUTH_USER=front BASIC_AUTH_PASS= sudo -E bash deployment/setup-pve201.sh +# +# What it does (idempotent — safe to re-run): +# 1. Installs flights-tim-tunnel.service systemd unit and brings it up. +# 2. Smoke-tests the tunnel (curl to flights.test.aeroflot.ru via 127.0.0.1:8443). +# 3. Installs the new ui-dashboard.gnerim.ru nginx vhost + htpasswd dir. +# 4. Renders /etc/nginx/htpasswd/ui-dashboard from BASIC_AUTH_USER/PASS. +# 5. Reloads nginx after `nginx -t` passes. +# +# Each step prints a heading and exits non-zero on failure. Re-running after a +# fix continues where it failed (everything is overwrite-safe). +set -euo pipefail + +if [ "$(id -u)" -ne 0 ]; then + echo "fatal: run as root (sudo -E bash $0)" >&2 + exit 2 +fi + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" + +step() { printf '\n=== %s ===\n' "$*"; } +ok() { printf ' ok: %s\n' "$*"; } +fail() { printf ' FAIL: %s\n' "$*" >&2; exit 1; } + +# ---------- 1. systemd unit ---------- +step "1. flights-tim-tunnel.service" + +UNIT_SRC="$REPO_ROOT/deployment/systemd/flights-tim-tunnel.service" +UNIT_DST="/etc/systemd/system/flights-tim-tunnel.service" +[ -f "$UNIT_SRC" ] || fail "missing $UNIT_SRC — wrong branch?" + +if [ -f "$UNIT_DST" ] && cmp -s "$UNIT_SRC" "$UNIT_DST"; then + ok "$UNIT_DST already up-to-date" +else + cp "$UNIT_SRC" "$UNIT_DST" + ok "installed $UNIT_DST" +fi + +systemctl daemon-reload +systemctl enable --now flights-tim-tunnel.service +sleep 2 +systemctl is-active flights-tim-tunnel.service >/dev/null \ + || { systemctl status flights-tim-tunnel.service --no-pager; fail "tunnel unit not active"; } +ok "unit active" + +# ---------- 2. tunnel smoke test ---------- +step "2. tunnel smoke test" + +ss -ltn | grep -qE '127\.0\.0\.1:8443\s' || fail "no listener on 127.0.0.1:8443" +ok "listener present" + +SWAGGER_RC=$(curl -sS -k --max-time 10 -o /dev/null -w "%{http_code}" \ + --resolve flights.test.aeroflot.ru:8443:127.0.0.1 \ + https://flights.test.aeroflot.ru:8443/swagger/index.html) +if [ "$SWAGGER_RC" = "401" ]; then + ok "swagger HTTP 401 (real backend, WAF passed)" +elif [ "$SWAGGER_RC" = "200" ]; then + fail "swagger HTTP 200 — likely WAF interstitial (tunnel bypassed)" +else + fail "swagger unexpected HTTP $SWAGGER_RC" +fi + +API_RC=$(curl -sS -k --max-time 10 -o /dev/null -w "%{http_code}" \ + --resolve flights.test.aeroflot.ru:8443:127.0.0.1 \ + https://flights.test.aeroflot.ru:8443/api/health) +[ "$API_RC" = "200" ] && ok "api/health HTTP 200" || fail "api/health HTTP $API_RC" + +# ---------- 3. nginx vhost ---------- +step "3. nginx vhost" + +VHOST_SRC="$REPO_ROOT/deployment/nginx/ui-dashboard.gnerim.ru.conf" +VHOST_DST="/etc/nginx/sites-available/ui-dashboard.gnerim.ru" +[ -f "$VHOST_SRC" ] || fail "missing $VHOST_SRC" + +if [ -f "$VHOST_DST" ] && cmp -s "$VHOST_SRC" "$VHOST_DST"; then + ok "$VHOST_DST already up-to-date" +else + if [ -f "$VHOST_DST" ]; then + BAK="${VHOST_DST}.bak.$(date +%Y%m%d-%H%M%S)" + cp "$VHOST_DST" "$BAK" + ok "backed up old vhost to $BAK" + fi + cp "$VHOST_SRC" "$VHOST_DST" + ok "installed $VHOST_DST" +fi + +ENABLED="/etc/nginx/sites-enabled/ui-dashboard.gnerim.ru" +if [ ! -L "$ENABLED" ]; then + ln -sf "$VHOST_DST" "$ENABLED" + ok "created sites-enabled symlink" +else + ok "sites-enabled symlink already present" +fi + +mkdir -p /etc/nginx/htpasswd +ok "/etc/nginx/htpasswd ensured" + +# ---------- 4. htpasswd ---------- +step "4. htpasswd" + +: "${BASIC_AUTH_USER:?BASIC_AUTH_USER required (export it before sudo -E)}" +: "${BASIC_AUTH_PASS:?BASIC_AUTH_PASS required (export it before sudo -E)}" + +HASH=$(openssl passwd -apr1 "$BASIC_AUTH_PASS") +HTPASSWD_PATH="/etc/nginx/htpasswd/ui-dashboard" +echo "${BASIC_AUTH_USER}:${HASH}" > "$HTPASSWD_PATH" +chmod 644 "$HTPASSWD_PATH" +ok "wrote $HTPASSWD_PATH" + +# ---------- 5. nginx reload ---------- +step "5. nginx -t + reload" + +nginx -t +systemctl reload nginx +ok "nginx reloaded" + +# ---------- summary ---------- +step "done" +echo "Tunnel: $(systemctl is-active flights-tim-tunnel.service)" +echo "Nginx: $(systemctl is-active nginx)" +echo +echo "Try:" +echo " curl -u ${BASIC_AUTH_USER}: -I https://ui-dashboard.gnerim.ru/ # expect 502 until container is deployed (Workflow A)" +echo " curl -u ${BASIC_AUTH_USER}: -I https://ui-dashboard.gnerim.ru/api/health # expect 200 from real upstream"