# MIM4U 502 Error Resolution Guide **Last Updated:** 2026-01-31 **Document Version:** 1.0 **Status:** Active Documentation --- **Date**: 2026-01-18 **Issue**: `https://mim4u.org/` returns HTTP 502 Bad Gateway **Status**: ⚠️ **RESOLUTION IN PROGRESS** --- ## Root Cause Analysis ### Current Situation 1. **VMID 7810 (mim-web-1) @ 192.168.11.37**: - ✅ Container is running - ❌ **nginx is NOT installed** - ❌ **No web service on port 80** 2. **VMID 7811 (mim-api-1) @ 192.168.11.36**: - ✅ Container is running - ❌ **No web service on port 80** - ❌ **Port 80 not accessible** 3. **NPMplus Configuration**: - ⚠️ Likely routing to old IP (192.168.11.36) OR - ⚠️ Routing to 192.168.11.37 but no service responding --- ## 502 Error Explanation **HTTP 502 Bad Gateway** means: - NPMplus received the request - NPMplus tried to proxy to backend (192.168.11.36 or 192.168.11.37) - Backend service is not responding or not accessible --- ## Solution Steps ### Step 1: Install nginx on VMID 7810 The container needs nginx installed and running to serve the web application. **Option A — run the fix script (recommended):** From a host that can SSH to the Proxmox node (r630-02): ```bash ./scripts/mim4u-install-nginx-and-fix-502.sh # Or dry-run: ./scripts/mim4u-install-nginx-and-fix-502.sh --dry-run ``` The script installs nginx, writes the security-enabled config (including rate limits in `/etc/nginx/conf.d/mim4u-rate-limit.conf` and the default site), ensures `/var/www/html` exists, and reloads nginx. **Option B — manual steps:** ```bash # SSH to Proxmox host ssh root@192.168.11.12 # Install nginx in container pct exec 7810 -- bash -c 'export DEBIAN_FRONTEND=noninteractive && apt-get update && apt-get install -y nginx' # Start nginx pct exec 7810 -- systemctl enable nginx pct exec 7810 -- systemctl start nginx # Verify curl -I http://192.168.11.37:80/ ``` ### Step 2: Verify NPMplus Routing Check what IP NPMplus is routing to: 1. **Access NPMplus Web UI**: - URL: `https://192.168.0.166:81` or `https://192.168.11.166:81` - Navigate to: Proxy Hosts → `mim4u.org` (and `www.mim4u.org`) 2. **Verify Configuration**: - Forward Hostname/IP: Should be `192.168.11.37` - Forward Port: Should be `80` - Forward Scheme: Should be `http` - **www.mim4u.org**: Same backend so both apex and www work. Optional: create a Redirect host for `www.mim4u.org` → `https://mim4u.org` in NPMplus to canonicalize to apex. 3. **Security (HSTS / SSL)**: - Enable **SSL** and **Force SSL** for mim4u.org (and www, secure, training) so HTTPS is used. - Enable **HSTS** in the proxy host’s SSL tab so browsers get `Strict-Transport-Security`. NPMplus adds the header when terminating SSL. ### Step 3: Deploy MIM4U Web Application (When Ready) Once nginx is running, deploy the actual MIM4U web application: - Application files go in: `/opt/miracles-in-motion/dist` (or configured path) - Nginx config: `/etc/nginx/sites-available/miracles-in-motion` - nginx should serve static files and proxy `/api/*` to VMID 7811 --- ## Quick Fix (Temporary) If you need the site working immediately, you can: 1. **Install nginx** on VMID 7810 (see Step 1 above) 2. **Configure basic nginx** to serve a default page: ```bash # Basic nginx config (temporary) — server_name includes www so www.mim4u.org works; security headers (HSTS when on HTTPS via NPMplus, CSP) pct exec 7810 -- bash -c 'cat > /etc/nginx/sites-available/default << EOF server { listen 80; server_name mim4u.org www.mim4u.org secure.mim4u.org training.mim4u.org _; root /var/www/html; index index.html; # Security headers (HSTS added by NPMplus when terminating SSL; CSP reduces XSS) 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'\'' https://fonts.googleapis.com; font-src '\''self'\'' https://fonts.gstatic.com; img-src '\''self'\'' data: https:; connect-src '\''self'\'' https://mim4u.org; frame-ancestors '\''self'\'';" always; location / { try_files \$uri \$uri/ /index.html =404; } location /api/ { proxy_pass http://192.168.11.36:3001; 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; } } EOF' pct exec 7810 -- nginx -t && pct exec 7810 -- systemctl reload nginx ``` This will at least allow nginx to respond and stop the 502 error. --- ## Complete Deployment For full MIM4U deployment, see: - `scripts/deploy-miracles-in-motion-pve2.sh` - Full deployment script - [MIM4U_FIRST_PARTY_ANALYTICS.md](./MIM4U_FIRST_PARTY_ANALYTICS.md) — related MIM4U ops context --- ## Verification After fixes: ```bash # Test direct IP access curl -I http://192.168.11.37:80/ # Test public domain (after NPMplus update) curl -I https://mim4u.org/ ``` **Expected**: HTTP 200 (not 502) --- ## Optional: Rate limiting for /api/ To rate-limit `/api/` at nginx, the `limit_req_zone` directive must live in the **http** block (e.g. in `/etc/nginx/nginx.conf`), not in the server block. Example: ```nginx # In http { ... } in nginx.conf limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/m; ``` Then in your server block (or in the snippet above), inside `location /api/` add: ```nginx limit_req zone=api_limit burst=5 nodelay; ``` Alternatively, use Cloudflare WAF rate limiting in front of mim4u.org (see [CLOUDFLARE_SETUP](../../miracles_in_motion/docs/deployment/CLOUDFLARE_SETUP.md)). --- **Last Updated**: 2026-01-18 **Status**: ⚠️ nginx installation needed on VMID 7810