DeepSeek Harness 公网部署教程:反向代理、Public URL 与 TLS 怎么配
发布日期:2026-11-09 | 话题:DeepSeek Harness、公网部署、Nginx、TLS | 约 2,000 字
DeepSeek Harness(dsh)是 DeepSeek AI 在 2026 年开源的 Agent harness,其 Web UI 默认只监听 loopback,不能直接让公网浏览器访问。把 0.2.2-rc.1 部署到公网,需要同时处理三件事:用 --host 绑定本机地址、用 --public-url 公告外部地址、用 --trusted-host 接受浏览器 Host;再由反向代理完成 Host 保留、路径前缀剥离、WebSocket 升级转发和 cookie 作用域改写。默认端口 3080,通配 --host 会被拒绝;TLS 可在代理或监听器终止,启动 URL 含进程凭据,3080 不应直接暴露公网。本文给出一套可复制的 Nginx 配置、TLS 两种终止方式,以及启动凭据和端口边界的安全清单。

DeepSeek Harness 公网部署,是把默认只监听 loopback 的 Web UI 放到反向代理后面,通过 --public-url 公告外部地址、--trusted-host 接受浏览器 Host,并用 TLS 保护浏览器到服务端链路的一组配置。
一、先给结论:公网部署不是加一个 --host 0.0.0.0
截至 2026-11-04 发布的 0.2.2-rc.1,dsh --profile web 默认只监听 loopback,其他机器上的浏览器无法直接访问。官方 CLI 帮助把 --host 限定为“本机某个具体 IPv4/IPv6 地址”,通配地址会在启动时被拒绝;未启用 TLS 的非 loopback 监听还会在启动时警告。
所以公网部署要同时处理三层,而不是改一个参数:
一句话结论:--public-url 负责“告诉浏览器去哪”,--trusted-host 负责“让 DSH 接受这个浏览器”,监听地址负责“端口开在哪里”。三者不能互相替代。
二、先启动一个只给本机代理访问的 DSH
同机反向代理是最常见的部署方式。先让 DSH 绑定 127.0.0.1,只允许本机 Nginx 访问:
dsh --profile web \
--no-open \
--host 127.0.0.1 \
--port 3080 \
--public-url https://app.example/ui/ \
--trusted-host app.example这条命令里:
--no-open:服务器上没有桌面浏览器,避免启动时尝试打开页面。--host 127.0.0.1:只监听本机回环;公网入口交给代理。--public-url https://app.example/ui/:公告带/ui/前缀的外部地址,末尾斜杠会被归一化。--trusted-host app.example:接受浏览器可见的app.exampleauthority;不带端口时匹配任意端口。
如果 DSH 跑在容器里,官方示例是绑定容器自己的 Pod 地址,而不是通配地址:
dsh --profile web --no-open \
--host "$(hostname -i | awk '{print $1}')" \
--public-url https://app.example/ \
--trusted-host app.example注意:--public-url 只改变公告,不配置监听器、路由或 cookie 作用域。真正的外部链路归反向代理所有。
三、--trusted-host 配错,代理再对也是 403
DSH 的 /api 浏览器信任栅栏会比对请求的 Host。它接受三类 authority(也就是 host 或 host:port):loopback、监听器自身的绑定地址,以及每个由 --trusted-host 点名的值。
最常见的 403 来自代理把 Host 改写成了 127.0.0.1:3080。浏览器发的是 app.example,DSH 收到的是 127.0.0.1:3080,栅栏不匹配,于是每个 API 调用都返回 403。
因此代理必须保留浏览器可见的 Host,而不是改写成上游地址。--public-url 只是展示,不等于接纳;即使公告 URL 写对了,没有 --trusted-host 仍然会被拒绝。
四、反向代理必须做对的 5 件事
官方部署指南把代理职责列得很清楚。只要用路径前缀 /ui/,下面五项都要满足:
保留 Host:原样转发浏览器可见的
Host,不要改写成监听器地址。剥离挂载前缀:DSH 监听器只认 origin-root 路由,
/ui/api/...必须以/api/...到达后端。转发升级请求:每个请求和 WebSocket 升级都要带
Upgrade与Connection头。改写 cookie 作用域:后端签发的是
Path=/的 host-only cookie;代理要把Path改成/ui/,并在 HTTPS 链路上补Secure。重定向裸挂载:
/ui/是唯一入口,/ui必须 301 到/ui/,否则启动 token 无法换成会话 cookie。
一个可用的 Nginx 配置如下(proxy_cookie_flags 需要 Nginx 1.19.3+):
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name app.example;
ssl_certificate /etc/letsencrypt/live/app.example/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example/privkey.pem;
location = /ui {
return 301 /ui/;
}
location /ui/ {
proxy_pass http://127.0.0.1:3080/;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_cookie_path / /ui/;
proxy_cookie_flags ~ secure;
proxy_read_timeout 3600s;
}
}这段配置里,map 要放在 Nginx 的 http 上下文,server 块按你的站点配置放置;proxy_pass 末尾的 / 负责剥离 /ui/ 前缀,$http_host 保留浏览器 Host,map 让 Connection 在 WebSocket 升级时变成 upgrade,普通请求时变成 close。
如果代理终止 TLS,而 Nginx 到 DSH 是明文 HTTP,proxy_cookie_flags ~ secure; 这一行是必要的;如果浏览器侧也是 HTTP,就不要加,否则浏览器不会回传 cookie。

五、TLS 在哪终止:代理终止,还是监听器自己终止
DSH 支持两种 TLS 终止位置,二者不是互斥关系。
无代理、直接对公网提供 HTTPS 时,要绑定具体网卡地址,而不是 loopback:
dsh --profile web \
--host "$(hostname -i | awk '{print $1}')" \
--port 3080 \
--public-url https://app.example:3080/ \
--trusted-host app.example \
--tls-cert ./server-chain.pem \
--tls-key ./server-key.pemhostname -i 可能返回多个地址,命令只取第一个;请换成这台机器实际对外的网卡地址,仍然不能用通配地址。
证书文件要包含完整证书链,私钥必须是不带口令的 PEM。两个路径都相对进程工作目录解析;只传一个会报用法错误,两个都传才会启用 HTTPS。
DSH 不会获取、续期或监视证书,也不会回退到 HTTP。文件缺失、为空、PEM 无效或证书与私钥不匹配时,启动会直接失败。更换证书后要重新加载监听器或重启进程,因为证书只在绑定前读取一次。
证书的 SAN 必须覆盖浏览器实际访问的 hostname 或 IP;默认端口仍是 3080,--public-url 不会改变监听端口。
六、启动 URL 是凭据,端口是最后一道边界
打印出来的 dsh web: URL 带有进程凭据,只应发给预期用户。官方文档明确说:启动 token 会换成签名会话 cookie,之后的每个 API 方法和 WebSocket 流都要认证。
这意味着不要把启动 URL 贴到群里、工单里或公开文档里。需要隐藏 URL 行时,可以在 Web profile 的 web-runtime 配置里设置 printUrl: false;凭据不会出现在模型上下文或 DSH_WEB_URL 中,但已经拿到 URL 的人仍然可以完成登录。
另一个容易漏掉的边界是端口本身。--public-url 和 Host 栅栏都不保护监听端口,所以不要把 3080 直接暴露到公网。把 DSH 绑定在 127.0.0.1,只让本机代理访问;如果必须跨机,至少用防火墙或安全组限制来源。
例如把 DSH 跑在七牛云 QVM 上时,可以让 3080 只监听回环地址,公网只放行 443,再由 Nginx 转发到本机 3080。这样即使公告 URL 配错,攻击面也不会直接落到 DSH 的 HTTP 端口。

七、一套可复制的部署顺序
先在本机用
--host 127.0.0.1启动,确认https://app.example/ui/能打开。配
--public-url和--trusted-host,用curl -I检查 403 是否消失。配反向代理,重点检查 Host、
/ui/前缀、WebSocket Upgrade 和 cookie Path。在代理或监听器上启用 TLS,确认浏览器地址栏是 HTTPS。
用外部网络访问一次,检查登录、流式输出和长连接是否正常。
收紧端口:公网只开 443,3080 只对本机或代理网段开放。
把启动命令交给 systemd、supervisor 或容器编排托管,并记录证书续期方式。
如果只记一条:先让 DSH 留在 loopback,再把代理放到它前面;不要为了省事把监听地址改成通配地址。
常见问题
Q:--public-url 配了,为什么还是 403? A:--public-url 只公告地址,不授予信任。还要用 --trusted-host 点名浏览器可见的 authority,并确保代理没有改写 Host。
Q:能不能直接 --host 0.0.0.0 让外部访问? A:不能。DSH 明确拒绝通配地址,--host 只接受本机某个具体 IPv4/IPv6 地址;公网访问应通过反向代理。
Q:换了 TLS 证书,为什么还是旧证书? A:监听器只在绑定前读取一次证书和私钥,运行期间不会重新读取。更换文件后要重新加载监听器或重启进程。
Q:反向代理后 WebSocket 老是断? A:检查 Upgrade 和 Connection 是否转发,Host 是否保留,以及代理的读超时是否足够长。路径前缀场景还要确认 /ui/ 已被正确剥离。
Q:启动 URL 能直接发给同事吗? A:它包含进程凭据,只应发给预期用户。需要多人使用时,先确认认证和权限边界,必要时在代理层再加一层访问控制。
结语
DeepSeek Harness 的公网部署,难点不在“把端口开出去”,而在三个地址概念不要混淆:监听地址决定服务在哪,--public-url 决定浏览器看到什么,--trusted-host 决定 DSH 接受谁。把 DSH 留在 loopback、让代理处理 Host/前缀/WebSocket/cookie,再用 TLS 和端口边界收口,部署才算完整。
本文基于 DeepSeek Harness 0.2.2-rc.1(2026-11-04)官方文档与 Nginx 官方文档,写作时间为 2026-11-09。RC 版本行为可能变化,升级前请用 dsh web --help 复核参数。
参考资料
DeepSeek Harness v0.2.2-rc.1 发布说明:https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.2-rc.1
在反向代理之后发布 Web UI:https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/guide/public-deployments.zh.md
Web App 公开部署参考:https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/bundle/web-app/README.zh.md
HTTP 服务器配置:https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/web-server.zh.md
CLI 帮助:https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/cli-help.zh.md
Nginx WebSocket 代理:https://nginx.org/en/docs/http/websocket.html
Nginx proxy_cookie_flags:https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cookie_flags
云服务器 QVM:https://www.qiniu.com/products/qvm
七牛云Token Plan 企业订阅(低至1.2折):https://www.qiniu.com/ai/tokenplan
七牛云10亿 Token 免费送:https://www.qiniu.com/ai/model/qiniu/conatus-free