# 生产域名需要在部署前替换为真实域名,并由 certbot 或等价流程写入 HTTPS 证书配置。 server { listen 80; server_name genarrative.example.com; location /.well-known/acme-challenge/ { root /var/www/html; } location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; server_name genarrative.example.com; ssl_certificate /etc/letsencrypt/live/genarrative.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/genarrative.example.com/privkey.pem; root /srv/genarrative/web; index index.html; include /etc/nginx/snippets/genarrative-maintenance.conf; location ^~ /admin/api/ { default_type application/json; if ($genarrative_maintenance) { return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}'; } proxy_pass http://127.0.0.1:8082/admin/api/; proxy_http_version 1.1; 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 { return 301 /admin/; } location ^~ /admin/assets/ { 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; } # 生产公网不再暴露旧一体化 API、生成资源代理和健康检查入口。 location ~ ^/(api|generated-|healthz) { return 404; } # SpacetimeDB 只开放 TypeScript SDK 运行所需的最小公网路由。 location ~ ^/v1/database/[^/]+/subscribe$ { proxy_pass http://127.0.0.1:3000; 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 { proxy_pass http://127.0.0.1:3000; 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; } location / { error_page 503 /maintenance.html; if ($genarrative_maintenance) { return 503; } try_files $uri $uri/ /index.html; } }