worker_rlimit_nofile 131072; events { worker_connections 16384; } http { keepalive_requests 10000; include /etc/nginx/mime.types; default_type application/octet-stream; resolver 127.0.0.11 ipv6=off; limit_conn_zone $binary_remote_addr zone=perip:10m; limit_req_zone $binary_remote_addr zone=reqperip:10m rate=100r/s; set_real_ip_from 130.211.0.0/22; set_real_ip_from 35.191.0.0/16; real_ip_header X-Forwarded-For; real_ip_recursive on; # ───────────── upstreams to Docker services ───────────── upstream backend5000 { server server1:5000; } # auth & free upstream backend5001 { server server2:5001; keepalive 1024;} # onet, distance, etc. upstream backend5002 { server server3:5002; } # premium upstream gitea_backend { server gitea:3000; } # gitea service (shared network) upstream woodpecker_backend { server woodpecker-server:8000; } ######################################################################## # 1. HTTP → HTTPS redirect for the main site ######################################################################## server { listen 80; listen [::]:80; server_name dev1.aptivaai.com; return 301 https://$host$request_uri; } ######################################################################## # 2. Main virtual host (dev1.aptivaai.com) on :443 ######################################################################## server { listen 443 ssl; http2 on; http2_max_concurrent_streams 2048; http2_idle_timeout 90s; http2_recv_timeout 90s; server_name dev1.aptivaai.com; ssl_certificate /etc/letsencrypt/live/dev1.aptivaai.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/dev1.aptivaai.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; # ==== RUNTIME PROTECTIONS ==== server_tokens off; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Content-Type-Options nosniff always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header X-Frame-Options SAMEORIGIN always; client_max_body_size 10m; large_client_header_buffers 4 8k; client_header_timeout 30s; client_body_timeout 30s; send_timeout 35s; keepalive_timeout 65s; proxy_set_header X-Request-ID $request_id; add_header X-Request-ID $request_id always; proxy_request_buffering off; proxy_max_temp_file_size 0; proxy_buffer_size 16k; proxy_buffers 8 16k; proxy_busy_buffers_size 32k; if ($request_method !~ ^(GET|POST|PUT|PATCH|DELETE|OPTIONS)$) { return 405; } if ($host !~* ^(dev1\.aptivaai\.com)$) { return 444; } location ~ /\.(?!well-known/) { deny all; } location ~* \.(?:env|ini|log|sql|sqlite|db|db3|bak|old|orig|swp)$ { deny all; } # ───── React static assets ───── root /usr/share/nginx/html; index index.html; location / { try_files $uri $uri/ /index.html; } location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg)$ { expires 6M; access_log off; } # ───── API reverse‑proxy rules ───── location ^~ /api/onet/ { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_read_timeout 90s; proxy_connect_timeout 15s; proxy_pass http://backend5001; } location ^~ /api/chat/ { limit_conn perip 10; limit_req zone=reqperip burst=20 nodelay; proxy_pass http://backend5001; proxy_http_version 1.1; proxy_buffering off; proxy_set_header Connection ""; } location ^~ /api/job-zones { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_read_timeout 90s; proxy_connect_timeout 15s; proxy_pass http://backend5001; } location ^~ /api/salary { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_read_timeout 90s; proxy_connect_timeout 15s; proxy_pass http://backend5001; } location ^~ /api/cip/ { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_read_timeout 90s; proxy_connect_timeout 15s; proxy_pass http://backend5001; } location ^~ /api/projections/ { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_read_timeout 90s; proxy_connect_timeout 15s; proxy_pass http://backend5001; } location ^~ /api/tuition/ { proxy_pass http://backend5001; } location ^~ /api/skills/ { proxy_pass http://backend5001; } location ^~ /api/maps/distance { proxy_pass http://backend5001; } location ^~ /api/schools { proxy_pass http://backend5001; } location ^~ /api/support { limit_conn perip 5; limit_req zone=reqperip burst=10 nodelay; proxy_pass http://backend5001; } location ^~ /api/data/ { proxy_pass http://backend5001; } location ^~ /api/careers/ { proxy_pass http://backend5001; } location ^~ /api/programs/ { proxy_pass http://backend5001; } location ^~ /api/premium/ { limit_conn perip 10; limit_req zone=reqperip burst=20 nodelay; proxy_pass http://backend5002; proxy_http_version 1.1; proxy_set_header Connection ""; } location ^~ /api/premium/stripe/webhook { proxy_pass http://backend5002; proxy_http_version 1.1; proxy_set_header Connection ""; } location ^~ /api/public/ { proxy_pass http://backend5002; } location ^~ /api/ai-risk { proxy_pass http://backend5002; } location = /api/signin { limit_conn perip 5; limit_req zone=reqperip burst=10 nodelay; proxy_pass http://backend5000; } location = /api/register { limit_conn perip 3; limit_req zone=reqperip burst=5 nodelay; proxy_pass http://backend5000; } location ^~ /api/auth/ { limit_conn perip 5; limit_req zone=reqperip burst=10 nodelay; proxy_pass http://backend5000; } location = /api/user-profile { limit_conn perip 5; limit_req zone=reqperip burst=10 nodelay; proxy_pass http://backend5000; } # General API (anything not matched above) – rate-limited location ^~ /api/ { proxy_pass http://backend5000; } # shared 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; error_page 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } ######################################################################## # 3. Gitea virtual host (HTTPS) gitea.dev1.aptivaai.com ######################################################################## server { listen 443 ssl; http2 on; server_name gitea.dev1.aptivaai.com; client_max_body_size 1024m; ssl_certificate /etc/letsencrypt/live/gitea.dev1.aptivaai.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/gitea.dev1.aptivaai.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; location / { proxy_pass http://gitea_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; proxy_set_header X-Forwarded-Proto https; } } ######################################################################## # 4. Gitea HTTP → HTTPS redirect ######################################################################## server { listen 80; server_name gitea.dev1.aptivaai.com; return 301 https://$host$request_uri; } ######################################################################## # 5. Woodpecker CI – HTTPS ci.dev1.aptivaai.com ######################################################################## server { listen 443 ssl; http2 on; server_name ci.dev1.aptivaai.com; ssl_certificate /etc/letsencrypt/live/ci.dev1.aptivaai.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ci.dev1.aptivaai.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; location / { proxy_http_version 1.1; proxy_set_header Connection ""; 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 https; proxy_pass http://woodpecker_backend; } } ######################################################################## # 6. Woodpecker – HTTP → HTTPS redirect ######################################################################## server { listen 80; server_name ci.dev1.aptivaai.com; return 301 https://$host$request_uri; }}