把 DeepSeek Agent(dsh)部署上云记录

4 核 4G 的轻量服务器跑不动本地大模型,但跑 Agent 框架 + API 调模型绰绰有余。本文记录我把 DeepSeek 官方 Agent 框架 dsh 部署到外网可访问的全过程。

最终架构长这样(三层安全是灵魂:dsh 只听本机回环、Nginx 层 Basic Auth、防火墙只开 22/80,3080 永不出公网------因为 dsh 的 Agent 能读写文件、执行 shell,裸暴露等于把服务器钥匙挂门上):

markdown 复制代码
浏览器 ──http:80──▶ Nginx(Basic Auth + WebSocket 透传)
                        │ proxy_pass(仅本机回环)
                        ▼
                    dsh(127.0.0.1:3080,browser-trust fence)
                        │ HTTPS + API Key
                        ▼
                    DeepSeek API(deepseek-chat)

环境准备(快进版)

通用操作,命令按序执行:

bash 复制代码
# SSH 登录(腾讯云新版镜像默认用户是 ubuntu 不是 root)并切 root
ssh ubuntu@你的服务器IP
sudo -i

# 系统更新 + Node 22(插件生态普遍要求 22.x,别装 18)
apt update && apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
npm config set registry https://registry.npmmirror.com   # 国内镜像源

# 装 dsh,配成 systemd 常驻服务(解决断连即停、重启不自启)
npm install -g @deepseek-ai/dsh
which dsh    # 记下路径,写进下面 ExecStart
ini 复制代码
# /etc/systemd/system/dsh.service(用 nano 编辑,别用 vi)
[Unit]
Description=DeepSeek Harness Web UI
After=network.target

[Service]
ExecStart=/usr/bin/dsh web
Restart=always
RestartSec=5
User=root
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
bash 复制代码
systemctl daemon-reload && systemctl enable --now dsh
systemctl status dsh             # active (running) 即成功
curl -I http://127.0.0.1:3080    # 401 也算通(token 鉴权在工作)

接模型 :去 platform.deepseek.com 充 10 块钱、创建 API Key(只显示一次)。写 ~/.dsh/settings.yaml:

yaml 复制代码
agent-default-model:
  provider: deepseek
  model: deepseek-chat

llm-pi-ai:
  providers:
    deepseek:
      api: openai-completions
      baseURL: https://api.deepseek.com/v1
      apiKeyEnv: DEEPSEEK_API_KEY        # Key 不落盘,从环境变量读
      models:
        - id: deepseek-chat
        - id: deepseek-reasoner

再 systemctl edit --full dsh,[Service] 段加 Environment=DEEPSEEK_API_KEY=sk-xxx,daemon-reload + restart。到这里 dsh 在本机 3080 跑着了,但外网摸不到------这是刻意的安全设计。

新手粘贴三连坑 (我都踩过):两条命令挤一行 → 报 cannot execute binary file,一次一条,见提示符再敲下一条 ;PowerShell 粘 heredoc 带 ^[[200~ 特殊字符 → 卡在 >,Ctrl+C 后改用 nano;vi 卡在 -- INSERT -- → 直接用 nano(Ctrl+O 保存、Ctrl+X 退出)。

Nginx 反代:踩坑重灾区(本文精华)

现在套上 Nginx 这层"传达室"。

装好基础件

bash 复制代码
apt install -y nginx apache2-utils
htpasswd -c /etc/nginx/.htpasswd admin    # 输两遍密码

坑 1:htpasswd: cannot create file /etc/nginx/.htpasswd

我第一反应是命令错了,其实原因是 /etc/nginx/ 目录不存在------nginx 包压根没装上 (apt 那步没执行成功)。htpasswd 能跑只代表 apache2-utils 装了,两个包是独立的。回去补 apt install -y nginx 即可。

站点配置(WebSocket 三件套是关键)

bash 复制代码
cat > /etc/nginx/sites-available/dsh <<'EOF'
server {
    listen 80;
    server_name _;

    auth_basic "dsh-login";
    auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        proxy_pass http://127.0.0.1:3080;

        # WebSocket 三件套(流式输出必需,缺了发消息没反应)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_set_header Host $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;

        # Agent 一轮可能跑几分钟,默认 60s 超时会中途断
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}
EOF
ln -s /etc/nginx/sites-available/dsh /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx

整段 heredoc 必须一次性粘贴,结尾 EOF 单独成行、顶格。

坑 2:500 Internal Server Error(本文最值的坑)

浏览器访问 http://服务器IP,弹完密码框后给我一个 500。

定位三步:

bash 复制代码
tail -n 30 /var/log/nginx/error.log     # 灵魂命令,错误原因都在这
systemctl status dsh                    # 确认后端活着
journalctl -u dsh -n 50 --no-pager      # 看后端日志

error.log 里赫然写着:

scss 复制代码
open() "/etc/nginx/.htpasswd" failed (13: Permission denied)

原因 :我 chmod 640 之后,文件属主 root、属组 root。而 nginx 是 master(root) + worker(www-data) 的进程模型------绑 80 端口的是 root master,但实际处理请求、读密码文件的是降权后的 www-data worker,它不在 root 组里,读不了。

一行修复:

bash 复制代码
chown root:www-data /etc/nginx/.htpasswd
systemctl reload nginx

通用教训:给 nginx 的文件,权限要对着 www-data 配,不是对着 root 配 。排障心法:tail error.log > 猜。

坑 3:dsh 的第二道门------browser-trust fence

权限修好后,浏览器又给我一句:

ini 复制代码
dsh web authentication required; reopen the URL printed by dsh web.

这不是 nginx 的锅(502/500 才是),是 dsh 自己的 Host 校验 在拦人。dsh 像 Vite/Jupyter 一样内置了"浏览器信任围栏":只信任 127.0.0.1/localhost 的请求,防止外网直连调它的敏感 API。而走反代时,dsh 看到的 Host 是你的公网 IP------不认识,拒。

dsh web --help 里找到了正解:

lua 复制代码
--trusted-host <authority...>  extra authority the /api browser-trust fence accepts

改 systemd 服务(systemctl edit --full dsh):

ini 复制代码
ExecStart=/usr/bin/dsh web --no-open --trusted-host 你的服务器IP
bash 复制代码
systemctl daemon-reload && systemctl restart dsh

刷新浏览器 → 弹密码框 → 输密码 → dsh 界面出来了。手机切流量再试一次,真·外网可访问。

附带一个小坑:dsh 启动日志里的 token URL 会被 systemd 自动省略成 ...nvQbJ9k。想看完整内容加 -l:journalctl -u dsh --no-pager -l | grep token=。日志末尾的 > 是截断标记,不是 token 的一部分。token 等同于第二把钥匙,别截图公开。

插件与自定义 Agent

装第三方插件的两个坑

bash 复制代码
dsh plugin --profile web add dsh-dream-skin

坑 4 :报 pnpm not found on PATH------dsh 用 pnpm 管理插件,先 npm install -g pnpm。

坑 5(最哭笑不得) :装完 pnpm 再跑,报 ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER。pnpm 报错原文:

arduino 复制代码
"dsh-dream-skinroot@VM-0-2-ubuntu:~#" isn't supported by any available resolver.

包名末尾粘着终端提示符 root@VM-0-2-ubuntu:~#------复制命令时把提示符一起带进去了。SSH 客户端粘贴前,看一眼命令末尾干不干净。

装完插件记得 systemctl restart dsh------systemd 拉起的进程不会自动感知新装的包。

两个学习神器:

bash 复制代码
dsh --profile web --dump-config    # 打印实际加载的整棵配置树
journalctl -u dsh -f               # 实时日志

改配置前后各 dump 一次做对比,是理解"一切皆插件"最快的方式。

踩坑总表(收藏向)

# 现象 原因 解法
1 htpasswd cannot create file nginx 没装上 / 路径打错 补装 nginx,逐字核对路径
2 500 Internal Server Error www-data 读不到 .htpasswd chown root:www-data
3 dsh authentication required browser-trust fence 拦截 --trusted-host 你的IP
4 pnpm not found 插件依赖 pnpm npm install -g pnpm
5 ERR_PNPM_SPEC... 提示符粘进包名 粘贴前检查命令末尾
6 插件装完没生效 systemd 不自动重载 systemctl restart dsh
7 命令报奇怪参数错误 两条命令挤一行/粘贴污染 一次一条,见提示符再敲
8 heredoc 卡在 > PowerShell 粘贴带特殊字符 Ctrl+C,改 nano
9 换域名访问又被 fence 拦 trusted-host 只写了 IP 域名也加进 --trusted-host(可重复)

安全升级清单(公网长期使用前必看)

本文为了聚焦踩坑主线,用的是学习环境的最低配置。两个已知妥协,按优先级给出升级路径:

妥协点 风险 升级方案
全站 HTTP Basic Auth 只是 Base64 编码不是加密,公网传输的密码、对话内容可被中间人截获 上 HTTPS:有域名一条命令搞定(apt install certbot python3-certbot-nginx && certbot --nginx,自动配 443 和 80 跳转);没域名用 Tailscale 或 Cloudflare Tunnel 组私有入口
dsh 以 root 运行 Agent 被诱导执行恶意命令 = 整机 root 失守 建专用用户:useradd -m dsh,unit 改 User=dsh 并加 ProtectSystem=strict;注意配置目录随之变成 /home/dsh/.dsh,装插件也要用同一用户跑

另外三条低成本加固:

  • fail2ban 防 Basic Auth 爆破(连续输错密码自动封 IP)
  • 防火墙 80 换 443(80 只留作证书验证和跳转)
  • DeepSeek 平台设充值上限------Agent 长任务可能烧余额,10 元学习额度别绑大额支付

总结

走完这篇,你得到的是:一台外网可访问、有密码保护、开机自启的 DeepSeek Agent 服务器,成本 = 服务器钱 + API 充值的 10 块钱。

比结果更值钱的是过程中建立的三层思维:

  1. 链路思维:出问题先分层------网络层(防火墙)→ 网关层(Nginx 日志)→ 应用层(journalctl),别上来就瞎猜
  2. 最小权限思维:3080 不出公网、Key 不落盘、文件权限对着实际读取者(www-data)配
  3. 可观测思维 :error.log、journalctl -l、--dump-config,三个命令看穿一切

进阶方向:按《安全升级清单》加固,然后玩 dsh 的会话回放(resume/fork/replay)。

环境备注:腾讯云轻量 4C4G / Ubuntu 24.04 / Node v22 / dsh + pnpm 12.x,2026-09 实测通过。dsh 迭代很快,包名、配置字段以官方仓库 README 为准。

相关推荐
奕鼎竜瑆1 天前
Solid 前端响应式开发从零到精通
前端·人工智能
YOLO数据集集合1 天前
无人机桥梁损伤目标检测数据集 | 桥梁损伤 无人机巡检 结构健康监测 多类别检测9135期
人工智能·目标检测·无人机
动恰客流统计1 天前
景区客流统计怎么做?兼顾管控与运营的实施方案解析
大数据·前端·人工智能
weixin_443883011 天前
合规整改倒计时:高等级签名证书的应用场景
大数据·人工智能·法大大·法大大电子签·电子合同
魔猴疯猿1 天前
从0到1用Python开发第一个智能体
人工智能·python·深度学习·神经网络·机器学习
天一生水water1 天前
变分模态分解(VMD)的教程
人工智能
荆棘鸟智能1 天前
林业遥感长势评估怎么做?从NDVI时序分析到LiDAR蓄积量回归
人工智能·算法·智慧林业
代码方舟1 天前
数据科学风控实战:基于天远全能消金报告构建自动化信用评估网关
运维·人工智能·自动化
Yan-英杰1 天前
2026年数据采集服务怎么选?4大主流平台(亮数据 Bright Data、Apify、ScrapingBee、Zyte)深度对比
人工智能·神经网络·microsoft·机器学习·ai开发工具