Spaces:
Running
Running
| # ============================================================================= | |
| # PolyglotAlpha β nginx reverse-proxy config for Hugging Face Spaces (W23) | |
| # ============================================================================= | |
| # HF Spaces exposes exactly ONE port externally (the value of `app_port` in | |
| # the README frontmatter β we use 7860). nginx fans the single ingress out | |
| # to two backends: | |
| # | |
| # /api/*, /sse/*, /trigger/*, /events/*, /leaderboard/*, | |
| # /operators/*, /agents/*, /health -> uvicorn :8000 (FastAPI) | |
| # everything else -> next start :3001 (Next.js) | |
| # | |
| # Two routing concerns to keep in mind: | |
| # 1. SSE streams need `proxy_buffering off` AND a long read timeout β the | |
| # default 60 s would kill the lifecycle progress stream mid-event. | |
| # 2. Next.js HMR/websocket upgrades need the Upgrade/Connection headers | |
| # even in `next start` (the React server channel uses them). | |
| # ----------------------------------------------------------------------------- | |
| worker_processes 1; | |
| events { | |
| worker_connections 1024; | |
| } | |
| http { | |
| include /etc/nginx/mime.types; | |
| default_type application/octet-stream; | |
| sendfile on; | |
| keepalive_timeout 65; | |
| server_tokens off; | |
| # Lift the default 1 MB request body limit a touch β trigger payloads | |
| # with mock_bids can comfortably fit in 64 kB, but 4 MB gives headroom | |
| # for future demo features without surprising 413s. | |
| client_max_body_size 4m; | |
| upstream polyglot_backend { | |
| server 127.0.0.1:8000; | |
| } | |
| upstream polyglot_frontend { | |
| server 127.0.0.1:3001; | |
| } | |
| server { | |
| listen 7860 default_server; | |
| listen [::]:7860 default_server; | |
| server_name _; | |
| # βββ /api/sse/ (SSE β most specific, NO buffering) βββββββββββββββββ | |
| # Has to come BEFORE /api/ generic so the no-buffer settings apply. | |
| # `rewrite ... break` strips the /api prefix before forwarding to | |
| # FastAPI (which serves at /sse/events). | |
| location ^~ /api/sse/ { | |
| rewrite ^/api(/.*)$ $1 break; | |
| proxy_pass http://polyglot_backend; | |
| proxy_http_version 1.1; | |
| proxy_buffering off; | |
| proxy_cache off; | |
| proxy_read_timeout 3600s; | |
| proxy_send_timeout 3600s; | |
| 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_set_header Connection ""; | |
| add_header X-Accel-Buffering no always; | |
| } | |
| # βββ /api/* β all other backend routes βββββββββββββββββββββββββββββ | |
| # nginx strips the /api prefix so FastAPI's existing `/events`, | |
| # `/trigger`, `/leaderboard`, `/operators`, `/agents`, etc. | |
| # routes serve as-is. The UI's `NEXT_PUBLIC_API_BASE=/api` means | |
| # `fetch("/events/6")` becomes `fetch("/api/events/6")` from the | |
| # browser, which nginx routes here. | |
| # | |
| # WITHOUT this prefix, `/events/6` would be claimed by Next.js's | |
| # page router (which has its own `/events/[id]` route) β the | |
| # backend JSON response would never reach the UI's React tree. | |
| location ^~ /api/ { | |
| rewrite ^/api(/.*)$ $1 break; | |
| proxy_pass http://polyglot_backend; | |
| proxy_read_timeout 600s; | |
| 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; | |
| } | |
| # Health check used by the entrypoint pre-seed loop AND by HF Spaces | |
| # readiness probing. | |
| location = /health { | |
| proxy_pass http://polyglot_backend; | |
| proxy_read_timeout 5s; | |
| access_log off; | |
| } | |
| location = /healthz { | |
| return 200 "ok\n"; | |
| add_header Content-Type text/plain; | |
| access_log off; | |
| } | |
| # ---- Frontend: everything else ------------------------------------- | |
| # Next.js handles its own routing (App Router); the websocket/upgrade | |
| # headers are required for streaming server components and any | |
| # future websocket transport. | |
| location / { | |
| proxy_pass http://polyglot_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; | |
| proxy_cache_bypass $http_upgrade; | |
| proxy_read_timeout 60s; | |
| } | |
| } | |
| } | |