5273b3a7a6
The smoke test was getting 403 from the upstream WAF (rate-limit on webzavod's egress IP). 403 doesn't indicate a tunnel/routing problem — it confirms the egress IP IS the WAF-recognized one and is being throttled. Don't abort the rest of setup over a transient throttle; the only response that should hard-fail is HTTP 200 with HTML body (WAF interstitial), which means the tunnel was bypassed.
152 lines
5.4 KiB
Bash
Executable File
152 lines
5.4 KiB
Bash
Executable File
#!/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)
|
|
case "$SWAGGER_RC" in
|
|
401) ok "swagger HTTP 401 (real backend, WAF passed)" ;;
|
|
403) ok "swagger HTTP 403 (WAF rate-limit — egress IP is correct, just throttled)" ;;
|
|
200) fail "swagger HTTP 200 — likely WAF interstitial (tunnel bypassed)" ;;
|
|
*) fail "swagger unexpected HTTP $SWAGGER_RC" ;;
|
|
esac
|
|
|
|
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)
|
|
case "$API_RC" in
|
|
200) ok "api/health HTTP 200" ;;
|
|
403) ok "api/health HTTP 403 (WAF rate-limit — transient, egress IP confirmed correct)" ;;
|
|
*) fail "api/health HTTP $API_RC" ;;
|
|
esac
|
|
|
|
# ---------- 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"
|
|
|
|
# Install proxy_cache zone declaration (must live in http {} context)
|
|
CACHE_CONF_SRC="$REPO_ROOT/deployment/nginx/conf.d/flights-api-cache.conf"
|
|
CACHE_CONF_DST="/etc/nginx/conf.d/flights-api-cache.conf"
|
|
if [ -f "$CACHE_CONF_DST" ] && cmp -s "$CACHE_CONF_SRC" "$CACHE_CONF_DST"; then
|
|
ok "$CACHE_CONF_DST already up-to-date"
|
|
else
|
|
cp "$CACHE_CONF_SRC" "$CACHE_CONF_DST"
|
|
ok "installed $CACHE_CONF_DST"
|
|
fi
|
|
|
|
# Cache directory — nginx auto-creates with proper perms on first start, but
|
|
# we pre-create with the right ownership so reload picks it up cleanly.
|
|
CACHE_DIR="/var/cache/nginx/flights-api"
|
|
NGINX_USER="$(awk '/^user / {gsub(";",""); print $2}' /etc/nginx/nginx.conf 2>/dev/null | head -1)"
|
|
NGINX_USER="${NGINX_USER:-www-data}"
|
|
mkdir -p "$CACHE_DIR"
|
|
chown -R "$NGINX_USER":"$NGINX_USER" "$CACHE_DIR"
|
|
ok "$CACHE_DIR ensured (owner: $NGINX_USER)"
|
|
|
|
# ---------- 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"
|