安装
在 DeepSeek Harness 里通过 dsh-market 安装
dsh plugin --profile web add dshmarket
或使用命令行
dsh plugin --profile web add dsh-auth-tunnel
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 中文
无需修改 deepseek-harness,即可通过带共享密码保护的 Cloudflare Tunnel 公网访问 DeepSeek Harness Web GUI。
使用
前置条件
dshCLI 和 pnpm 已加入PATH;Web profile 不存在时,插件命令会自动创建。cloudflared已加入PATH,或在插件中配置其绝对executable路径。- 一个以 DSH 凭据保存的长随机共享密码。
安装
从 npm 安装最新发布的预览版 bundle:
dsh plugin --profile web add dsh-auth-tunnel@next
也可以从 Git 安装当前源码:
dsh plugin --profile web add github:ai-eks/dsh-auth-tunnel
当前源码分支适配 DeepSeek Harness 0.1.7-rc.2,使用新版实时 Config、配置表单和插件详情页接口。更早的 Harness 版本必须固定安装兼容的包版本、不可变 tag 或 revision:
dsh plugin --profile web add dsh-auth-tunnel@0.1.7-rc.1 # Harness 0.1.7-rc.1
dsh plugin --profile web add dsh-auth-tunnel@0.1.5-rc.1 # Harness 0.1.2-rc.1 / 0.1.3-alpha.2 / 0.1.5-rc.1
dsh plugin --profile web add dsh-auth-tunnel@0.1.1-rc.2.1 # Harness 0.1.1-rc.2
dsh plugin --profile web add 'github:ai-eks/dsh-auth-tunnel#v0.1.0-rc.8' # Harness rc.8
dsh plugin --profile web add 'github:ai-eks/dsh-auth-tunnel#b4baea7c47f5c245da789d3553d41938df89b311' # Harness rc.7
dsh plugin --profile web add 'github:ai-eks/dsh-auth-tunnel#v0.1.0-rc.6' # Harness rc.6
Git 安装通过 prepare 构建检出的源码。pnpm 10 及以上版本可能先要求允许该构建;按照 dsh 打印的 profile pnpm-workspace.yaml 路径和准确包名配置后,重新执行命令。
使用本地 checkout 时,先构建再添加路径:
cd /path/to/dsh-auth-tunnel
pnpm install
dsh plugin --profile web add .
该 bundle 会以 quick 模式插入并启用 auth-tunnel 行,同时把 Host 原生目录选择器替换为应用内浏览器选择器。不需要修改 deepseek-harness 源码,也不需要额外添加 profile 行。
Quick 模式
Quick 是默认模式。把共享密码写入 $DSH_HOME/.credentials.yaml($DSH_HOME 默认为 ~/.dsh):
DSH_WEB_PASSWORD: 'replace-with-a-long-random-password'
启动 Web profile:
dsh web
在配置 DSH_WEB_PASSWORD 前启动不再导致 Web profile 失败。插件会保持挂载并显示错误状态;添加该凭据后,隧道会自动启动。
隧道就绪后,终端会打印:
cloudflare tunnel: https://<random>.trycloudflare.com
打开这个 URL,在登录页输入 DSH_WEB_PASSWORD 对应的密码。只分享 URL,不要分享密码。启用的行也会显示在 Web Plugins 中。
Web 设置
保持 Loader 的 auth-tunnel 行启用后,打开 插件 → dsh-auth-tunnel 即可编辑全部配置。页面中的 启用公网隧道 开关保存后会立即启动或停止密码门和 cloudflared,并保留这张设置卡片。页面同时显示应用中、运行中、已停止或失败状态以及当前公网 URL。
允许远程页面修改设置 默认开启。共享访问密码是管理员凭据:通过密码登录的公网页面无需本地设置,即可读取和保存 Auth Tunnel 卡片及语言偏好。如果不希望已认证公网页面管理隧道本身,可关闭该开关;之后重新开启必须使用本机页面或设置文件。这些写入走插件自有的鉴权接口,配置变更保存到当前 profile 的 cordis.patch.yml。该开关与核心 Host 配置面是两道独立的围栏:gate 把 settings.*、credentials.* 与 llm.* 对每个已认证公网页面直接代理到 Host,但会拒绝核心 settings API 对 auth-tunnel namespace 的写入,这类写入必须经过有围栏的插件接口;bundle 的立即启动客户端会在配置表单判断浏览器类型前发布这条已认证路径。公网 GUI 因此与本机 GUI 保持完整的配置面一致性——响应只返回脱敏值,密钥只随写入载荷单向流出。同一时刻只接受一个远程写入;前一项配置仍在应用时,新的写入会返回冲突,页面重新读取后即可重试。远程页面不能保存会分配全新随机 Quick URL 的变更(切换到 Quick,或修改 Quick 的 Gate 端口或可执行文件);请在本机页面完成这类修改,以便获取新地址。从远程页面关闭该开关时,本次保存会完整返回后再关闭访问。
页面通过独立的 更新密码 按钮写入当前已保存的 passwordRef 凭据,访问密码与配置不会放在同一次提交里。Token 模式可直接粘贴 Tunnel Token,它会随 保存配置 单向写入 tokenRef 指向的凭据;默认引用为 DSH_TUNNEL_TOKEN。两种密钥输入成功后都会立即清空,Host 和页面都不会回传或展示明文。若要更换 passwordRef,请先创建目标凭据并保存引用,再单独更新密码。
| 关联配置 | Quick | Token |
|---|---|---|
| 访问密码 | 必需;两种模式共用,通过只写按钮单独更新 | 必需;两种模式共用,通过只写按钮单独更新 |
| Tunnel Token | 不需要 | 必需;可在页面直接粘贴,保存到 tokenRef 指向的凭据 |
| 公网主机名 | 不需要;自动获得临时 trycloudflare.com 地址 |
必需;填写 Cloudflare 已绑定域名 |
| Gate 端口 | 建议 0,自动分配 |
必须固定为 1–65535,并与 ingress 一致 |
页面保存的配置会自动应用,无需重启 DeepSeek Harness。passwordRef 和 sessionTtlHours 原地更新;mode、tokenRef、gatePort 或 executable 等隧道级变更会先启动候选实例,再替换插件自己的密码门或 cloudflared。候选实例启动失败时,页面会显示错误并保留旧隧道;切换成功时公网页面可能短暂断开,请打开新显示的地址,重新读取后再重试失败操作。切换回 Quick 模式时会保留 Token 模式字段,方便之后切回;Quick 模式会忽略这些字段。日常启停应使用页面开关;设置 Loader disabled: true 会卸载 Host 的 auth-tunnel 设置命名空间和卡片本身。
命名隧道模式
公网域名需要保持稳定时使用 token 模式。在 Cloudflare 创建命名隧道,绑定 gui.example.com 之类的域名,并让 dashboard ingress 指向固定 loopback 密码门,例如 http://127.0.0.1:7677。
可以在 Web 设置卡片直接粘贴 Tunnel Token。也可以预先把两个凭据写入 $DSH_HOME/.credentials.yaml:
DSH_WEB_PASSWORD: 'replace-with-a-long-random-password'
DSH_TUNNEL_TOKEN: 'eyJhIjo...'
在 $DSH_HOME/profiles/web/cordis.patch.yml 中覆盖 bundle 行:
- id: auth-tunnel
disabled: false
config:
enabled: true
mode: token
tokenRef: DSH_TUNNEL_TOKEN
publicHostname: gui.example.com
gatePort: 7677
publicHostname 只能填写 DNS 主机名,不能带 https://、端口或路径。配置和 Tunnel Token 都可以在上述 Web 设置卡片中完成并立即应用;Token 只进入凭据服务,不会写入 settings 或回显。修改 gatePort 后,仍需确保 Cloudflare Dashboard ingress 指向相同端口。
配置参考
| 键 | 类型 | 默认值 | 作用 |
|---|---|---|---|
enabled |
boolean | true |
是否运行密码门和 cloudflared;页面保存 false 后立即停止公网访问但保留设置页面。 |
allowRemoteSettings |
boolean | true |
是否允许已认证公网页面更新 Auth Tunnel 配置、只写访问密码和语言偏好。 |
passwordRef |
string(credential-ref) | DSH_WEB_PASSWORD |
解析共享访问密码的凭据引用;未配置时插件保持挂载,添加凭据后自动启动。 |
sessionTtlHours |
number ≥ 0.01 | 720 |
Cookie 有效期,单位为小时,默认 30 天。 |
mode |
quick | token |
quick |
临时 quick 隧道或命名 token 隧道。 |
tokenRef |
string(credential-ref) | DSH_TUNNEL_TOKEN |
Tunnel Token 凭据引用;仅 token 模式。 |
publicHostname |
DNS hostname | — | 不带 scheme、端口或路径的命名隧道主机名;仅 token 模式。 |
gatePort |
integer 0…65535 | 0 |
loopback 密码门端口;token 模式要求固定的非零值。 |
executable |
string | cloudflared |
cloudflared 的 PATH 名称或绝对路径。 |
startupTimeoutMs |
integer ≥ 1 | 15000 |
激活等待隧道就绪的最长时间。 |
已知限制
- 共享密码、单管理员信任:每个密码持有者都被视为管理员,默认可访问完整 Web GUI、Auth Tunnel 卡片、只写密码输入和语言偏好。关闭
allowRemoteSettings会移除这些插件自有控件,但不会限制核心 Host 配置面(settings、credentials、LLM 目录),该配置面仍对每个已认证公网页面直接代理到 Host。响应已脱敏,密钥只随写入载荷单向传输。当前没有速率限制、锁定、按用户会话或服务端吊销表。请勿将该密码分享给低信任访客;更严肃的部署应使用 Cloudflare Access 或其他身份感知代理。轮换密码会使所有会话失效。 - 单隧道、无自动重启:
cloudflared意外退出时会记录并显示错误,但不会自动重启;在页面关闭再开启隧道即可恢复。 - Quick URL 每次启动都会变化:需要固定 URL 时应使用 token 模式和自有域名。
- 保留本机 DSH 认证:共享密码保护隧道路径;直接访问原始 Web GUI 时,使用
dsh web输出的带 Token 地址及 DSH 浏览器会话。 - 子进程环境最小化:只继承
PATH、HOME和TMPDIR;公司代理应在插件之外为cloudflared配置。 - Loopback HTTP 是明文:密码门和上游 WebServer 通过同主机 loopback HTTP 通信;TLS 在 Cloudflare 终结。
- 每次启动只有一种目录选择器交互:启用 bundle 后,本机客户端也使用应用内浏览器选择器,因为 Web 应用不能按连接分别选择原生和浏览器选择器。
工作原理
public client
→ Cloudflare edge (TLS)
→ cloudflared (this host)
→ password gate, loopback only
→ existing loopback WebServer
密码门与代理
插件依赖 webServer、credentials、settings 及 Host connection 服务。它启动一个自己的 loopback node:http 密码门,解析配置的密码引用,再让 cloudflared 指向这道门。原始 WebServer 以及其他插件贡献的所有路由都原样保留在门后。
未认证的浏览器导航会重定向到 /dsh-auth-tunnel/login;其他未认证请求返回精简的 401。登录成功后签发 HttpOnly; SameSite=Strict 的 dsh_auth_tunnel Cookie,使用从密码派生的 HMAC 密钥签名。已认证导航还会刷新可读的 dsh_auth_tunnel_surface=1 标记,它只负责让客户端在设置插件启动前识别 tunnel 路径,不授予任何访问权限;Gate 仍会在每个请求上校验 HttpOnly Cookie。每次请求都会重新解析凭据,因此轮换密码会立即使已有会话失效。GET 或 POST /dsh-auth-tunnel/logout 会清除两个 Cookie。
密码门把登录请求体限制为 16 KiB,并代理已认证的 HTTP 与 WebSocket 流量。它把 Host 和匹配当前主机的浏览器 Origin 改写为 loopback 上游地址,让 WebServer 的 DNS-rebinding 与同源检查继续看到可信地址;外来或不透明 Origin 保持不变。HTTP 两段代理都会删除逐跳头并按连接重新生成,升级握手则保留协议需要的字段。客户端断开时,对应的上游请求也会取消。
校验公网密码 Cookie 后,Gate 通过 Host connection 的 Token 兑换接口取得私有 DSH 浏览器 Cookie,并在上游 HTTP 和 WebSocket 请求中使用。DSH 启动 Token 和浏览器 Cookie 仅保留在服务端;公网响应会过滤同名的上游 Set-Cookie。DSH Cookie 过期时独立续期,不要求仍有效的公网会话重新登录。
唯一不需要认证的上游应用路由是只读的 GET/HEAD /manifest.webmanifest。除非页面明确要求带凭据获取 manifest,否则浏览器不会为这类请求携带凭据;该文件只包含公开的应用元数据。
安装或升级客户端插件后需要刷新页面,以便在配置表单初始化前识别隧道。重新加载 Host connection 服务也会重启依赖它的隧道插件;Quick 模式可能获得新地址。
目录选择器
bundle 会禁用启动时选择的原生目录选择器,并挂载应用内目录浏览器。公网 host.pickDirectory 无法操作 Host 显示器上的系统弹窗,否则会一直等待到 Cloudflare 返回 524。浏览器选择器无需按接口打补丁,即可同时服务本机和公网客户端。
隧道生命周期
- quick 执行
cloudflared tunnel --url http://127.0.0.1:<gate>,并从子进程输出读取生成的*.trycloudflare.comURL。 - token 通过子进程环境变量
TUNNEL_TOKEN传递 Tunnel Token,执行cloudflared tunnel run,并等待连接注册标记。token 不会出现在 argv 中。
通常只有密码门开始监听且隧道报告就绪后,初次插件激活才会完成。访问密码凭据未配置是可恢复的例外:插件会保持挂载,状态显示错误且 running: false,不启动密码门或 cloudflared,不发布公网 URL;配置该凭据后会自动重试。如果初次激活时访问密码已配置,模式或 Token 凭据无效、密码门端口被占用、可执行文件缺失、子进程提前退出或等待超时,都会在公布公网 URL 前让初次加载失败。如果这些故障在初始缺少访问密码后的异步重试中才被发现,已挂载的插件会改为通过设置页错误状态报告。运行期间的配置变更会串行合并;需要重建时先启动新资源,成功后再替换旧资源,失败则保留旧隧道并通过设置页状态接口报告。拆卸或页面关闭时会关闭密码门,向 cloudflared 发送 SIGTERM,必要时在 2000 ms 后升级为 SIGKILL,并移除 shell 与提示词贡献。
模型体验
隧道就绪后,插件通过可选的 shell-env 服务发布 DSH_PUBLIC_URL,并通过可选的 system-prompt 服务添加 app:public-access 提示段。没有这行插件时,两项贡献都不存在。
提示段渲染为:
This instance is also reachable from the public internet at <publicUrl> through a Cloudflare Tunnel, protected by the instance's shared access password. Share that URL — never the password — when the user asks to open this GUI from another device or network. All sessions, tools, and files still run on this host.
该提示段在隧道进程存活期间保持静态,不会使跨轮 KV cache 失效。
评论
评论存放在 GitHub Discussions。用 GitHub 账号登录后可发表评论或点表情。