利用 Termux proot + caddy反代搭建 dsh 开发服务器

前言

使用 harness 工具时常常出现守在电脑前做"AI监工"的情况,目前市场上的 harness 工具如Codex,ClaudeCode提供移动客户端远程控制电脑的功能,但需要外部客户端且受限于网络环境。

Deepseek Harness 使用 Web 应用提供网页端的可视化界面,使得访问无需额外客户端,跨平台性好。恰好本人有台闲置的安卓手机,为了将其充分利用,决定将其作为一台能够运行 dsh 的服务器,允许在其它各类设备中通过浏览器访问。

Termux 配置

Termux 环境使用 proot 运行 Ubuntu 容器,优点是不用 Root ,缺点是无法提供真实的root环境,也无法使用 docker ,配置网络环境,使用 systemd 等。(proot 与安卓共享 Linux 内核,CPU性能损耗约为百分之二十;同时无法调用 GPU ,图形化性能差。如果想要实现更好的性能,请在 root 环境下使用 chroot)

解除子进程限制:安卓手机限制应用子进程数量,在adb命令中输入adb shell device_config put activity_manager max_phantom_processes 2147483647解除限制

配置Proot环境:

在 Termux 下

pkg update && pkg upgrade -y
pkg install proot-distro -y
# 安装 proot
proot-distro install ubuntu
# 安装 ubuntu 容器
proot-distro login ubuntu
# 进入容器
apt update && apt upgrade -y
apt install nodejs npm -y
npm install -g @deepseek-ai/dsh
dsh web
# 安装 dsh

利用caddy配置反代

dsh 只允许本地地址监听,且/api 请求的 Host 必须是回环地址或 --trusted-host 白名单,否则 403;同时明文 HTTP 会导致页面会报 crypto.randomUUID is not a function,我们使用 Caddy 转发流量,并用 header_upHost/Origin 改写为回环地址的方式绕过信任墙。

同时注意 proot 无 root 权限,因此无法占用 **0 到 1023 **的端口。

自签证书:

 mkdir -p /root/.dsh/certs
  openssl req -x509 -newkey rsa:2048 -nodes \
    -keyout /root/.dsh/certs/key.pem \
    -out /root/.dsh/certs/cert.pem \
    -days 3650 \
    -subj "/CN=dsh-web-lan" \
    -addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:192.168.1.133,IP:10.214.209.2"
# Caddy 内置 CA 在 PRoot 环境会产生 TLS 内部错误,这里用自己的自签证书

编辑 Caddyfile:

 {
        auto_https disable_redirects          #  防止 HTTP 重定向到 80 端口(proot 里没权限)导致启动失败
        servers {
                protocols h1                      # 强制 HTTP/1.1;否则 WebSocket 协商为 h2 后端不认
        }
  }

  http://:3080 {                             # HTTP 入口(仅本机用)
        reverse_proxy 127.0.0.1:3081 {
                header_up Host 127.0.0.1:3081      # 改写 Host,让 dsh 信任墙放行
                header_up Origin http://127.0.0.1:3081
        }
  }

  https://:8443 {                            # HTTPS 入口(暴露在局域网)
        tls /root/.dsh/certs/cert.pem /root/.dsh/certs/key.pem   # 自签证书
        reverse_proxy 127.0.0.1:3081 {
                header_up Host 127.0.0.1:3081
                header_up Origin http://127.0.0.1:3081
        }
  }

启动 Caddy

nohup caddy run --config /etc/caddy/Caddyfile >> /root/.dsh/logs/caddy.log 2>&1 &
# 注意没有systemd

注意

  • 这里直接监听所有网卡的流量,相当于把 dsh 服务暴露在所有的网络下,只在可信任网络下使用,否则应在 Caddy 层加 forward_auth / basic_auth 等访问控制。
  • 为了使得服务能够在公网下访问到,可以使用内网穿透工具,其中包括:
    • 使用 Ngrok 等工具直接获取公网URL,此时注意服务完全暴露在公网下,需要增设安全措施
    • 使用 ZeroTire 等 p2p 握手工具将相关设备加入到同一网络下,此时可以让 caddy 只监听 zt 网络,以避免局域网下的攻击。(这里需要在 Termux 的宿主安卓机中下载 APP 来实现)

配置dsh

在 Termux 环境下跑 dsh 很重要的一点就是 让dsh意识到自己在Proot环境中,以及目前环境存在那些限制

因此,我们可以让 dsh 自身为自己创建 skill ,约束其在该环境下的行为,并将其持久化。可以先让其探索当前环境,再撰写skill,重点考虑:

  • 无 systemd,开机自启如何配置?
  • 保证自身进程:自身进程如何守护?假如服务热更新,必须遵循严格的延迟重启模式。
  • 不能绑 <1024 端口,不能 mknod、不能写 /proc/sys、无 iptables

考虑到我们希望dsh在移动端也能够使用,可以安装插件(或让其开发)以适配移动端界面,现有插件项目:21hbguo/dsh-mobile-ui: DSH Web GUI 手机端 UI 适配插件:窄屏下全屏聊天布局(抽屉化侧栏/面板 + 顶部操作条 + 返回键退栈),桌面宽度零影响

end