worker_processes auto; events { worker_connections 1024; } http { resolver 127.0.0.11 valid=10s; # Define a rate limit zone to prevent abuse limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; # Map Authorization header to a token variable for sticky sessions map $http_authorization $auth_token { "~*Bearer\s+(.*)" $1; default $remote_addr; # Fallback to IP hash if no token is provided } # Upstream with hash-based load balancing (Sticky Sessions) # The hash uses the user's API Key so the same API Key always hits the same node, # preserving the cascade_id context in memory. upstream windsurf_backend { hash $auth_token consistent; # In a real Swarm/Compose environment with scale=3, Docker DNS resolves 'windsurf-api' to all IPs. # But 'hash' works better with explicit servers or using a DNS resolver dynamically if needed. # Nginx free version requires manual IP listings for sticky sessions, # or we rely on ip_hash for generic load balancing if behind a single reverse proxy. zone windsurf_backend_zone 64k; server windsurf-api:3003 resolve; } server { listen 80; location / { limit_req zone=mylimit burst=20 nodelay; proxy_pass http://windsurf_backend; proxy_http_version 1.1; # SSE and streaming requirements proxy_set_header Connection ''; proxy_buffering off; proxy_cache off; chunked_transfer_encoding on; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }