Add deployment/setup-pve201.sh — one-shot Phase B host bootstrap

Idempotent: installs systemd tunnel unit, smoke-tests it, writes the
nginx vhost + htpasswd, reloads nginx. Reads BASIC_AUTH_USER/PASS from
env (use sudo -E).
This commit is contained in:
2026-04-27 12:06:32 +03:00
parent 03eeddfbf8
commit 894113e09d
+129
View File
@@ -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=<pw> 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}:<pw> -I https://ui-dashboard.gnerim.ru/ # expect 502 until container is deployed (Workflow A)"
echo " curl -u ${BASIC_AUTH_USER}:<pw> -I https://ui-dashboard.gnerim.ru/api/health # expect 200 from real upstream"