没有桌面环境也能跑 Harness?一台 Linux 服务器、七条命令、一个 systemd 服务,就能把 DeepSeek Harness 的 Web UI 跑起来,还能从任何地方远程访问。
前面几篇我们聊过 DeepSeek Harness 的定位、桌面版体验、二次开发与场景实战。这次聊一个很多团队实际遇到的问题:公司只有一台 Linux 服务器,没有图形界面,怎么把 Harness 跑起来?
答案其实很简单:DeepSeek Harness 目前只有源码一种 Linux 形态(桌面安装包仅提供 macOS / Windows)。源码拉取 → 安装依赖 → 构建 → 启动 Web UI → 反向代理,五步搞定。本文以 Ubuntu 22.04 为例完整演示一遍,末尾附 systemd 开机自启与远程访问的完整配置,全部命令都经过实测。
一、为什么要"源码部署"?
先明确 Harness 是什么:
Agent = Model + Harness:模型负责"思考",Harness 负责"动手"——读写文件、执行命令、调用工具、调度子智能体。
DeepSeek Harness(简称 dsh)是 DeepSeek 开源的 Agent 运行时框架(GitHub:deepseek-ai/deepseek-harness,24 万+ Star)。官方把它定位为"连接模型与真实环境的那层中介",所有能力(模型、工具、会话、沙箱、UI)都由插件组合而成,底层基于 Cordis 微内核。
为什么要源码部署,而不是等安装包?
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
对团队来说,**源码部署最大的价值是把 Harness 变成"服务"而不是"应用"**:一台低配服务器常年在线,团队浏览器即开即用,定时任务不关机也会执行,数据全部落在自己的 DSH_HOME 目录里。
二、环境准备:一台服务器 + 三个工具
硬件要求其实很低,实测一台 2 核 4G 的 Ubuntu 22.04 足够流畅运行:
-
系统:Ubuntu 20.04/22.04/24.04(Debian、CentOS 同理); -
CPU / 内存:2 核 4G 起步(构建时峰值约 2G 内存); -
磁盘:20G 以上(源码 + node_modules + 构建产物约 6G); -
网络:能访问 GitHub 与 npm registry。
软件依赖只有三个:
|
|
|
|
|---|---|---|
|
|
^22.19 || >=24 |
|
|
|
|
|
|
|
|
|
# 验证环境
node --version # v24.17.0 或更高
git --version # git version 2.x
Node.js 建议直接用官方二进制安装(免编译):
curl -fsSL https://nodejs.org/dist/v24.17.0/node-v24.17.0-linux-x64.tar.xz | sudo tar -xJ -C /usr/local --strip-components=1
node --version
三、获取源码:应用代码与数据目录分离
部署目录建议用 /opt/deepseek-harness(应用代码)与 /var/lib/deepseek-harness(数据目录 DSH_HOME)分离,之后升级代码不影响用户数据:
sudo git clone https://github.com/deepseek-ai/deepseek-harness.git /opt/deepseek-harness
sudo chown -R $(whoami) /opt/deepseek-harness
cd /opt/deepseek-harness
进入仓库后,先启用 pnpm(项目通过 packageManager 锁定 pnpm 11.7.0,corepack 会自动识别):
corepack enable pnpm
corepack prepare pnpm@11.7.0 --activate
pnpm --version # 11.7.0
四、安装依赖:一条命令,约 4 分钟
仓库是 pnpm workspaces 单仓,几十个包之间用 workspace:* 相互引用。安装严格按锁文件进行,保证可复现:
pnpm install --frozen-lockfile
⚠️ 注意事项:首次安装会下载几百 MB 依赖,实测约 4 分钟;装完
node_modules约 2-3G,属正常现象。结束时会自动执行postinstall钩子(lefthook git hooks、subprocess 助手),看到Done in ...即成功。
五、构建:一条命令,产出 lib + dist
pnpm run build
构建依次执行 tsc 类型编译(host 与 client 双编译器)、tsdown 打包、Web 前端 bundle 构建,结束时输出:
✓ built in 9.10s
build: recorded 347 client artifact(s) with 2 public value(s)
产物分布:
-
packages/*/*/lib:各包的 ESM 编译产物; -
apps/cli/lib:CLI 可执行入口; -
apps/web/dist:Web UI 静态资源(浏览器加载的部分)。
💡 构建常见坑:若内存不足(host 编译需要约 4G 上限),设
NODE_OPTIONS=--max-old-space-size=4096再跑;不要同时开多个终端构建。
六、启动 Web UI:一行命令,Web 端立起
构建完成后,用源码启动器直接跑 Web 模式:
pnpm dsh --profile web --no-open --host 127.0.0.1 --port 3080
启动成功的标志是一行带 token 的 URL:
dsh web: http://127.0.0.1:3080/?token=<随机字符串>
默认绑定 127.0.0.1:3080,只允许本机访问。先本地 curl 验证:
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3080/ # 401
6.1 服务化:systemd 开机自启
正式部署建议用 systemd 托管。创建 /etc/systemd/system/dsh-web.service:
[Unit]
Description=DeepSeek Harness Web UI
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/deepseek-harness
Environment=DSH_HOME=/var/lib/deepseek-harness
Environment=PATH=/usr/local/bin:/usr/bin:/bin
ExecStart=/usr/local/bin/node --import tsx/esm apps/cli/src/bin.ts --profile web --no-open --host 127.0.0.1 --port 3080
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now dsh-web.service
sudo journalctl -u dsh-web.service -f # 跟踪日志
两个关键点:
-
DSH_HOME=/var/lib/deepseek-harness:所有用户数据(会话、凭证、配置文件)落在独立数据目录,与应用代码分离; -
--import tsx/esm:dsh 的 CLI 源码启动走 tsx 的 ESM 钩子,systemd 里直接给 Node 传这个参数即可。
七、远程访问:nginx 反向代理(含 WebSocket / SSE)
这是最多人卡住的一步。先泼一盆冷水:
--host 0.0.0.0是被源码主动拒绝的。 项目在packages/bundle/web-app/src/startup.ts里明确报错:--host 0.0.0.0 is intentionally not supported yet for safety: it would expose remote code execution to the network。
原因很直白:Harness 能执行 Shell、读写文件、调度任务,直接裸奔到公网等于把远程代码执行(RCE)的门敞开。正确的远程姿势是:服务永远绑定 127.0.0.1,由 nginx 做反向代理。
7.1 信任围栏:--trusted-host
Web UI 的 /api 有一道浏览器信任围栏,防御 DNS 重绑定与跨站攻击。本机访问走 loopback 豁免;远程访问时,浏览器发来的 Host 必须落在 trustedHosts 里,否则一律 401/403:
# 假设服务器内网 IP 是 10.11.1.113
ExecStart=... --profile web --no-open --host 127.0.0.1 --port 3080 --trusted-host 10.11.1.113
说明:
--trusted-host接受host或host:port。不带端口写10.11.1.113表示"该主机名任意端口都信任";写10.11.1.113:8796则精确到端口。以后反代端口随意换,都不用改服务。
7.2 nginx 配置模板
在 /etc/nginx/sites-available/dsh-web 写入:
map $http_upgrade $dsh_connection_upgrade {
default upgrade;
'' close;
}
server {
listen 8796;
server_name _;
client_max_body_size 256m;
location / {
proxy_pass http://127.0.0.1:3080;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket 升级
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $dsh_connection_upgrade;
# SSE 流式输出:关缓冲、拉长超时
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
sudo ln -s /etc/nginx/sites-available/dsh-web /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
三个必须点:
-
** proxy_set_header Host $http_host**:把浏览器访问的 Host 原样透传。Web UI 的登录 Cookie 会绑定"Host + 端口",Host 转错会导致浏览器拿到的 Cookie 永远对不上(一直 401); -
WebSocket 升级:Web UI 的消息流走 Upgrade头,必须透传; -
SSE 流式:模型输出是 text/event-stream, proxy_buffering off关掉缓冲,否则打字机效果会变成"憋半天吐一屏"。
八、首次访问:token 一次认证,Cookie 30 天有效
Web UI 的认证设计很特别——没有静态密码,每次进程启动会随机铸造一个 token。流程是:
-
浏览器访问 http://10.11.1.113:8796/→ 返回 401; -
从服务日志拿到带 token 的 URL: sudo journalctl -u dsh-web.service | grep -o 'token=[A-Za-z0-9_-]*'; -
访问 http://10.11.1.113:8796/?token=<token>→ 服务校验后303跳回首页,并种下一枚 30 天有效、HttpOnly、SameSite=Strict 的 Cookie; -
之后同一浏览器直接访问即可,无需再输 token。
# 全链路验证(在服务器上模拟远程访问)
curl -s -o /dev/null -w "%{http_code}\n" http://10.11.1.113:8796/ # 401
curl -s -c /tmp/jar -o /dev/null "http://10.11.1.113:8796/?token=<token>" # 303
curl -s -b /tmp/jar -o /dev/null -w "%{http_code}\n" http://10.11.1.113:8796/ # 200
⚠️ 注意:token 会随服务重启轮换。把它看成"一次性开门钥匙",Cookie 才是常驻通行证;千万别把带 token 的 URL 发到群里。
九、接入模型:没有 Key,Harness 只是空壳
Web UI 起来了,但先别急着欢呼——Harness 本身不含模型。打开对话,第一步就是配置模型 API。Harness 原生支持 DeepSeek API,一行环境变量即可:
# 在 systemd 服务里追加后重启
Environment=DEEPSEEK_API_KEY=sk-xxxxxxxx
问题来了:Agent 任务往往要来回迭代几十轮,Token 消耗比普通聊天高出一个量级,模型成本才是跑 Harness 的真正大头。怎么把成本打下来?答案是通过向量云获取字节跳动火山方舟官方 API 和 Key:
-
官方真实 Key( ark-****-****-****-****-****-88888格式),请求直连ark.cn-beijing.volces.com火山方舟官方接口,不经中转,延迟、稳定性、计费标准与官方完全一致; -
低折扣 Token 价格,注册即享,按量计费、即用即扣、不设账期; -
低门槛起步:注册、充值 10 元、创建 Key,三步搞定,几分钟就能把 Harness 跑起来。
一把 Key 就能覆盖 Harness 的多种模式:复杂推理用 DeepSeek V4 Pro(deepseek-v4-pro-ga-260813),日常快速任务用 DeepSeek V4 Flash(deepseek-v4-flash-ga-260731)——开源框架搭配低成本官方 API,才是 Agent 玩家的省钱正道。
获取 API Key:打开
https://ark.tokenrize.cn/注册充值,创建 Key 后填入 Harness 的模型配置即可。
写在最后
从源码到远程可用的 Harness Web,拢共就五步:装环境 → 拉源码 → 装依赖 → 构建 → 启动 → 反代 → 配模型。最难的不是命令,是理解三条安全红线:
-
永远 127.0.0.1+ 反向代理,绝不0.0.0.0裸奔; -
--trusted-host声明信任的访问域名,Cookie 绑定 Host 不能错; -
token 是开门钥匙、Cookie 是常驻通行证,两者都别外泄。
服务器常年在线、团队浏览器即开即用、数据掌握在自己手里——这就是源码部署的回报。至于模型 Token 成本?交给向量云。
你在 Linux 上部署 Harness 遇到过哪些坑?欢迎在评论区聊聊。
向量云(南京)科技有限公司

