DeepSeek Harness 部署复用笔记
适用场景:已有一台阿里云 Ubuntu 服务器,服务器上已有一个工具网站;希望额外部署 DeepSeek Harness,并通过公网 IP + Nginx 登录验证访问。
注意:不要把真实 API Key 写进文档、截图或聊天里。
1. 最终架构
最终采用的是:
浏览器访问 http://服务器公网IP:4081
↓
Nginx Basic Auth 登录验证
↓
Nginx 反向代理到 127.0.0.1:3080
↓
DeepSeek Harness Web 服务
↓
DeepSeek API
端口关系:
4081:公网入口,Nginx 监听
3080:服务器内部端口,Harness 本体监听
80:原小陈工具网站入口
3000:小陈工具网站后端内部端口
核心 Nginx 配置关系:
listen 4081;
proxy_pass http://127.0.0.1:3080;
简单记:
外面进 4081,里面转 3080。
2. 这次遇到的主要问题
2.1 原服务器配置偏低
原服务器大概是:
Ubuntu 24.04
2 核 2 GiB
已有小陈工具网站运行
直接在这台服务器源码构建 Harness 时,pnpm install 和 pnpm run build 会吃大量内存和 CPU,导致:
CPU 100%
内存 90%+
swap 接近用满
SSH 卡顿
原网站短暂打不开
结论:
2核2G 可以尝试运行,但不适合源码构建大型项目。
2.2 GitHub clone 不稳定
服务器 git clone 出现过:
GnuTLS recv error (-110)
说明服务器访问 GitHub HTTPS 不稳定。后来采用:
本地下载源码 ZIP
本地/虚拟机编译
打包上传服务器
2.3 URL 复制成 Markdown 格式
错误形式:
[https://example.com](https://example.com)
命令行里应该只输入纯 URL:
https://example.com
否则可能导致:
下载到 9 字节错误文件
Git 要求输入 Username/Password
curl 访问错误地址
2.4 pnpm 下载慢或卡住
项目使用 pnpm,不是普通 npm 项目。因为仓库里有:
pnpm-lock.yaml
pnpm-workspace.yaml
说明这是 pnpm workspace/monorepo。
常用优化:
pnpm config set registry https://registry.npmmirror.com
pnpm config set fetch-timeout 180000
pnpm config set fetch-retries 5
pnpm config set network-concurrency 1
pnpm install --network-concurrency 1
2.5 构建时报 git rev-parse HEAD
如果源码是 ZIP 解压,不是 git clone,构建脚本可能报:
Error: Command failed: git rev-parse HEAD
解决:在源码目录临时初始化 Git:
git init
git config user.email "local@local"
git config user.name "local"
git add .
git commit -m "local build"
2.6 构建时报缺 cc
报错:
spawnSync cc
ENOENT
意思是缺 C 编译器。
解决:
sudo apt update
sudo apt install -y build-essential python3 make g++ pkg-config
2.7 构建时报内存不足
报错:
JavaScript heap out of memory
说明 Node 编译时堆内存不足。
项目里有构建参数:
--max-old-space-size=4096
意思是允许 Node 最多用 4GB JS 堆内存。
如果服务器只有 2G 内存,即使有 2G swap,也很吃紧。可以临时加大 swap,但更推荐本地虚拟机构建。
2.8 systemd 启动出现端口占用
日志:
EADDRINUSE: address already in use 127.0.0.1:3080
原因:之前手动启动过 Harness,占着 3080,后来 systemd 又启动一个 Harness,也想占 3080。
解决:只保留 systemd 管理的服务。
systemctl stop deepseek-harness
ss -lntp | grep ':3080'
kill -9 PID
systemctl start deepseek-harness
3. 本地 VMware Ubuntu 构建流程
因为 Windows 没有 WSL,Docker Desktop 又要求 WSL,所以改用 VMware Ubuntu。
Ubuntu 虚拟机建议:
Ubuntu 24.04 Desktop
内存 6G 或 8G
CPU 4 核
硬盘 50G
网络 NAT
安装后打开终端:
sudo apt update
sudo apt install -y curl git unzip tar openssh-client build-essential python3 make g++ pkg-config
安装 Node 22:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash -
sudo apt install -y nodejs
node -v
npm -v
安装 pnpm:
sudo npm install -g pnpm
pnpm -v
下载 Harness:
cd ~
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
如果是 ZIP 解压,需要补 Git 信息:
git init
git config user.email "local@local"
git config user.name "local"
git add .
git commit -m "local build"
安装依赖并构建:
pnpm config set registry https://registry.npmmirror.com
pnpm install
pnpm run build
构建成功后打包:
cd ~
tar -czf deepseek-harness-built.tar.gz deepseek-harness
注意:tar 命令里输出文件名和目录之间必须有空格。
正确:
tar -czf deepseek-harness-built.tar.gz deepseek-harness
错误:
tar -czf deepseek-harness-built.tar.gz.deepseek-harness
上传服务器:
scp ~/deepseek-harness-built.tar.gz root@服务器公网IP:/srv/
4. 服务器解压和运行
服务器上解压:
cd /srv
rm -rf /srv/deepseek-harness-built
mkdir -p /srv/deepseek-harness-built
tar -xzf /srv/deepseek-harness-built.tar.gz -C /srv/deepseek-harness-built --strip-components=1
cd /srv/deepseek-harness-built
ls package.json
ls node_modules
临时启动测试:
cd /srv/deepseek-harness-built
DEEPSEEK_API_KEY='你的真实Key' DSH_TRUSTED_HOSTS='服务器公网IP:4081,127.0.0.1:3080,127.0.0.1:4081' pnpm dsh web --host 127.0.0.1 --port 3080 --no-open
确认端口:
ss -lntp | grep -E ':3080|:4081'
应该看到:
127.0.0.1:3080 node
0.0.0.0:4081 nginx
5. Nginx 配置
文件位置:
/etc/nginx/sites-available/harness
推荐配置:
server {
listen 4081;
server_name 47.*.*.*;
auth_basic "DeepSeek Harness";
auth_basic_user_file /etc/nginx/.harness_passwd;
location / {
proxy_pass http://127.0.0.1:3080;
proxy_http_version 1.1;
proxy_set_header Host 127.0.0.1:3080;
proxy_set_header Origin http://127.0.0.1:3080;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600;
proxy_send_timeout 3600;
proxy_buffering off;
}
}
重要备注:
proxy_set_header Host 127.0.0.1:3080;
proxy_set_header Host 127.0.0.1:3080; 表示 Nginx 转发请求给 DeepSeek Harness 后端服务时,把 HTTP 请求头里的 Host 设置为 127.0.0.1:3080。DeepSeek Harness 后端服务实际监听地址是 127.0.0.1:3080,所以 DeepSeek Harness 后端服务会把这次请求识别成本机访问。
proxy_set_header Host http://127.0.0.1:3080; 是错误写法。Host 请求头不能包含 http://。Host 请求头只能包含主机名和端口,例如 127.0.0.1:3080。
proxy_set_header Origin http://127.0.0.1:3080;
proxy_set_header Origin http://127.0.0.1:3080; 表示 Nginx 转发请求给 DeepSeek Harness 后端服务时,把浏览器来源 Origin 设置为 http://127.0.0.1:3080。Origin 请求头可以包含 http://。
如果浏览器打开"选择工作区目录"时出现 client api: directoryPicker/list failed: transport failure for /api/directoryPicker/list: HTTP 403,优先检查 Nginx 配置文件中是否错误写成了 proxy_set_header Host http://127.0.0.1:3080;。正确写法必须是 proxy_set_header Host 127.0.0.1:3080;。
创建网页登录密码:
htpasswd -c /etc/nginx/.harness_passwd admin
启用配置:
ln -s /etc/nginx/sites-available/harness /etc/nginx/sites-enabled/harness
nginx -t
systemctl reload nginx
访问:
http://服务器公网IP:4081
6. systemd 后台服务
服务文件位置:
/etc/systemd/system/deepseek-harness.service
示例:
[Unit]
Description=DeepSeek Harness Web
After=network.target
[Service]
Type=simple
WorkingDirectory=/srv/deepseek-harness-built
Environment="DEEPSEEK_API_KEY=你的真实Key"
Environment="DSH_TRUSTED_HOSTS=服务器公网IP:4081,127.0.0.1:3080,127.0.0.1:4081"
ExecStart=/usr/bin/pnpm dsh web --host 127.0.0.1 --port 3080 --no-open
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
启用:
systemctl daemon-reload
systemctl enable deepseek-harness
systemctl start deepseek-harness
常用管理命令:
systemctl status deepseek-harness --no-pager
systemctl restart deepseek-harness
systemctl stop deepseek-harness
journalctl -u deepseek-harness -n 100 --no-pager
7. Token 怎么找
Harness 自己有一层 token 认证。服务重启后 token 可能变化。
找日志中的 URL:
journalctl -u deepseek-harness -n 300 --no-pager -o cat | grep -Eo 'http://[^ ]+'
只看最新一个:
journalctl -u deepseek-harness -n 300 --no-pager -o cat | grep -Eo 'http://[^ ]+' | tail -1
直接转换成公网访问 URL:
journalctl -u deepseek-harness -n 300 --no-pager -o cat | grep -Eo 'http://127.0.0.1:3080/[^ ]+' | tail -1 | sed 's#http://127.0.0.1:3080#http://服务器公网IP:4081#'
如果没有输出,可能是服务没正常启动,先看:
systemctl status deepseek-harness --no-pager
journalctl -u deepseek-harness -n 120 --no-pager
8. API Key 验证
不要把真实 Key 发到聊天里。
服务器上测试 Key:
curl https://api.deepseek.com/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 你的Key" \
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"hello"}],"stream":false}'
常见结果:
Authentication Fails / invalid api key:Key 无效
Insufficient Balance:Key 有效,但余额不足
返回 assistant 内容:调用成功
如果 deepseek-chat 余额不足,但 deepseek-flash 成功,说明:
Key 有效,但当前模型、余额或权限不同。
10. 复用 FAQ
Q1:为什么不用 npm,要用 pnpm?
因为 DeepSeek Harness 仓库里有:
pnpm-lock.yaml
pnpm-workspace.yaml
说明它是 pnpm workspace 项目。用 npm 可能导致 workspace 包链接不对、依赖版本不一致、构建失败。
Q2:listen 4081 和 proxy_pass 是在哪运行?
它们不是命令,是 Nginx 配置,写在:
/etc/nginx/sites-available/harness
修改后执行:
nginx -t
systemctl reload nginx
Q3:为什么访问会弹用户名密码?
这是 Nginx Basic Auth,配置来自:
auth_basic "DeepSeek Harness";
auth_basic_user_file /etc/nginx/.harness_passwd;
用户名通常是:
admin
忘记密码可重设:
htpasswd -c /etc/nginx/.harness_passwd admin
systemctl reload nginx
Q4:为什么浏览器显示 dsh web authentication required?
这是 Harness 自己的 token 认证。需要用 dsh web 启动时打印的 token URL。
公网访问时,把:
http://127.0.0.1:3080/?token=xxx
改成:
http://服务器公网IP:4081/?token=xxx
Q5:为什么页面一直"自动重连中"?
常见原因:
Harness 后端挂了
Nginx WebSocket/长连接转发不完整
3080 端口冲突
服务反复重启
检查:
ss -lntp | grep -E ':3080|:4081'
journalctl -u deepseek-harness -n 120 --no-pager
tail -n 80 /var/log/nginx/error.log
Q6:EADDRINUSE 127.0.0.1:3080 是什么?
端口被占用。通常是手动启动的 Harness 没停,systemd 又启动了一个。
处理:
systemctl stop deepseek-harness
ss -lntp | grep ':3080'
kill -9 PID
systemctl start deepseek-harness
Q7:API 密钥无效 一定是 Key 错吗?
不一定。可能是:
Key 真无效
余额不足
模型名不对
模型没权限
systemd 没读到新 Key
最准确是用 curl 直接测 DeepSeek API。
Q8:Insufficient Balance 是什么?
Key 有效,但账户余额不足。充值或换可用模型。
Q9:Ubuntu ISO 安装完要删吗?
可以删。VMware 虚拟机装好后,ISO 只是一张"安装光盘镜像",不再需要。删除可释放约 5-6GB 空间。
Q10:.service 文件是什么?
是 systemd 的服务说明书,不是业务代码。真正执行的是里面的:
ExecStart=...
例如:
systemctl start deepseek-harness
就是让 systemd 按 /etc/systemd/system/deepseek-harness.service 的说明启动 Harness。