Files
opendance-web/deploy/proxy/README.md
T

229 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 反向代理说明(nginx / IIS)
> **职责边界**:本 Web 端**只提供业务服务**(NestJS API + 管理端页面),
> **不部署、不配置反向代理**。反向代理由另外的服务或团队负责,本文档只提供配置说明。
>
> 安装脚本 `deploy/install.sh` 不会安装或修改任何反代软件。
## 一、需要转发的目标(两个端口,按用途分开)
本服务**同时监听两个端口**,职责不同:
| 端口 | 环境变量 | 默认 | 给谁用 | 提供什么 |
|--|--|--|--|--|
| 软件 API 端口 | `PORT` | `3000` | Windows/Godot 客户端、Android App | `/api`、`/health`、`/static`、`/contracts`;**不含管理页面**(未知路径 404) |
| 管理端端口 | `ADMIN_PORT` | `3001` | 浏览器(管理员) | 管理页面 + 上面全部接口 |
```
软件 API: http://<后端地址>:3000
管理端: http://<后端地址>:3001
```
两者都不需要在代理层托管静态文件,也不需要配置 SPA 回退(服务端已处理);
各用一条 `location /`(nginx)或全匹配规则(IIS)即可。
**推荐做法**:把两个端口挂在两个不同的站点/域名上,便于分别做访问控制,例如
- `https://dance-api.example.com` -> 转发到 `3000`(给客户端,可用 IP 白名单)
- `https://dance-admin.example.com` -> 转发到 `3001`(给管理员,建议加 Basic Auth / SSO 或只在内网放行)
如果客户端与管理端在同一个内网、也不想配域名,可以**让客户端直连 `3000`**(不经过反代),
只把管理端 `3001` 挂到反代上;反之亦可。
| 路径 | 内容 | 哪个端口提供 |
|--|--|--|
| `/`、`/assets/*` | 管理端页面与静态资源 | **仅管理端**;前端路由深链接(如 `/songs`)由服务端回退到 `index.html` |
| `/api/*` | REST API | 两个端口都提供(契约见 `contracts/rest-api.yaml`) |
| `/health` | 健康检查 | 两个端口都提供;可用作反代的存活探测,数据库不可用时返回 **503** |
| `/static/*` | 上传文件 | 两个端口都提供(模型 / 音频 / 关键点序列) |
| `/contracts/*` | 契约快照 | 两个端口都提供,只读 |
> Windows 客户端与 Android 之间的**关键点 WebSocket 链路不经过本服务**,
> 反代无需配置 WebSocket 转发。
>
> `ADMIN_PORT` 设为与 `PORT` 相同时是**单端口兼容模式**:两个端口合一,
> 管理页面重新出现在 API 端口上(此时反代只需要一条规则)。
## 二、后端绑定地址怎么选
`deploy/.env` 中的 `HOST`(软件 API 端口)与可选的 `ADMIN_HOST`(管理端端口,缺省跟随 `HOST`):
| 部署形态 | 建议值 | 说明 |
|--|--|--|
| 反代与后端**同机** | `HOST=127.0.0.1` | 后端不直接对外暴露,最安全 |
| 反代与后端**不同机** | `HOST=0.0.0.0` | 必须用防火墙把端口限制为仅反代来源可访问 |
| 只想让管理端在内网可见 | `ADMIN_HOST=<内网网卡地址>` | 与 `HOST=0.0.0.0` 组合使用,把管理端限制在内网 |
改完执行 `systemctl restart opendance-api`(或对应的 `ctl.sh restart`)生效。
## 三、必须同步调整的两项
1. **上传上限**:本服务默认允许 512 MiB(`UPLOAD_MAX_BYTES`)。
代理层默认值通常远小于此(nginx 1 MB、IIS 约 28.6 MB),不改会导致大模型上传失败。
2. **超时**:上传大文件与下载关键点序列可能较慢,代理的读写超时必须放大。
## 四、nginx 配置
完整样例见 [`nginx.conf.example`](nginx.conf.example)。核心内容:
```nginx
upstream opendance_api {
server 127.0.0.1:3000;
keepalive 16;
}
server {
listen 80;
server_name your.domain.com;
client_max_body_size 512m; # ← 必须放开,否则 VRM/FBX 上传失败
client_body_timeout 300s;
location / {
proxy_pass http://opendance_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 Connection "";
proxy_connect_timeout 30s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_request_buffering off; # 大文件直接透传,不在代理落盘
}
}
```
安装位置与重载:
```bash
# Debian / Ubuntu
cp nginx.conf.example /etc/nginx/sites-available/opendance.conf
ln -s /etc/nginx/sites-available/opendance.conf /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
# RHEL 系
cp nginx.conf.example /etc/nginx/conf.d/opendance.conf
nginx -t && systemctl reload nginx
```
## 五、IIS 配置
IIS 需要先安装两个模块(**默认都没有**):
1. **URL Rewrite** - https://www.iis.net/downloads/microsoft/url-rewrite
2. **Application Request Routing (ARR)** - https://www.iis.net/downloads/microsoft/application-request-routing
装完 ARR 后还需启用代理(否则会报 404.4):
```
IIS 管理器 -> 选中服务器节点 -> Application Request Routing Cache
-> 右侧 Server Proxy Settings -> 勾选 Enable proxy -> 应用
```
完整 `web.config` 样例见 [`web.config.example`](web.config.example),放到站点根目录即可:
```xml
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="OpenDanceReverseProxy" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://127.0.0.1:3000/{R:1}" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<!-- 512 MiB:IIS 默认约 28.6 MB,不改大文件上传必失败 -->
<requestLimits maxAllowedContentLength="536870912" />
</requestFiltering>
</security>
<proxy preserveHostHeader="true" />
<serverRuntime uploadReadAheadSize="536870912" />
</system.webServer>
</configuration>
```
### IIS 容易踩的三个坑
1. **`requestLimits` 与 `serverRuntime` 要一起改**。只改前者,SSL 场景下仍会在
读取请求体时失败(`uploadReadAheadSize` 默认仅 48 KB)。
2. **代理超时改的是服务器级配置**,不是站点级。ARR 默认 120 秒,上传大文件会
中断。在 `applicationHost.config` 的 `<webProxy>` 节点调整:
```xml
<webProxy enabled="true" timeout="00:05:00" />
```
3. **`preserveHostHeader`** 需与 ARR 的 "Preserve host header" 设置一致,
否则后端收到的 Host 会变成 `127.0.0.1:3000`,影响日志与重定向。
## 六、HTTPS 与访问控制(可选)
- **HTTPS 终止在反代**:本服务只监听 HTTP,证书配置在 nginx/IIS 侧即可。
- **访问控制**:本版本**未内置登录认证**,如需公网访问,请在反代层加
Basic Auth、IP 白名单或对接已有 SSO。未加任何防护时请只在内网开放。
## 七、自检清单
配置完成后逐项确认:
```bash
# 0. 两个端口都在监听(双端口部署)
ss -tlnp | grep -E ':(3000|3001)'
# 1. 后端自身可用(绕过反代)
curl -i http://127.0.0.1:3000/health
curl -i http://127.0.0.1:3001/health
# 2. 经反代可访问
curl -i http://<反代地址>/health
# 3. 管理端页面可打开(应返回 HTML)
curl -i http://<反代地址>/ | head -5
# 4. 前端深链接可用(应返回同一份 HTML,而不是 404)
curl -i http://<反代地址>/songs | head -5
# 5. API 可用
curl -i http://<反代地址>/api/catalog/version
# 6. 上传上限已放开:找一个小于 UPLOAD_MAX_BYTES 的文件试传
# 若返回 413 说明代理层限制没改
```
| 现象 | 原因 |
|--|--|
| 反代 502 / 504 | 后端未启动,或 `HOST` 绑定地址不对(同机应为 `127.0.0.1`,异机应为 `0.0.0.0`) |
| 页面能开、接口 404 | 只转发了 `/`,需要把 `/api/`、`/health`、`/static/` 一并转发(最简单是全匹配) |
| 上传大文件 413 | 代理层上传上限没放开(见第三、四、五节) |
| 上传中途断开 | 代理超时太短 |
| `/songs` 直接访问 404 | SPA 回退被代理拦截;本服务已处理,代理**不要**自己加 `try_files`,全匹配转发即可 |
| 客户端接口全 404 | 把客户端的转发规则指到了管理端口之外,或误把 `/api` 前缀重写掉;客户端应转发到软件 API 端口 |
| 管理页面 404 | 把浏览器的转发规则指到了**软件 API 端口**(该端口不提供管理页面,这是有意设计);改指 `ADMIN_PORT` |
| 两个端口都转发到同一条规则 | 若确实想合并两个端口,设置 `ADMIN_PORT=PORT` 走单端口模式,而不是让反代去猜 |
## 八、还没有反代时:直连后端怎么访问
在运维侧配好反代之前,可以直接访问后端业务服务(本项目开箱即用,不依赖反代):
1. `deploy/.env` 中 `HOST=0.0.0.0`(若只想让某个网段访问,也可填具体网卡地址)
2. 防火墙放行后端端口(默认 `3000/tcp`)
3. 浏览器访问 `http://<服务器IP>:3000`
> 注意:服务默认在 **3000** 端口,不在 80/443。直接访问 `http://<服务器IP>/`
> 是打不开的--那需要反代把 80/443 转到 3000,属于本节的配置范围。
一条命令定位「服务起来了但外部访问不了」:
```bash
bash deploy/check-access.sh # 只读诊断,不改配置
bash deploy/check-access.sh /opt/opendance # 指定安装目录
```
脚本会打印 `.env` 中的 `HOST`/`PORT`、实际监听地址(重点看是否只监听
`127.0.0.1`)、回环与对外 IP 两次自测结果、80/443 上有没有反代、
firewalld / ufw / iptables 的放行情况,并直接给出修复命令。