polyglot-alpha / deploy /nginx.conf
licaomeng
deploy: main@8970ffb β†’ HF Spaces (2026-05-27T05:19Z)
88d2f2a
# =============================================================================
# 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;
}
}
}