Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
Made-with: Cursor
193 lines
5.9 KiB
Markdown
193 lines
5.9 KiB
Markdown
# 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
|