f4153ebfa7
新增品牌维护页和404页面并补齐网关路由 将临时维护公告迁到release外运行态覆盖并增加构建门禁 同步Nginx、Pingora、部署脚本与生产运维文档 隐藏移动端顶部SEO介绍并保留桌面端与H1语义 增加维护页、404页和移动端回归测试
310 lines
11 KiB
Plaintext
310 lines
11 KiB
Plaintext
# 开发服无域名时使用的 HTTP 入口,只允许用于 DEPLOY_TARGET=development。
|
||
# 没有域名时,将 SERVER_NAME 填为开发机 IP 或临时主机名。
|
||
# 生产 release 仍必须使用 genarrative.conf 的 HTTPS 配置。
|
||
log_format genarrative_upstream
|
||
'$remote_addr - $remote_user [$time_local] "$request" '
|
||
'$status $body_bytes_sent "$http_referer" "$http_user_agent" '
|
||
'request_time=$request_time upstream_connect_time=$upstream_connect_time '
|
||
'upstream_header_time=$upstream_header_time upstream_response_time=$upstream_response_time '
|
||
'upstream_status=$upstream_status request_id=$request_id';
|
||
|
||
upstream genarrative_api {
|
||
server 127.0.0.1:8082;
|
||
keepalive 64;
|
||
}
|
||
|
||
limit_conn_zone $binary_remote_addr zone=genarrative_api_conn:10m;
|
||
limit_req_zone $binary_remote_addr zone=genarrative_gallery_rps:10m rate=5000r/s;
|
||
limit_req_zone $binary_remote_addr zone=genarrative_api_rps:10m rate=300r/s;
|
||
limit_req_zone $binary_remote_addr zone=genarrative_admin_rps:10m rate=30r/s;
|
||
|
||
# 维护期间允许真实 TCP 内网来源继续访问整站;不信任请求头伪造的客户端地址。
|
||
geo $remote_addr $genarrative_internal_client {
|
||
default 0;
|
||
127.0.0.0/8 1;
|
||
10.0.0.0/8 1;
|
||
172.16.0.0/12 1;
|
||
192.168.0.0/16 1;
|
||
169.254.0.0/16 1;
|
||
::1 1;
|
||
fc00::/7 1;
|
||
fe80::/10 1;
|
||
}
|
||
|
||
server {
|
||
listen 80;
|
||
server_name genarrative.example.com;
|
||
access_log /var/log/nginx/genarrative.access.log genarrative_upstream;
|
||
error_log /var/log/nginx/genarrative.error.log warn;
|
||
limit_conn_status 429;
|
||
limit_conn_log_level warn;
|
||
limit_req_status 429;
|
||
limit_req_log_level warn;
|
||
|
||
gzip on;
|
||
gzip_vary on;
|
||
gzip_proxied any;
|
||
gzip_comp_level 5;
|
||
gzip_min_length 1024;
|
||
gzip_types
|
||
text/plain
|
||
text/css
|
||
text/javascript
|
||
application/javascript
|
||
application/json
|
||
application/xml
|
||
application/xml+rss
|
||
image/svg+xml;
|
||
|
||
# __GENARRATIVE_BROTLI_DIRECTIVES__
|
||
|
||
root /srv/genarrative/web;
|
||
index index.html;
|
||
|
||
include /etc/nginx/snippets/genarrative-maintenance.conf;
|
||
|
||
location ^~ /admin/api/ {
|
||
default_type application/json;
|
||
limit_conn genarrative_api_conn 64;
|
||
limit_req zone=genarrative_admin_rps burst=16 nodelay;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
|
||
}
|
||
|
||
proxy_pass http://genarrative_api/admin/api/;
|
||
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-Request-Id $request_id;
|
||
}
|
||
|
||
location = /admin {
|
||
error_page 503 /maintenance.html;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503;
|
||
}
|
||
|
||
return 301 /admin/;
|
||
}
|
||
|
||
location ^~ /admin/assets/ {
|
||
error_page 503 /maintenance.html;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503;
|
||
}
|
||
|
||
try_files $uri =404;
|
||
}
|
||
|
||
location ^~ /admin/ {
|
||
error_page 503 /maintenance.html;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503;
|
||
}
|
||
|
||
try_files $uri $uri/ /admin/index.html;
|
||
}
|
||
|
||
location ^~ /assets/ {
|
||
try_files $uri =404;
|
||
}
|
||
|
||
location = /api/runtime/puzzle/gallery {
|
||
default_type application/json;
|
||
limit_conn genarrative_api_conn 320;
|
||
limit_req zone=genarrative_gallery_rps burst=4096 nodelay;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
|
||
}
|
||
|
||
proxy_pass http://genarrative_api;
|
||
proxy_http_version 1.1;
|
||
proxy_buffering off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
add_header X-Accel-Buffering no always;
|
||
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-Request-Id $request_id;
|
||
}
|
||
|
||
location = /api/runtime/custom-world-gallery {
|
||
default_type application/json;
|
||
limit_conn genarrative_api_conn 320;
|
||
limit_req zone=genarrative_gallery_rps burst=4096 nodelay;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
|
||
}
|
||
|
||
proxy_pass http://genarrative_api;
|
||
proxy_http_version 1.1;
|
||
proxy_buffering off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
add_header X-Accel-Buffering no always;
|
||
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-Request-Id $request_id;
|
||
}
|
||
|
||
location ~ ^/api/runtime/puzzle/gallery/[^/]+$ {
|
||
default_type application/json;
|
||
limit_conn genarrative_api_conn 32;
|
||
limit_req zone=genarrative_api_rps burst=32 nodelay;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
|
||
}
|
||
|
||
proxy_pass http://genarrative_api;
|
||
proxy_http_version 1.1;
|
||
proxy_buffering off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
add_header X-Accel-Buffering no always;
|
||
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-Request-Id $request_id;
|
||
}
|
||
|
||
location ~ ^/api/runtime/custom-world-gallery/[^/]+/[^/]+$ {
|
||
default_type application/json;
|
||
limit_conn genarrative_api_conn 32;
|
||
limit_req zone=genarrative_api_rps burst=32 nodelay;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
|
||
}
|
||
|
||
proxy_pass http://genarrative_api;
|
||
proxy_http_version 1.1;
|
||
proxy_buffering off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
add_header X-Accel-Buffering no always;
|
||
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-Request-Id $request_id;
|
||
}
|
||
|
||
# 临时兼容主站仍在使用的 /api/* HTTP facade;前端完成 SpacetimeDB SDK 迁移后删除。
|
||
location ~ ^/api(?:/|$) {
|
||
default_type application/json;
|
||
# 中文注释:创作接口会携带参考图 Data URL,Nginx 只放行到 api-server;真实大小限制仍由路由 DefaultBodyLimit 和业务字节校验负责。
|
||
client_max_body_size 64m;
|
||
limit_conn genarrative_api_conn 64;
|
||
limit_req zone=genarrative_api_rps burst=64 nodelay;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
|
||
}
|
||
|
||
proxy_pass http://genarrative_api;
|
||
proxy_http_version 1.1;
|
||
proxy_buffering off;
|
||
proxy_read_timeout 3600s;
|
||
proxy_send_timeout 3600s;
|
||
add_header X-Accel-Buffering no always;
|
||
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-Request-Id $request_id;
|
||
}
|
||
|
||
# 开发服仍不恢复旧生成资源代理和健康检查公网入口。
|
||
location ~ ^/(generated-|healthz|readyz) {
|
||
return 404;
|
||
}
|
||
|
||
# 仅开放前端 SpacetimeDB SDK 运行所需的最小公网路由。
|
||
location ~ ^/v1/database/[^/]+/subscribe$ {
|
||
if ($genarrative_maintenance) {
|
||
return 503;
|
||
}
|
||
|
||
proxy_pass http://127.0.0.1:3101;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "Upgrade";
|
||
proxy_set_header Host $host;
|
||
proxy_read_timeout 3600s;
|
||
}
|
||
|
||
location ^~ /v1/identity {
|
||
if ($genarrative_maintenance) {
|
||
return 503;
|
||
}
|
||
|
||
proxy_pass http://127.0.0.1:3101;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "Upgrade";
|
||
proxy_set_header Host $host;
|
||
}
|
||
|
||
location ^~ /v1/ {
|
||
return 404;
|
||
}
|
||
|
||
# BEGIN GENARRATIVE MAIN SPA ROUTES
|
||
location = / {
|
||
error_page 503 /maintenance.html;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503;
|
||
}
|
||
|
||
try_files /index.html =404;
|
||
}
|
||
|
||
location ~* "^/(?:bark-battle|big-fish|child-motion-demo|creation|creation/baby-object-match|creation/baby-object-match/generating|creation/baby-object-match/result|creation/bark-battle|creation/bark-battle/generating|creation/bark-battle/result|creation/big-fish|creation/big-fish/generating|creation/big-fish/result|creation/creative-agent|creation/jump-hop|creation/jump-hop/generating|creation/jump-hop/result|creation/match3d|creation/match3d/generating|creation/match3d/result|creation/puzzle|creation/puzzle-clear|creation/puzzle-clear/generating|creation/puzzle-clear/result|creation/puzzle/generating|creation/puzzle/result|creation/rpg|creation/rpg/agent|creation/rpg/generating|creation/rpg/result|creation/square-hole|creation/square-hole/generating|creation/square-hole/result|creation/visual-novel|creation/visual-novel/generating|creation/visual-novel/result|creation/wooden-fish|creation/wooden-fish/generating|creation/wooden-fish/result|editor/canvas|gallery/jump-hop/detail|gallery/puzzle/detail|gallery/visual-novel/detail|match3d|project|puzzle|runtime/baby-love-drawing|runtime/baby-object-match|runtime/bark-battle|runtime/big-fish|runtime/jump-hop|runtime/match3d|runtime/puzzle|runtime/puzzle-clear|runtime/rpg/adventure|runtime/rpg/characters|runtime/square-hole|runtime/visual-novel|runtime/wooden-fish|works/detail|worlds/detail)/?$" {
|
||
error_page 503 /maintenance.html;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503;
|
||
}
|
||
|
||
try_files $uri /index.html =404;
|
||
}
|
||
# END GENARRATIVE MAIN SPA ROUTES
|
||
|
||
location / {
|
||
error_page 503 /maintenance.html;
|
||
error_page 404 /404.html;
|
||
|
||
if ($genarrative_maintenance) {
|
||
return 503;
|
||
}
|
||
|
||
try_files $uri $uri/ =404;
|
||
}
|
||
}
|