239 lines
8.8 KiB
Plaintext
239 lines
8.8 KiB
Plaintext
# fire-safety-ymd public HTTPS entrypoint (example)
|
|
#
|
|
# This file is intended to be included from nginx's http context (normally
|
|
# /etc/nginx/conf.d/*.conf). Replace the safe app-id in the exact chat
|
|
# location with the value configured in FIRE_SAFETY_CHAT_COMPAT_APP_ID.
|
|
# /chat and /chat/ are the optional public test page. They are always
|
|
# proxied here, while Go's FIRE_SAFETY_CHAT_PAGE_ENABLED switch decides
|
|
# whether they serve HTML or return 404.
|
|
# Never put FIRE_SAFETY_CHAT_AUTH_TOKEN, FIRE_SAFETY_MCP_AUTH_TOKEN, a
|
|
# SuperAgent key, or a database credential in this file.
|
|
|
|
limit_req_zone $binary_remote_addr zone=fire_safety_chat:10m rate=5r/s;
|
|
limit_req_zone $binary_remote_addr zone=fire_safety_mcp:10m rate=20r/s;
|
|
|
|
upstream fire_safety_ymd_backend {
|
|
server 127.0.0.1:16587;
|
|
keepalive 16;
|
|
}
|
|
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name agent.nianxx.com;
|
|
|
|
return 301 https://agent.nianxx.com$request_uri;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl http2;
|
|
listen [::]:443 ssl http2;
|
|
server_name agent.nianxx.com;
|
|
|
|
ssl_certificate "/cert/agent.nianxx.com.pem";
|
|
ssl_certificate_key "/cert/agent.nianxx.com.key";
|
|
ssl_session_cache shared:SSL:1m;
|
|
ssl_session_timeout 10m;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
limit_req_status 429;
|
|
|
|
# Optional same-origin public test page. The Go handler serves the page
|
|
# only when FIRE_SAFETY_CHAT_PAGE_ENABLED=true; otherwise these exact
|
|
# routes return 404. The page never receives a token from Nginx.
|
|
location = /chat {
|
|
limit_req zone=fire_safety_chat burst=20 nodelay;
|
|
client_max_body_size 16k;
|
|
|
|
proxy_pass http://fire_safety_ymd_backend;
|
|
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_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Port $server_port;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Request-ID $request_id;
|
|
proxy_buffering on;
|
|
proxy_cache off;
|
|
proxy_connect_timeout 5s;
|
|
proxy_read_timeout 30s;
|
|
proxy_send_timeout 30s;
|
|
proxy_next_upstream off;
|
|
proxy_intercept_errors off;
|
|
}
|
|
|
|
location = /chat/ {
|
|
limit_req zone=fire_safety_chat burst=20 nodelay;
|
|
client_max_body_size 16k;
|
|
|
|
proxy_pass http://fire_safety_ymd_backend;
|
|
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_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Port $server_port;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Request-ID $request_id;
|
|
proxy_buffering on;
|
|
proxy_cache off;
|
|
proxy_connect_timeout 5s;
|
|
proxy_read_timeout 30s;
|
|
proxy_send_timeout 30s;
|
|
proxy_next_upstream off;
|
|
proxy_intercept_errors off;
|
|
}
|
|
|
|
# The page keeps CSS and JavaScript as same-origin static resources. Keep
|
|
# these locations exact and proxy them to Go so the Go page switch applies
|
|
# to the complete page surface (HTML, CSS and JavaScript).
|
|
location = /chat/app.css {
|
|
limit_req zone=fire_safety_chat burst=20 nodelay;
|
|
client_max_body_size 16k;
|
|
|
|
proxy_pass http://fire_safety_ymd_backend;
|
|
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_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Port $server_port;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Request-ID $request_id;
|
|
proxy_buffering on;
|
|
proxy_cache off;
|
|
proxy_connect_timeout 5s;
|
|
proxy_read_timeout 30s;
|
|
proxy_send_timeout 30s;
|
|
proxy_next_upstream off;
|
|
proxy_intercept_errors off;
|
|
}
|
|
|
|
location = /chat/app.js {
|
|
limit_req zone=fire_safety_chat burst=20 nodelay;
|
|
client_max_body_size 16k;
|
|
|
|
proxy_pass http://fire_safety_ymd_backend;
|
|
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_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Port $server_port;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Request-ID $request_id;
|
|
proxy_buffering on;
|
|
proxy_cache off;
|
|
proxy_connect_timeout 5s;
|
|
proxy_read_timeout 30s;
|
|
proxy_send_timeout 30s;
|
|
proxy_next_upstream off;
|
|
proxy_intercept_errors off;
|
|
}
|
|
|
|
# DashScope-compatible user chat. Keep this exact location restricted to
|
|
# the one configured app ID; do not replace it with a catch-all regex.
|
|
# The incoming xtoken is forwarded unchanged and validated by Go.
|
|
location = /api/v1/apps/replace-with-fire-safety-app-id/completion {
|
|
limit_req zone=fire_safety_chat burst=20 nodelay;
|
|
client_max_body_size 128k;
|
|
|
|
proxy_pass http://fire_safety_ymd_backend;
|
|
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_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Port $server_port;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Request-ID $request_id;
|
|
# X-Accel-Buffering is a response header; the Go handler also sets it.
|
|
add_header X-Accel-Buffering no always;
|
|
|
|
proxy_buffering off;
|
|
proxy_request_buffering off;
|
|
proxy_cache off;
|
|
gzip off;
|
|
proxy_connect_timeout 5s;
|
|
proxy_read_timeout 660s;
|
|
proxy_send_timeout 660s;
|
|
# Do not retry a streaming POST upstream and risk a duplicate run.
|
|
proxy_next_upstream off;
|
|
proxy_intercept_errors off;
|
|
}
|
|
|
|
# SuperAgent's inbound MCP callback. Go validates its independent
|
|
# Authorization: Bearer token; this proxy deliberately does not inject it.
|
|
location = /mcp {
|
|
limit_req zone=fire_safety_mcp burst=40 nodelay;
|
|
client_max_body_size 256k;
|
|
|
|
proxy_pass http://fire_safety_ymd_backend;
|
|
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_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Port $server_port;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Request-ID $request_id;
|
|
|
|
proxy_buffering on;
|
|
proxy_cache off;
|
|
proxy_connect_timeout 5s;
|
|
proxy_read_timeout 30s;
|
|
proxy_send_timeout 30s;
|
|
proxy_next_upstream off;
|
|
proxy_intercept_errors off;
|
|
}
|
|
|
|
# Optional public liveness check. It is intentionally not a readiness or
|
|
# database check; omit this location if health must remain private.
|
|
location = /health {
|
|
client_max_body_size 1k;
|
|
|
|
proxy_pass http://fire_safety_ymd_backend;
|
|
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_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Port $server_port;
|
|
proxy_set_header X-Forwarded-Server $host;
|
|
proxy_set_header X-Request-ID $request_id;
|
|
|
|
proxy_connect_timeout 5s;
|
|
proxy_read_timeout 5s;
|
|
proxy_send_timeout 5s;
|
|
proxy_next_upstream off;
|
|
proxy_intercept_errors off;
|
|
}
|
|
|
|
# Do not expose every Go route through the public hostname.
|
|
location / {
|
|
default_type application/json;
|
|
return 404 '{"error":{"code":"NOT_FOUND","message":"Not found."}}';
|
|
}
|
|
|
|
error_page 429 = @rate_limited;
|
|
location @rate_limited {
|
|
internal;
|
|
default_type application/json;
|
|
return 429 '{"error":{"code":"RATE_LIMITED","message":"Too many requests."}}';
|
|
}
|
|
}
|