DeepSeek Harness 公网访问怎么配?public-url、trusted-host 与 TLS 三件套
DeepSeek Harness 的公网访问要同时配三样:--public-url 负责公告外部地址,--trusted-host 负责放行浏览器 authority,TLS 负责加密与 Secure cookie。 三者不是替代关系。只配 public-url,所有 API 会 403;只配 trusted-host,打印出来的地址还是错的;只配 TLS,子路径部署仍会在 cookie 上翻车。这篇按“公告 → 放行 → 代理配合”讲清顺序。
DeepSeek Harness:--public-url 公告什么、不公告什么
--public-url 只影响对外展示,不改变监听器实际提供的路由。 官方给的范围很具体:(来源)
| 被公告的位置 | 用途 |
|---|---|
| 启动时打印与自动打开的 URL | 让你直接复制到浏览器 |
DSH_WEB_URL | 给外部脚本与集成读取 |
| agent 运行时上下文中的 Web GUI URL | 让 Agent 知道外部入口 |
它接受 http:// 或 https:// 根,可以带挂载前缀,并会归一化成以 / 结尾。监听器仍然只提供 origin-root 路由,从不理解 /ui 这类挂载段。换句话说:public-url 是“告诉别人我在哪”,不是“让监听器搬到那个路径下”。
最常见的错误是把 --public-url 当成信任授权。官方写得很清楚:公告 URL 与栅栏是两件事,公告不等于接纳。
DeepSeek Harness:--trusted-host 放行哪个 authority
浏览器使用的 authority 只要不在栅栏名单里,每个 /api 调用都会 403,代理配得再正确也没用。 栅栏默认接受三类来源:(来源)
- loopback — 本机直接访问
127.0.0.1或localhost。 - 监听器自身的绑定地址 — 监听在哪个地址,就接受哪个地址。
--trusted-host列出的条目 — 可重复传入,不带端口时匹配任意端口,适合每次绑定不同端口的隧道。
配置时按下面做:
dsh web \
--public-url https://app.example/ui/ \
--trusted-host app.example
- 先确认浏览器地址栏的 authority — 是
app.example还是app.example:8443。预期:填进--trusted-host的值与实际访问完全一致。 - 不带端口就匹配任意端口 — 隧道场景可以只写主机名。预期:端口变化后不必改参数。
- 重启后复验 — 打开带令牌的地址,再打开开发者工具看
/api请求。预期:不再出现 403;若仍是 403,检查是不是代理改写了 Host。
栅栏只负责放行请求,真正的认证仍由启动令牌与签名会话 cookie 完成。TLS 在哪里终止都不改变这套判断。
DeepSeek Harness:反向代理必须配合的五件事
代理不是“转发一下”就完了;官方列了五项硬要求,漏任何一项都会表现成登录失败或接口 403。 逐项核对:(来源)
- 保留浏览器可见的
Host— 栅栏拿收到的 Host 与 authority 比对,代理不要改写成监听器地址。预期:后端日志里看到的 Host 是外部域名。 - 剥离挂载前缀 — 监听器应答 origin-root 路由,
/ui/api/...必须以/api/...抵达。预期:代理规则里只有转发前 rewrite,不在后端加前缀。 - 转发升级请求 — 页面发出的每个请求与 WebSocket 升级都要带
Upgrade与Connection头抵达监听器。预期:实时连接不断开。 - 改写 cookie 作用域 — 后端签发的是
Path=/的 host-only cookie;代理要把Path改成/ui/,并只在 HTTPS 链路上补Secure。预期:浏览器只在该子路径回传 cookie。 - 重定向裸挂载 —
/ui要以/ui/抵达;只有/ui/会把启动 token 换成会话 cookie,持有 cookie 后/ui/index.html也能取文档。预期:访问/ui不会 404。
这五项里,第 1 项和第 4 项最容易漏。前者导致 403,后者导致“登录成功但下一页又回登录页”。
DeepSeek Harness:Host、裸挂载与 cookie 的三个细节
这三处最容易在“页面能开”之后才暴露,且都不属于 TLS 握手问题。 逐项看:(来源)
- Host 必须原样保留 — 栅栏拿收到的 Host 与 authority 比对;代理改写成监听器地址后,外部域名就不在名单里。预期:后端看到的是浏览器地址栏里的 authority。
/ui必须变成/ui/— 只有/ui/会把启动 token 换成会话 cookie;已持有 cookie 的浏览器也能用/ui/index.html。预期:访问裸挂载不会 404。- cookie 的 Path 与 Secure 分开处理 — 后端签发
Path=/的 host-only cookie;代理改 Path 为挂载路径,并只在 HTTPS 链路上补 Secure。预期:浏览器只在子路径回传 cookie,且不会通过 HTTP 泄露。
还有一个边界:公告 URL 与栅栏都不保护监听端口。端口必须限制在可信代理或内网内,不能因为“有 TLS”就认为可以裸奔。
DeepSeek Harness:TLS 与 cookie 的三种组合
TLS 可以终止在代理、终止在监听器,或两者都终止;区别在于 Secure 由谁加、cookie 的 Path 由谁改。 三种组合:(来源)
| 组合 | 证书在哪 | cookie 处理 |
|---|---|---|
| 代理终止 TLS | 代理 | 代理改 Path,并在 HTTPS 链路补 Secure |
| dsh web 原生 TLS | 监听器 | 监听器直接签发带 Secure 的 cookie,代理只改 Path |
| 两端都终止 | 代理与监听器 | 两段都加密,按各自链路分别处理 |
原生 TLS 用 --tls-cert 与 --tls-key,证书要带完整链、私钥不带口令,文件只在启动时读一次。它不会自动续期,也不会监视文件变化;换证书要重启或重新加载监听器。
无论哪种组合,面向浏览器的外部链路都应是 HTTPS。用 http:// 根会明文暴露启动令牌,而令牌就是进程凭据。
DeepSeek Harness:上线前的检查清单
把“能打开”与“能正常用”分开验证,才不会把 403 误判成 TLS 问题。 按下面顺序过一遍:(来源)
- 本机直连 —
curl -vk https://127.0.0.1:3080/。预期:TLS 握手成功。 - 代理转发 —
curl -v https://app.example/ui/。预期:返回页面,不出现 502。 - 检查响应头 — 看
Set-Cookie的Path与Secure。预期:Path 是/ui/,HTTPS 下有 Secure。 - 看 API — 浏览器开发者工具里挑一个
/api请求。预期:200,不是 403。 - 看 WebSocket — 观察实时输出是否持续刷新。预期:连接保持,不反复重连。
如果第 1 步通过、第 2 步通过、第 4 步 403,基本就是 --trusted-host 或 Host 改写;如果第 3 步 cookie 不对,就是代理的 Path/Secure 改写漏了。
DeepSeek Harness 常见问题
Q:--public-url 能不能只写域名不写协议?
不能。官方要求 http:// 或 https:// 根;缺协议时无法归一化,也无法正确生成外部 URL。
Q:能不能用 IP 访问?
可以,但 --trusted-host 要写浏览器实际使用的 IP authority,证书也要覆盖该 IP,否则名称校验会失败。
Q:栅栏会不会保护监听端口? 不会。官方明确说,公告 URL 与栅栏都不保护监听端口本身;端口应限制在可信代理或内网内,不要直接暴露到公网。
一句话收束: 公网访问不是“加个反代”就完事,而是公告地址、信任名单、TLS 与 cookie 路径四件事对齐;403 先查 authority,登录循环先查 cookie Path。
常见问题
DeepSeek Harness 里,--public-url 只公告外部访问地址,影响打印的启动 URL、DSH_WEB_URL 与 agent 运行时上下文;--trusted-host 才决定 /api 信任栅栏放行哪个浏览器 authority。只配 public-url 不会让请求通过栅栏,未列入 trusted-host 的域名仍会收到 403。
DeepSeek Harness 里,代理要原样保留浏览器可见的 Host,剥离 /ui 前缀后再转发到监听器,转发 Upgrade 与 Connection 头,把 cookie 的 Path 从 / 改写为 /ui/ 并在 HTTPS 链路上补 Secure,还要把 /ui 重定向到 /ui/,否则启动令牌无法换成会话 cookie。
DeepSeek Harness 里,这是信任栅栏在拦,不是认证失败。栅栏只接受 loopback、监听器绑定地址和 --trusted-host 列出的 authority;浏览器通过其他域名访问时,即使代理与 TLS 都正常,每个 API 调用也会 403。把地址栏里的 authority 原样加进 --trusted-host 再重启。
DeepSeek Harness 里,两种都支持。交给代理适合统一域名、WAF 与多后端;让 dsh web 用 --tls-cert/--tls-key 自己终止适合单入口部署。无论谁终止,TLS 监听一侧都会给会话 cookie 加 Secure,浏览器侧链路应保持 HTTPS。
DeepSeek Harness 里,面向浏览器的 http:// 根会明文暴露启动令牌。启动令牌能换取会话 cookie,等于进程凭据;应使用 https:// 的外部根,并且不要把带 token 的打印地址转发给非预期用户。
相关术语
- --public-url
- --public-url 是 dsh web 的公告参数,接受可带挂载前缀的 http:// 或 https:// 根并归一化为以 / 结尾;它只影响对外展示与运行时上下文,不改变监听器提供的 origin-root 路由。— DeepSeek Harness 官方文档 - 在反向代理之后发布 Web UI
- 信任栅栏
- 信任栅栏是 dsh web 对 /api 请求做的 Host 与 authority 校验,只接受 loopback、监听器绑定地址以及 --trusted-host 列出的条目;不匹配时所有 API 调用返回 403。— DeepSeek Harness 官方文档 - 在反向代理之后发布 Web UI
- 挂载前缀
- 挂载前缀是反向代理把 Web UI 暴露在子路径(例如 /ui/)时使用的路径段。监听器只提供 origin-root 路由,因此代理必须在转发前剥离该前缀。— DeepSeek Harness 官方文档 - 在反向代理之后发布 Web UI
- 启动令牌
- 启动令牌是 dsh 进程每次启动生成、只打印一次的凭据,访问带 token 的根地址会把它换成签名会话 cookie;令牌不持久化,也不应转发给非预期用户。— DeepSeek Harness 官方文档 - 在反向代理之后发布 Web UI
来源
- DeepSeek Harness 官方文档 - 在反向代理之后发布 Web UI· deepseek-ai
- DeepSeek Harness 官方参考 - HTTP 服务器· deepseek-ai