# ═══════════════════════════════════════════════════════════ # Dealix Production Nginx Configuration # Reverse proxy for Frontend (port 3000) + Backend (port 8000) # With SSL-ready blocks (uncomment when Let's Encrypt is set up) # ═══════════════════════════════════════════════════════════ # Rate limiting zone limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s; limit_req_zone $binary_remote_addr zone=web:10m rate=50r/s; # Upstream definitions upstream dealix_backend { server 127.0.0.1:8000; keepalive 32; } upstream dealix_frontend { server 127.0.0.1:3000; keepalive 16; } # ─── HTTP Server (redirect to HTTPS when SSL is ready) ──── server { listen 80; listen [::]:80; server_name _; # Replace with: dealix.sa www.dealix.sa # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Gzip compression gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml; # API Backend location /api/ { limit_req zone=api burst=20 nodelay; proxy_pass http://dealix_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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 for AI operations (may take longer) proxy_connect_timeout 60s; proxy_send_timeout 120s; proxy_read_timeout 120s; # CORS headers add_header Access-Control-Allow-Origin "*" always; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; add_header Access-Control-Allow-Headers "Authorization, Content-Type, Accept" always; if ($request_method = OPTIONS) { return 204; } } # Swagger docs location /api/docs { proxy_pass http://dealix_backend/api/docs; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /api/openapi.json { proxy_pass http://dealix_backend/api/openapi.json; proxy_set_header Host $host; } # WebSocket support (for real-time updates) location /ws/ { proxy_pass http://dealix_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 86400; } # WhatsApp Webhook location /api/v1/whatsapp/webhook { proxy_pass http://dealix_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # Frontend (Next.js) location / { limit_req zone=web burst=30 nodelay; proxy_pass http://dealix_frontend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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; } # Static file caching location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { proxy_pass http://dealix_frontend; expires 30d; add_header Cache-Control "public, immutable"; } # Health check endpoint location /health { proxy_pass http://dealix_backend/api/v1/health; access_log off; } # Block sensitive paths location ~ /\. { deny all; return 404; } location ~ /(\.env|\.git|docker-compose|Dockerfile) { deny all; return 404; } # Custom error pages error_page 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; internal; } } # ─── HTTPS Server (uncomment after certbot setup) ───────── # server { # listen 443 ssl http2; # listen [::]:443 ssl http2; # server_name dealix.sa www.dealix.sa; # # ssl_certificate /etc/letsencrypt/live/dealix.sa/fullchain.pem; # ssl_certificate_key /etc/letsencrypt/live/dealix.sa/privkey.pem; # ssl_protocols TLSv1.2 TLSv1.3; # ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; # ssl_prefer_server_ciphers on; # ssl_session_cache shared:SSL:10m; # ssl_session_timeout 10m; # # # HSTS # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # # # (Copy all location blocks from HTTP server above) # }