把 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-xxxdaemon-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。想看完整内容加 -ljournalctl -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.logjournalctl -l--dump-config,三个命令看穿一切

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

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

相关推荐
zy_destiny44 分钟前
豆包赋能抖音内容创作与运营实战指南
人工智能
X54先生(人文科技)1 小时前
《元创力》纪实录 · 卷宗 3.5-C《协议的形状——ELR体系第一份商业合同的形成全记录》
人工智能·深度学习·架构·ai写作·开源协议
GitCode官方1 小时前
小鸿 AI 语音案例正式上线海思案例中心!首个适配 OpenHarmony 7.0 Release 全栈开源 AI 硬件
人工智能·开源·atomgit
昇腾知识体系1 小时前
昇腾 Atlas 800I A5 服务器:机型定位与部署入口
服务器·人工智能·华为·架构·知识图谱
小白说大模型1 小时前
《FDE前沿部署工程师实战教程》企业 Agent 项目实战:从需求分析到 PoC 落地
人工智能·spring·机器学习·自然语言处理·chatgpt·数据挖掘·需求分析
打不了嗝 ᥬ᭄1 小时前
神经网络基础与整体架构
人工智能·深度学习·神经网络
xp_fangfei1 小时前
Halcon之第7讲--模板匹配详解与实战应用
人工智能·计算机视觉
LaughingZhu1 小时前
Product Hunt 每日热榜 | 2026-09-11
人工智能·深度学习·神经网络·搜索引擎·百度
residual_fan1 小时前
经验模态重构:直向工业时间序列数据的数据扩增方法
人工智能·算法·重构·数据挖掘·数据分析