把 DSH(DeepSeek Harness)部署到服务器:手机、电脑实时同步,云端开发

发布于

适用场景:你有一台服务器,想把 DeepSeek Harness 的浏览器界面(Web GUI)跑在上面,让家里的电脑、公司的电脑、甚至手机浏览器都能登录使用,用 AI 帮你写代码、跑任务。本文基于 DSH `0.1.0-rc.6` + Ubuntu 22.04/24.04 + nginx + pm2 的实际部署经验整理。

## 为什么需要服务器 + 反代
DSH 的 Web 界面(`dsh --profile web`)默认只监听 `127.0.0.1:3080`,而且出于安全考虑**禁止 `--host 0.0.0.0`**(CLI 直接报错:防止把远程代码执行能力暴露到公网)。所以正确姿势是:

```
浏览器(手机/电脑)──► nginx (80/443)──► dsh web (127.0.0.1:3080)
```

nginx 做反向代理 + 登录保护 + 移动端适配,DSH 本身只在本机回环地址提供服务。

---

## 架构总览
- dsh web:实际服务,监听 `127.0.0.1:3080`
- dsh-webui-auth 插件: 登录认证(未认证的浏览器拿不到任何资源)
- pm2: 守护进程 + 开机自启
- nginx: 对外入口,反代 + 移动端缩放 + manifest 直出

---

## 第一步:安装 DSH
需要 Node.js `^22.19.0 || >=24.0.0`:

```sh
npm install -g @deepseek-ai/dsh
dsh --version # 验证安装
```

## 第二步:初始化 web profile 并安装认证插件
`dsh --profile web` 首次运行时自动初始化 profile(目录在 `~/.dsh/profiles/web`)。先装登录认证插件(需要 pnpm,Node 自带 corepack):

```sh
corepack enable pnpm
npx @deepseek-ai/dsh plugin --profile web add dsh-webui-auth
```

之后启动 web 服务,首次访问登录页时创建你的账号密码(存在 `~/.dsh/profiles/web/node_modules/dsh-webui-auth/dsh-webui-auth.json`,密码是 scrypt 哈希):

```sh
dsh --profile web
```

### 补充:固定目录选择器为浏览器模式(服务器远程访问必做)
创建 `~/.dsh/patch.yml`:

```yaml
# 固定目录选择器为「浏览器浏览」模式。
# 默认的 directory-picker-auto 会根据服务器环境自动选择:
# - native:系统目录对话框,需要在服务器本机的显示器上操作;
# - browse:浏览器内的目录列表(可浏览/新建子目录)。
# 服务器通过 nginx 反代远程访问时,native 对话框会弹在服务器自己的屏幕上,
# 远程的手机/电脑根本看不到,必须固定为 browse。
# 注意:patch 无法直接改已有行的插件 name ,所以先禁用 auto 行,
# 再插入 browse 的主机端 + 客户端插件对。

- id: directory-picker
disabled: true

- insert:
- id: directory-picker-browse
name: '@deepseek-ai/dsh-host-directory-picker-browse'
- id: directory-picker-browse-ui
name: '@deepseek-ai/dsh-client-ui-directory-picker-browse'
```

启动时用 `--patch` 挂上(见第四步的启动参数)。如果服务器上确实没有 DISPLAY/chooser 环境,auto 也会选 browse,但显式固定可以保证任何环境下行为一致。

## 第三步:配置 API Key
在 `~/.dsh/.credentials.yaml` 写入:

```yaml
DEEPSEEK_API_KEY: sk-你的密钥
```

(或通过环境变量 `DEEPSEEK_API_KEY` 注入,二选一即可。)

## 第四步:pm2 守护 + 开机自启
写 pm2 配置 `~/.dsh/pm2.json`:

```json
{
"apps": [
{
"name": "dsh-web",
"script": "/usr/local/bin/dsh",
"args": "--profile web --patch /root/.dsh/patch.yml --trusted-host 你的域名",
"autorestart": true,
"restart_delay": 3000
}
]
}
```

> `--trusted-host 你的域名` 必须加:Web 界面调用 `/api` 时有浏览器信任围栏,通过域名访问时 Host 不再是 `127.0.0.1:3080`,不加这个参数 API 会被拒。

启动并设置开机自启:

```sh
pm2 start ~/.dsh/pm2.json
pm2 save
pm2 startup
```

## 第五步:nginx 反向代理
新建 `/etc/nginx/sites-available/dsh.apple.me`(域名换成你的),软链到 `sites-enabled` 并 reload:

```sh
ln -s /etc/nginx/sites-available/dsh.apple.me /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
```

下面这份是**完整最终配置**,包含两个必踩的坑的解法(见注释),gzip/缓存为可选优化:
[nginx 配置太长,点击这里访问我的博客,里面有 nginx 配置](https://php.js.cn/blog/deepseek-harness-on-cloud-vps/)

---

## 坑 1:手机浏览器内容区域太小
**现象**:手机上打开 Web 界面,工作区域宽度太窄,设置页面几乎没法用。

**原因**:页面 HTML 里的 viewport meta 是 `initial-scale=1`,文字太大。

**解法**:在 nginx 上用 `sub_filter` 把响应里的 viewport 改成 `0.7`,让页面在手机屏上缩小显示。两个要点:
1. 必须先 `proxy_set_header Accept-Encoding "";` 把发给上游的压缩请求头置空,否则上游返回 gzip 压缩的 body,`sub_filter` 的字符串替换会失效;
2. `sub_filter` 默认只处理 `text/html`,HTML 页面正好符合。

改完 `nginx -t && systemctl reload nginx`,手机**硬刷新**(清缓存)后就能看到效果。

---

## 坑 2:manifest.webmanifest 请求永远是 302 ,PWA 装不上
**现象**:浏览器加载 `<link rel="manifest">` 时请求 `/manifest.webmanifest` 一直被重定向到登录页(302),DevTools 里 manifest 解析失败,手机 "添加到主屏幕" 不可用,`display` 模式也控制不了。

**原因**:`dsh-webui-auth` 插件在 HTTP 层拦截了**所有**未认证请求(包括静态资源)并 302 到登录页。而浏览器拉取 manifest 的请求不会携带登录 Cookie,于是永远 302,拿不到 manifest 内容。

**解法**:让 nginx 绕过认证,**直接输出**这份 manifest 文件——内容照抄 DSH dist 里的 `manifest.webmanifest`,并把 `"display": "fullscreen"` 改成 `"standalone"`(standalone 是"普通应用窗口",手机 PWA 更合适;fullscreen 会全屏隐藏浏览器 UI)。

要点:
1. 用 `location = ` 精确匹配,只接管这一个路径,不影响其他资源;
2. 内容**硬编码**在 nginx 里,以后 DSH 升级如果改了 manifest 结构需要手动同步;
3. 不用改 DSH 源码,也不用给认证插件开白名单,改动全部在 nginx 层,升级 DSH 不会丢。

---

## 访问与验证
- 电脑:浏览器打开 `http://你的域名`,登录后正常使用;
- 手机:同样地址登录。验证 PWA:Chrome 菜单 →「添加到主屏幕」; DevTools → Application → Manifest,`display` 应为 `standalone`;
- 如果手机或电脑上看到的是旧页面,记得硬刷新清缓存。

## 常见问题
1. 想用 HTTPS?
用 certbot 申请证书,`listen 443 ssl`,并把 80 重定向到 443(注意 443 的 location 也要带上同样的 sub_filter 和 manifest 直出配置)。
2. 改完 nginx 不生效?
`nginx -t` 先查语法,再 `systemctl reload nginx`,浏览器硬刷新。
3. 远程访问时"选择目录"没反应,或对话框弹在服务器本机屏幕上?
检查启动参数里是否带了 `--patch /root/.dsh/patch.yml` 固定 browse 目录选择器;不固定时 auto 可能选中 native(系统对话框弹在服务器屏幕上,远程用户看不到也点不了)

---

原文链接:[点击查看](https://www.v2ex.com/t/1234815)

评论

暂无评论。

0.058065s