域名和反向代理
通过域名(尤其是 HTTPS)而非 IP 地址提供 Studio 服务的配置。 本章必须按顺序全部完成。 缺少任何一项都会导致各种表面上看似无关的症状: "预览显示空白页面"、"构建聊天连接错误"、"部署应用数据返回 401" 等。
只有一个域名
预览和部署应用在 Studio 同一域名下的 /container/ 路由提供。
https://studio.company.com/ → 스튜디오 UI + API
https://studio.company.com/container/… → 프리뷰 · 배포앱
所需资源为 1 条 DNS 记录、1 张证书、1 个虚拟主机。
2026-08-23 之前,应用托管在独立主机(studio-apps.company.com)上,需要通过
APPS_ORIGIN 或环境配置的"应用源"告知其地址。这个配置已被移除。
移除的原因是该值一旦为空,服务器会生成 요청호스트:5171 格式的预览 URL,
在只暴露 80/443 的反向代理环境中,浏览器无法访问,导致实时预览完全变成空白页。
仅使用相对路径则不存在出错的可能。
.env 或环境配置中残留的旧 APPS_ORIGIN 值现在被忽略。
预览和部署应用的内容来自聊天生成的代码,属于不可信内容。过去的架构通过源隔离阻止其 JavaScript 访问 Studio 登录令牌。现在它们运行在同一源失去了这种隔离。 这是缩减为单域名的设计取舍。
因此不要将应用创建权限授予不可信的用户。此架构基于仅向内部运维人员授予构建者角色的前提。
准备清单
- DNS A 记录 1 条
- 该主机名的 TLS 证书
- 反向代理能到达 Studio 主机的 :80 端口
- Studio 主机防火墙允许代理 → :80 的流量
应用监听端口(:5171)由 Studio 主机内的 web nginx 通过 /container/ · /apps/ · /preview/
转发,无需向外暴露。仅在不使用反向代理、直接通过端口访问的部署中打开防火墙。
1. 在代理中添加虚拟主机
外层代理只需将所有流量转发到 Studio 主机的 :80。/container/ ·
/apps/ · /preview/ 的路由分支已由主机内的 web nginx 处理。
必须配置的 4 项
这些项遗漏时症状各不相同,难以排查。建议直接复制下方示例使用。
| 配置项 | 缺少时的症状 |
|---|---|
proxy_set_header Host $http_host | 路由和链接生成错误 |
Upgrade / Connection 头 | 预览实时更新(HMR) WebSocket 断开,代码修改不会显示在屏幕上 |
proxy_read_timeout 3600s | 构建聊天显示"连接错误: network error" — 代理工具执行时保持沉默超过 60 秒后会断开流 |
proxy_buffering off | 流式响应缓冲,答案会大批量延迟才显示 |
构建聊天和问答通过 SSE 实时传输。服务器每 25 秒发送一次心跳,
代理超时只要超过这个时间即可,但**3600s 是生产环境验证过的值**。
nginx 配置示例
server {
listen 80;
server_name studio.company.com;
location / {
proxy_pass http://<studio-host>:80;
proxy_http_version 1.1;
proxy_set_header Host $http_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 Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s; # 에이전트 SSE(빌드 채팅) — 필수
proxy_buffering off; # 스트리밍 즉시 전달 — 필수
client_max_body_size 64M; # 사진·도면 첨부
}
}
HTTPS 通过 certbot 等工具申请 — listen 443 ssl 块可直接继承上述配置。
如果直接将虚拟主机文件挂载到打包的 web nginx 容器的 conf.d,
文件名必须以 zz- 开头。nginx 按字母序将第一个 server 块作为默认服务器,
文件名靠前会导致所有不匹配的请求都被错误路由,
造成 Studio 整体故障(这曾发生过实际事故)。
2. 重新登录(必须)
配置完域名后所有用户必须登出后重新登入一次。
登录 Cookie 在签发时绑定到特定主机。之前用 IP 登录的会话在切换到域名后无法传递, 数据请求会返回 401 失败。
3. 检验
| 检验项 | 操作 |
|---|---|
| Studio 正常启动 | 访问 https://studio.company.com → 登录 |
| 预览正常显示 | 打开项目 → 预览面板出现,控制台无 Mixed Content 错误 |
| 应用路由畅通 | 访问 https://studio.company.com/container/ → 显示 404 或应用列表表示正常(已连接) |
| 实时更新 | 在聊天中修改一句文本 → 预览自动刷新 |
| 长期构建 | 运行 1 分钟以上的构建聊天 → 无"连接错误"完成 |
| 部署应用数据 | 打开已部署应用 → 显示真实数据(无 401) |
注意事项
配置域名后仅通过域名访问。通过 IP 访问的用户会获得不同的 Cookie, 导致部署应用数据返回 401。
- WebSocket 默认支持,无需额外配置。
- 免费通用证书仅覆盖一级子域名(
studio.company.com✅,apps.studio.company.com❌)。
聊天中上传现场照片和图纸,需要设置 client_max_body_size 64M。
缺少此项会导致大文件上传返回 413 错误。
不使用反向代理仅使用 HTTPS
如果没有独立代理服务器,在 Studio 主机直接终止 TLS,使用运维包的 TLS 覆盖层。
cd /opt/kopens/plantpulse-studio-docker
cp tls/nginx-tls.conf.example tls/nginx-tls.conf # server_name 등 수정
# tls/cert.pem, tls/key.pem 배치(사내 CA 또는 공인 인증서)
docker compose -f docker-compose.yml -f docker-compose.tls.yml up -d
tls/nginx-tls.conf.example 中缺少 /container/ 块,注释仍建议已移除的
APPS_ORIGIN 和独立端口(5443)。直接使用会导致预览和部署应用地址
(/container/…) 返回 404。
暂时应复制该文件(tls/nginx-tls.conf),手动添加 /container/ 块 — 使用上方
nginx 配置示例 中的 4 种头,去掉前缀后转发给应用监听器。
不要加入 APPS_ORIGIN 行(被忽略)。
症状 → 原因 快速对照
这些是域名部署时实际常遇到的问题。更全面的内容见 故障排查。
| 症状 | 原因 | 处理 |
|---|---|---|
预览和部署应用显示空白,控制台出现 Mixed Content | Studio 使用 HTTPS,应用资源却请求 HTTP | 代理添加 X-Forwarded-Proto $scheme,转到全 HTTPS |
| 部署应用实数据返回 401 | 配置域名前的登录会话 | 登出后重新登入 1 次 |
| 构建聊天耗时长会显示"连接错误: network error" | 代理无传输超时(默认 60 秒) | 配置 proxy_read_timeout 3600s |
| 代码修改不显示在预览中 | HMR WebSocket 升级失败 | 添加 Upgrade / Connection 头 |
| 答案大批量延迟显示 | proxy_buffering 启用(默认) | 关闭 proxy_buffering off |
| 任意域名都被错误路由 | web nginx conf.d 加载顺序(第一个 server 为默认) | 虚拟主机文件名以 zz- 开头 |
/container/… 返回 404 | TLS 覆盖层副本缺少 /container/ 块 | 参考上方警告 |
| 直接端口部署中应用无法打开 | 防火墙阻止 5171 | 开放防火墙后用 curl -I http://<host>:5171/ 验证 |