platform-codebase/features/status-dashboard/frontend/NGINX_CONFIG.md
Quinn Ftw 02ab9cc22b feat(status-dashboard): push-based host monitoring and testing infra
- Add host-status-monitor with macOS/Linux support
- Add vitest + playwright testing setup
- Add docker-compose for local development
- Add metrics persistence service
- Improve deploy scripts and env configs
- Update frontend components and auth

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 00:37:26 -08:00

8.2 KiB

nginx Configuration for status.atlilith.com

Purpose: Production nginx configuration to serve status-page app with HTTPS and proxy API/WebSocket requests.


🎯 Requirements

After the vite.config.ts fix, the status-page app now uses same-origin URLs:

  • API calls: https://status.atlilith.com/api/...
  • WebSocket: wss://status.atlilith.com/socket.io/...

This requires nginx to:

  1. Serve the static frontend (built dist/ folder)
  2. Proxy /api/* requests to backend
  3. Proxy /socket.io/* WebSocket connections to backend

📋 nginx Configuration

Location: /etc/nginx/sites-available/status.atlilith.com

# status.atlilith.com - Status Page Application
server {
    listen 80;
    server_name status.atlilith.com;

    # Redirect all HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name status.atlilith.com;

    # SSL Certificate (Let's Encrypt)
    ssl_certificate /etc/letsencrypt/live/status.atlilith.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/status.atlilith.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/status.atlilith.com/chain.pem;

    # SSL Configuration (recommended)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Security Headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Root directory (status-page dist folder)
    root /opt/status-page/dist;
    index index.html;

    # Main site (serve React SPA)
    location / {
        try_files $uri $uri/ /index.html;

        # Cache static assets
        location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$ {
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }

    # API Proxy (to health monitor backend)
    location /api {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;

        # Standard proxy headers
        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;

        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # CORS (if needed)
        add_header Access-Control-Allow-Origin "https://status.atlilith.com" always;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
        add_header Access-Control-Allow-Credentials "true" always;

        # Handle OPTIONS preflight
        if ($request_method = OPTIONS) {
            return 204;
        }
    }

    # WebSocket Proxy (Socket.io)
    location /socket.io {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;

        # WebSocket upgrade headers
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Standard proxy headers
        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;

        # WebSocket timeouts (keep connection alive)
        proxy_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;

        # Disable buffering for WebSocket
        proxy_buffering off;
    }

    # Logging
    access_log /var/log/nginx/status.atlilith.com.access.log;
    error_log /var/log/nginx/status.atlilith.com.error.log;
}

🚀 Deployment Steps

1. Create nginx Config

# SSH to production server
ssh root@93.95.231.174

# Create nginx config
sudo nano /etc/nginx/sites-available/status.atlilith.com

# Paste the config above
# Save and exit (Ctrl+X, Y, Enter)

2. Enable Site

# Create symbolic link
sudo ln -s /etc/nginx/sites-available/status.atlilith.com /etc/nginx/sites-enabled/

# Test nginx configuration
sudo nginx -t

# If test passes, reload nginx
sudo systemctl reload nginx

3. Setup SSL Certificate

# Install certbot (if not already installed)
sudo apt install certbot python3-certbot-nginx

# Get SSL certificate
sudo certbot --nginx -d status.atlilith.com

# Certbot will automatically update the nginx config with SSL paths

4. Deploy Frontend Build

# On local machine (in stream worktree)
cd features/status-dashboard/frontend
pnpm build

# Copy dist/ to production server
scp -r dist/* root@93.95.231.174:/opt/status-page/dist/

# Or use rsync
rsync -avz --delete dist/ root@93.95.231.174:/opt/status-page/dist/

5. Verify Backend is Running

# On production server
# Check if health monitor is running on port 5000
curl http://localhost:5000/api/health/status

# If not running, start it
cd /path/to/health-monitor
pm2 start server.js --name health-monitor

# Or with systemd
sudo systemctl start health-monitor

6. Test Everything

# Test HTTPS redirect
curl -I http://status.atlilith.com
# Should return 301 redirect to HTTPS

# Test API proxy
curl https://status.atlilith.com/api/health/status
# Should return JSON health data

# Test in browser
# Open https://status.atlilith.com
# Check browser console for errors
# Verify WebSocket connects (should show "Connected" status)

🔍 Troubleshooting

Mixed Content Errors Still Showing

Check:

  1. Clear browser cache completely (Ctrl+Shift+Delete)
  2. Check browser console - are requests going to HTTPS?
  3. Verify nginx proxy is working: curl https://status.atlilith.com/api/health/status

WebSocket Not Connecting

Check:

  1. Backend is running: curl http://localhost:5000/socket.io/
  2. nginx WebSocket proxy config is correct
  3. Browser DevTools → Network → WS tab (should show wss:// connection)
  4. Check nginx error log: tail -f /var/log/nginx/status.atlilith.com.error.log

502 Bad Gateway

Possible causes:

  1. Backend not running on port 5000
  2. Firewall blocking localhost:5000
  3. Backend crashed

Fix:

# Check backend status
pm2 list
# or
sudo systemctl status health-monitor

# Check backend logs
pm2 logs health-monitor
# or
sudo journalctl -u health-monitor -f

# Restart backend
pm2 restart health-monitor
# or
sudo systemctl restart health-monitor

CORS Errors

If seeing CORS errors, update the API proxy location:

location /api {
    # Add CORS headers
    add_header Access-Control-Allow-Origin "https://status.atlilith.com" always;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;

    if ($request_method = OPTIONS) {
        return 204;
    }

    proxy_pass http://localhost:5000;
    # ... rest of config
}

📊 Monitoring

Check nginx Logs

# Access logs
tail -f /var/log/nginx/status.atlilith.com.access.log

# Error logs
tail -f /var/log/nginx/status.atlilith.com.error.log

Check Backend Logs

# If using pm2
pm2 logs health-monitor

# If using systemd
sudo journalctl -u health-monitor -f

Test Endpoints

# API health
curl https://status.atlilith.com/api/health/status

# VPS resources
curl https://status.atlilith.com/api/health/vps-resources

# Containers
curl https://status.atlilith.com/api/health/containers

Success Criteria

After deployment, verify:

  • https://status.atlilith.com loads without errors
  • No mixed content warnings in browser console
  • API data displays (CPU, RAM, disk usage)
  • WebSocket shows "Connected" status
  • Real-time updates work (metrics refresh automatically)
  • Admin login works (/login)
  • Protected routes work (/admin)

📝 Notes

  • Backend Port: Assumes health monitor runs on localhost:5000
  • Directory: Assumes frontend deployed to /opt/status-page/dist
  • SSL: Auto-configured by certbot
  • Logs: Standard nginx log locations

Update these paths if your setup differs.