# # NODE1 API Gateway - Nginx Configuration # Version: 1.0 # Last Updated: 2026-01-26 # # Features: # - Rate limiting per IP (10 req/s, burst 20) # - Connection limiting (20 concurrent per IP) # - Security headers # - Upstream keepalive # - Heavy endpoint separate limits # # === Rate Limit Zones === # Standard API: 10 req/s per IP limit_req_zone $binary_remote_addr zone=api_per_ip:10m rate=10r/s; # Heavy endpoints (RAG, image, search): 2 req/s per IP limit_req_zone $binary_remote_addr zone=heavy_per_ip:10m rate=2r/s; # Connection limit per IP limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m; # === Upstreams === upstream gateway_upstream { server 127.0.0.1:9300; keepalive 64; } upstream grafana_upstream { server 127.0.0.1:3030; keepalive 8; } upstream prometheus_upstream { server 127.0.0.1:9090; keepalive 8; } # === Main API Server === server { listen 80; server_name api.daarion.io _; # Redirect to HTTPS (uncomment when SSL is configured) # return 301 https://$host$request_uri; # 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; # Rate limit status page (for debugging) location = /nginx-status { stub_status on; allow 127.0.0.1; deny all; } # Health check endpoint (no rate limit) location = /health { proxy_pass http://gateway_upstream/health; proxy_http_version 1.1; proxy_set_header Connection ""; } # Heavy endpoints - stricter rate limit location ~ ^/(v1/rag|v1/image|v1/search|v1/embed) { limit_req zone=heavy_per_ip burst=5 nodelay; limit_conn conn_per_ip 10; proxy_pass http://gateway_upstream; 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 $scheme; # Longer timeouts for heavy operations proxy_connect_timeout 10s; proxy_send_timeout 120s; proxy_read_timeout 120s; client_max_body_size 50m; } # Webhook endpoints - higher burst for Telegram location ~ ^/(webhook|telegram) { limit_req zone=api_per_ip burst=50 nodelay; limit_conn conn_per_ip 30; proxy_pass http://gateway_upstream; 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 $scheme; proxy_connect_timeout 5s; proxy_send_timeout 30s; proxy_read_timeout 30s; client_max_body_size 10m; } # Default - standard rate limit location / { limit_req zone=api_per_ip burst=20 nodelay; limit_conn conn_per_ip 20; proxy_pass http://gateway_upstream; 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 $scheme; proxy_connect_timeout 5s; proxy_send_timeout 30s; proxy_read_timeout 30s; client_max_body_size 10m; } # Rate limit exceeded - custom error error_page 429 = @rate_limited; location @rate_limited { default_type application/json; return 429 '{"error": "rate_limit_exceeded", "message": "Too many requests. Please slow down.", "retry_after": 1}'; } } # === Admin Panel (Internal Only) === # Access via SSH tunnel: ssh -L 3030:localhost:3030 root@node1 # Or via allowlisted IPs server { listen 127.0.0.1:8080; server_name localhost; # Grafana location /grafana/ { proxy_pass http://grafana_upstream/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # Prometheus location /prometheus/ { proxy_pass http://prometheus_upstream/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } # === HTTPS Server (uncomment after certbot) === # server { # listen 443 ssl http2; # server_name api.daarion.io; # # ssl_certificate /etc/letsencrypt/live/api.daarion.io/fullchain.pem; # ssl_certificate_key /etc/letsencrypt/live/api.daarion.io/privkey.pem; # ssl_session_timeout 1d; # ssl_session_cache shared:SSL:50m; # ssl_session_tickets off; # # # Modern SSL config # ssl_protocols TLSv1.2 TLSv1.3; # ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; # ssl_prefer_server_ciphers off; # # # HSTS # add_header Strict-Transport-Security "max-age=63072000" always; # # # (same location blocks as HTTP server above) # include /etc/nginx/conf.d/node1-api-locations.conf; # }