本文记录一次真实部署的完整过程和踩坑经验。环境:Debian 12、2 核 CPU、约 925MB 内存、39GB 磁盘。 文中所有密钥、Token、密码、用户 ID、机器人用户名一律用占位符表示,公开发布前请务必替换,并不要把真实 Token 写进文章或代码仓库。
避坑总览:先看这五条
- 小内存先加 Swap,再装 DSH。 不加 Swap,npm 安装 DSH 时很容易被 OOM killer 杀掉,表现为安装莫名中断、dsh 命令缺失、服务起不来。
- 不要装旧的
dsh-telegram。 新版教程用的是@xmanrui/dsh-im,两者不要混装。 - Token 只走 DSH 设置界面。 不要把 Bot Token 写进
cordis.patch.yml、settings.yaml或任何会被提交的文件。 - 私聊一定要开白名单。 dsh-im 默认对所有私聊开放,不设白名单等于谁都能指挥你的机器人。
- 模型选错是最高频的报错来源。 要 Key 的官方模型、要 GitHub 授权的 EAC 模型、免密的 Kilo 免费池,这三类不要混着选。
一、服务器准备
1. 改主机名(可选,但建议做)
hostnamectl set-hostname b2
并在 /etc/hosts 里加一行:
127.0.1.1 b2
2. 检查资源
free -m # 查看内存与已有 Swap
df -h # 确认根分区剩余空间大于 2GB
如果 free -m 里 Swap 全为 0,说明机器没有预置交换,继续下一步。
3. 创建 2GB Swap
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
老版本若不支持 fallocate,可用 dd if=/dev/zero of=/swapfile bs=1M count=2048 代替。
开机自动挂载并调低 swappiness:
echo '/swapfile none swap sw 0 0' >> /etc/fstab
sysctl vm.swappiness=10
echo 'vm.swappiness=10' >> /etc/sysctl.conf
swappiness 默认是 60,小内存机器会把数据过早换出、拖慢性能;设为 10 表示只在内存紧张时才动用 Swap。再执行 free -m,Swap 应显示约 2048MB。
补充说明:如果云厂商给你的是静态公网 IP,但网卡上只显示内网地址,这多半是 NAT 映射,属正常现象,只要出站 IP 和入站 SSH 到的都是同一台机器即可。
4. 装基础工具
apt update
apt install -y curl ca-certificates gnupg git
二、安装 Node 和 DSH
用 NodeSource 装 Node 22:
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
node -v
npm -v
实测版本:Node v22.23.4、npm 10.9.9。
全局安装 DSH,并补装 pnpm(插件安装需要它,缺了会报 pnpm 未找到):
npm install -g @deepseek-ai/dsh
npm install -g pnpm
dsh --version
实测 DSH 版本:0.2.1-rc.5。
长耗时安装建议脱离 SSH 会话运行,例如用 setsid / nohup 后台跑,避免 SSH 断线把安装进程一起带走。SSH 偶尔出现 banner 交换超时,多半是网络抖动,先重试,不要轻易判定服务器挂了。
三、安装免费模型插件和 IM 插件
1. 免费模型插件
dsh plugin --profile web add github:Ebony-Vinyl/dsh-our-free-model
实测版本:2.8.0。
注意两点:
- 不要同时把它写进
cordis.patch.yml,重复注册会出问题。 - 用下面的命令检查,
our-free-model应该只出现一次:
dsh --profile web --dump-config
2. IM 插件(Telegram 对接)
dsh plugin --profile web add -w @xmanrui/dsh-im
实测版本:5.9.1。
最终 bundles 顺序应为:
@deepseek-ai/dsh-base
@deepseek-ai/dsh-web-app
dsh-our-free-model
@xmanrui/dsh-im
再次检查 dump-config,确认 our-free-model 和 @xmanrui/dsh-im 都在,且没有旧的 dsh-telegram。
四、用 systemd 跑 DSH,不要对外暴露 Web UI
教程本身只要求前台跑 dsh --profile web,但为了让机器人 survives 重启,建议写一个 systemd 服务。关键点:Web UI 只监听本地,Telegram 走长轮询,不需要开放任何入站端口。
/etc/systemd/system/dsh.service 示例:
[Unit]
Description=DSH Telegram Agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/root
Environment=DSH_HOME=/root/.dsh
Environment=HOME=/root
ExecStart=/usr/bin/dsh --profile web
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
启动并验证:
systemctl daemon-reload
systemctl enable dsh
systemctl start dsh
systemctl status dsh --no-pager
ss -tlnp | grep -E '3080|8326'
正常情况下服务是 active,且 3080、8326 只出现在 127.0.0.1 上,不要在防火墙或安全组里放行它们。
五、绑定 Telegram 机器人
- 在 BotFather 创建机器人,拿到 Bot Token,记好但不要发到公开场合。
- 打开 DSH 的「设置 → IM机器人」,选择 Telegram,粘贴 Token 并保存。
- 务必开启私聊白名单模式,填入自己的数字 USER_ID,例如:
<你的数字 USER_ID>
只放你一个人。群聊默认是开放模式,如需收紧要另外设置,不要以为开了私聊白名单群聊就自动安全了。
绑定成功后,机器人应显示已连接、长轮询正常。绑定信息保存在 ~/.dsh/integrations/dsh-telegram/,Token 在里面是引用形式,不是明文,但这不等于可以把该目录公开分享。
六、模型选择避坑:这是本次部署最关键的一节
dsh-im 的模型列表里混了三类模型,选错就会报错:
| 类型 | 表现 | 能不能在服务器上用 |
|---|---|---|
DeepSeek 官方模型,如 deepseek-flash | 没有 Key 时报缺少凭据 | 没配 Key 就不能用 |
EAC 模型,如 opencode/deepseek-v4.1-flash-free | 报 401,需要 GitHub 授权并 star 仓库 | 服务器上用不了,它是桌面端取向的渠道 |
Kilo 免费池,如 kilo-auto/free | 免账号、免 Key | 可以,这就是默认该选的 |
正确做法:把默认模型写进 ~/.dsh/profiles/web/cordis.patch.yml 的 agent-default-model:
- id: agent-default-model
name: "@deepseek-ai/dsh-agent-default-model"
config:
provider: our-free-model
model: kilo-auto/free
reasoningEffort: high
改完重启服务:
systemctl restart dsh
systemctl is-active dsh
dsh --profile web --dump-config | grep -A4 agent-default-model
重要:改完模型一定要在 Telegram 里先发 /new 开新会话,再发正常消息。 旧会话还钉在旧模型上,不换会话,报错会继续出现。这一步最容易被忽略。
七、验证清单
按顺序全部通过,才算部署完成:
-
systemctl status dsh是active - 3080、8326 只监听在
127.0.0.1 - Telegram 发
/start有回复 - Telegram 发
/status能看到会话和模型 - Telegram 发
/new后,再发一句正常消息能正常回复 - 没有出现“任务结果未确认”“内部未知错误”之类的提交失败提示
八、常见问题
Q:npm 安装 DSH 装到一半就没了,dsh 命令也不存在? A:先看内存和 Swap,十有八九是 OOM killer 杀了 npm。按第一节补 2GB Swap 再重装,不要反复在没 Swap 的机器上硬装。
Q:插件安装报 pnpm 未找到? A:先全局装 pnpm 再装插件。
Q:/start 失败,提示缺少凭据?
A:会话默认模型走了 DeepSeek 官方渠道,但你没配 Key。按第六节把默认模型改成 Kilo 免费池,再 /new。
Q:正常消息报 401,要 GitHub 授权 star 仓库?
A:你选到了 EAC 模型。换回 kilo-auto/free,再 /new。不要尝试绕过 EAC 的授权闸门。
Q:改了模型还是报错?
A:先确认你是不是还在旧会话里。/new 之后再测一次;同时用 journalctl -u dsh --no-pager | tail -n 100 看服务日志,用 Telegram 的 /status 看当前会话到底用的是哪个模型。
Q:SSH 经常断,b2 是不是挂了? A:不一定。先重试连接,再看服务状态。长安装一定要脱离 SSH 会话跑,断线才不会中断安装。
九、发布前的安全提醒
- 不要把 Bot Token、服务器密码、API Key 写进教程、截图或代码仓库。
- 数字 USER_ID、白名单、机器人用户名在公开发布时建议用占位符或打码。
- Web UI 只监听本地是刻意为之,不要为了图方便把它暴露到公网。