# Trust all proxies (adjust as needed) set_real_ip_from 0.0.0.0/0; real_ip_header X-Forwarded-For; real_ip_recursive on; # Map to track which backend served the request for debugging map $upstream_addr $served_from { "127.0.0.1:8001" "8001"; "127.0.0.1:8002" "8002"; "127.0.0.1:8003" "8003"; "127.0.0.1:8004" "8004"; "127.0.0.1:8005" "8005"; "127.0.0.1:8006" "8006"; "127.0.0.1:8007" "8007"; "127.0.0.1:8008" "8008"; "127.0.0.1:8009" "8009"; "127.0.0.1:8010" "8010"; "127.0.0.1:8011" "8011"; "127.0.0.1:8012" "8012"; "127.0.0.1:8013" "8013"; "127.0.0.1:8014" "8014"; "127.0.0.1:8015" "8015"; "127.0.0.1:8016" "8016"; "127.0.0.1:8017" "8017"; "127.0.0.1:8018" "8018"; "127.0.0.1:8019" "8019"; "127.0.0.1:8020" "8020"; "127.0.0.1:8021" "8021"; } # Use the space query parameter as the sticky value map $arg_space $sticky_value { "" $remote_addr; # Fall back to client IP if space parameter is not present default $arg_space; # Use the space parameter value } # Map for handling the upgrade header for WebSockets map $http_upgrade $connection_upgrade { default Upgrade; '' close; } # Regular API traffic upstream (ports 8001-8005) upstream api_backend { server 127.0.0.1:8001; server 127.0.0.1:8002; server 127.0.0.1:8003; server 127.0.0.1:8004; server 127.0.0.1:8005; } # WebSocket traffic upstream (ports 8006-8021) upstream ws_backend { hash $sticky_value consistent; server 127.0.0.1:8006; server 127.0.0.1:8007; server 127.0.0.1:8008; server 127.0.0.1:8009; server 127.0.0.1:8010; server 127.0.0.1:8011; server 127.0.0.1:8012; server 127.0.0.1:8013; server 127.0.0.1:8014; server 127.0.0.1:8015; server 127.0.0.1:8016; server 127.0.0.1:8017; server 127.0.0.1:8018; server 127.0.0.1:8019; server 127.0.0.1:8020; server 127.0.0.1:8021; } server { listen 8080; server_name localhost; # Default location for most traffic including API requests location / { add_header X-Served-From $served_from always; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header Tailscale-User-Login $http_tailscale_user_login; proxy_pass http://api_backend; # 5min timeout proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; } # WebSocket specific traffic only for /api/storage/memory location /api/storage/memory { proxy_pass http://ws_backend; # WebSocket support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; # Ensure query parameters are forwarded proxy_pass_request_headers on; # Standard 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 Tailscale-User-Login $http_tailscale_user_login; add_header X-Served-From $served_from always; # Increased timeouts for long-lived WebSocket connections proxy_read_timeout 86400; proxy_send_timeout 86400; } # Expose Nginx status at /_nginx location /_nginx { # Enable the stub_status module stub_status; # Access restrictions allow 100.64.0.0/10; # Tailscale network allow 127.0.0.1; # Localhost IPv4 allow ::1; # Localhost IPv6 deny all; # Deny everyone else } }