Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
Made-with: Cursor
102 lines
4.3 KiB
Bash
Executable File
102 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Install nginx on MIM4U web container (VMID 7810) and apply security-enabled config to fix 502.
|
|
# Run from a host that can SSH to the Proxmox node (e.g. r630-02). Requires root on Proxmox.
|
|
#
|
|
# Usage: ./scripts/mim4u-install-nginx-and-fix-502.sh [--dry-run]
|
|
# Optional: set PROXMOX_HOST_R630_02 and MIM_API_IP in env or config/ip-addresses.conf
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
[[ -f "$PROJECT_ROOT/config/ip-addresses.conf" ]] && source "$PROJECT_ROOT/config/ip-addresses.conf" 2>/dev/null || true
|
|
|
|
VMID_MIM_WEB="${VMID_MIM_WEB:-7810}"
|
|
PROXMOX_HOST="${PROXMOX_HOST_R630_02:-192.168.11.12}"
|
|
# API backend (VMID 7811) for /api/ proxy
|
|
MIM_API_IP="${MIM_API_IP:-192.168.11.36}"
|
|
MIM_API_PORT="${MIM_API_PORT:-3001}"
|
|
DRY_RUN="${1:-}"
|
|
|
|
run_remote() {
|
|
if [[ "$DRY_RUN" == "--dry-run" ]]; then
|
|
echo "[dry-run] ssh root@$PROXMOX_HOST pct exec $VMID_MIM_WEB -- $*"
|
|
return 0
|
|
fi
|
|
ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new "root@$PROXMOX_HOST" "pct exec $VMID_MIM_WEB -- $*"
|
|
}
|
|
|
|
echo "=== MIM4U 502 fix: install nginx on VMID $VMID_MIM_WEB (Proxmox $PROXMOX_HOST) ==="
|
|
echo "API backend: $MIM_API_IP:$MIM_API_PORT"
|
|
echo ""
|
|
|
|
# 1) Install nginx if missing
|
|
echo "[1/4] Installing nginx..."
|
|
run_remote bash -c 'export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install -y -qq nginx' 2>/dev/null || true
|
|
|
|
# 2a) Rate limit zones (http context via conf.d)
|
|
echo "[2/4] Writing nginx config (site + rate limit)..."
|
|
RATE_LIMIT_CONF='# MIM4U rate limits (included from main nginx.conf)
|
|
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
|
|
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/s;
|
|
'
|
|
if [[ "$DRY_RUN" != "--dry-run" ]]; then
|
|
echo "$RATE_LIMIT_CONF" | ssh "root@$PROXMOX_HOST" "pct exec $VMID_MIM_WEB -- bash -c 'cat > /etc/nginx/conf.d/mim4u-rate-limit.conf'"
|
|
fi
|
|
|
|
# 2b) Write nginx site config (security headers + SPA + /api proxy)
|
|
# CSP: font-src 'self' only (Inter is self-hosted via @fontsource)
|
|
NGINX_CONF="server {
|
|
listen 80;
|
|
server_name mim4u.org www.mim4u.org secure.mim4u.org training.mim4u.org _;
|
|
root /var/www/html;
|
|
index index.html;
|
|
|
|
add_header X-Content-Type-Options \"nosniff\" always;
|
|
add_header X-Frame-Options \"SAMEORIGIN\" always;
|
|
add_header X-XSS-Protection \"1; mode=block\" always;
|
|
add_header Referrer-Policy \"strict-origin-when-cross-origin\" always;
|
|
add_header Content-Security-Policy \"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; font-src 'self'; img-src 'self' data: https:; connect-src 'self' https://mim4u.org; frame-ancestors 'self';\" always;
|
|
|
|
location /health {
|
|
default_type text/plain;
|
|
return 200 'ok';
|
|
add_header Content-Type text/plain;
|
|
}
|
|
|
|
location / {
|
|
limit_req zone=general burst=20 nodelay;
|
|
try_files \$uri \$uri/ /index.html =404;
|
|
}
|
|
|
|
location /api/ {
|
|
limit_req zone=api burst=5 nodelay;
|
|
proxy_pass http://${MIM_API_IP}:${MIM_API_PORT};
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
|
}
|
|
}"
|
|
|
|
if [[ "$DRY_RUN" != "--dry-run" ]]; then
|
|
echo "$NGINX_CONF" | ssh "root@$PROXMOX_HOST" "pct exec $VMID_MIM_WEB -- bash -c 'cat > /etc/nginx/sites-available/default'"
|
|
fi
|
|
|
|
# 3) Ensure /var/www/html exists and has index (placeholder if no app deployed yet)
|
|
echo "[3/4] Ensuring web root..."
|
|
run_remote mkdir -p /var/www/html
|
|
run_remote bash -c 'test -f /var/www/html/index.html || cat >/var/www/html/index.html <<END
|
|
<!DOCTYPE html><html><head><title>MIM4U</title></head><body><p>Miracles in Motion - site coming soon.</p></body></html>
|
|
END'
|
|
|
|
# 4) Test and reload nginx
|
|
echo "[4/4] Testing and reloading nginx..."
|
|
run_remote nginx -t 2>/dev/null && run_remote systemctl enable nginx 2>/dev/null || true
|
|
run_remote systemctl reload nginx 2>/dev/null || run_remote systemctl start nginx 2>/dev/null || true
|
|
|
|
MIM_WEB_IP="${IP_MIM_WEB:-192.168.11.37}"
|
|
echo ""
|
|
echo "Done. Verify from LAN: curl -I http://${MIM_WEB_IP}:80/"
|
|
echo "Then ensure NPMplus proxy hosts point to ${MIM_WEB_IP} (see docs/04-configuration/MIM4U_502_ERROR_RESOLUTION.md)."
|