把 DSH 塞进一台 ARM 盒子,踩了七个坑
2026-10-26 · 11 分钟阅读
DSH 是个 Web 版 AI 助手,官方只发 npm 命令行包。我想把它跑在一台常驻的 ARM 盒子上,出门在外也能随时连回家用。
踩了一路坑,把能抄的步骤和不能踩的坑都记下来。
环境
| 项目 | 值 |
|---|---|
| 硬件 | ARM 盒子(aarch64) |
| 存储 | eMMC 6.5G + 一块 29G 的 U 盘 |
| 系统 | Armbian 26.11(Ubuntu 26.04 base) |
| 内核 | 6.18 |
| DSH 版本 | 0.2.1-rc.2 |
第一个关键决策:数据目录必须放 U 盘,不能放 eMMC。
盒子自带的 eMMC 只有 6.5G,DSH 的依赖能吃掉 2G 以上。用 DSH_HOME 环境变量把数据目录指到 U 盘挂载点(/mnt/data/dsh),eMMC 只留系统。
安装
# Node 需要 20+
node -v
# 全局安装 DSH
npm install -g @deepseek-ai/dsh
# 验证
dsh --version
# 建数据目录(放 U 盘,别放 eMMC)
mkdir -p /mnt/data/dsh
# 首次启动,生成 profile
DSH_HOME=/mnt/data/dsh dsh --profile web --host 192.168.20.111 --no-open
首次启动会自动从随附模板初始化 web profile,要等 40~60 秒(在装依赖,不是卡死)。
做成常驻服务
先 Ctrl+C 停掉,写 systemd 单元:
# /etc/systemd/system/dsh-keep.service
[Unit]
Description=DSH harness (web profile, web GUI)
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0
StartLimitBurst=0
[Service]
Type=simple
User=root
Environment=DSH_HOME=/mnt/data/dsh
Environment=PATH=/root/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WorkingDirectory=/root
ExecStart=/usr/local/bin/dsh --profile web --host 192.168.20.111 --no-open --trusted-host 192.168.20.111:3080
Restart=always
RestartSec=5
OOMScoreAdjust=-100
MemoryMax=1G
StandardOutput=journal
StandardError=journal
SyslogIdentifier=dsh-keep
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now dsh-keep
journalctl -u dsh-keep -f
日志里会出现带 token 的访问地址,浏览器打开即可:
dsh web: http://192.168.20.111:3080/?token=xxxxx
坑一:--host 不能用 0.0.0.0
DSH 明确拒绝通配地址,帮助原文:
--host <host> bind address: one concrete IPv4 or IPv6 literal of a local interface;
wildcard addresses are rejected
必须写具体网卡 IP。 想局域网访问就写盒子自己的局域网地址(我用有线口的 192.168.20.111,比无线稳)。
坑二:只绑 IP 不加 --trusted-host,插件市场装不了东西
这个坑最隐蔽。
表现:页面能打开、能浏览,但一点「安装插件」就报 untrusted origin。
原因:插件市场(dshmarket)的写操作有自己的同源校验,要求请求的 Host 是回环地址或 --trusted-host 声明过的地址。通过局域网 IP 访问时 Host 是 192.168.20.111:3080,不在信任列表,所有写操作返回 403。
修法:启动参数加上下面这条,注意要带端口:
--trusted-host 192.168.20.111:3080
坑三:MemoryMax=1G 会 OOM
DSH 内存峰值能到 860M,MemoryMax=1G 太贴边,撞上就被杀。
建议给 1.2G 以上,或者干脆不设上限。 我卡 1G 是因为机器总共只有 1.7G 内存,属于无奈的取舍。
坑四:别在它自己的终端里 restart 自己
如果 DSH 里跑着 agent,agent 去执行 systemctl stop dsh-keep,等于自己拔自己电源。
要改这个服务,从外部 SSH 进来操作。
坑五:Restart=always 对正常 stop 不生效
systemctl stop 属于正常退出,Restart=always 不会拉起。停了就是停了,得手动 start。
坑六:--no-open 必须加
不加的话它会尝试调浏览器,无头服务器上会报错或卡住。
坑七:数据目录千万别放 eMMC
DSH_HOME 一定要指向 U 盘/外置盘。我第一次装没注意,把依赖全塞 eMMC 里,/root/.cache 一个目录就吃掉 2G,系统盘直接告急。
装插件
进入 Web UI 后:
- dshmarket:插件市场本身,先装这个,后面才有市场界面
- workbuddy:模型接入插件
- 其他插件在市场里按需装
装新插件必须重启 DSH 才生效——包安装走 pnpm,在 HMR 队列之外,装完得重启一次才能加载。
只有「已有插件的启停 / 改配置」才热重载,不用重启。
实际数字
| 指标 | 值 |
|---|---|
| DSH 本体内存 | ~330M |
| 加插件后总内存 | ~500M |
| 磁盘占用 | 本体 ~1G,数据目录随用量增长 |
| 启动时间 | 40~60 秒(首次更久,在装依赖) |
不建议做的事
- 别把
MemoryMax卡太紧:会 OOM。但机器内存小又不得不卡,这是个取舍。 - 别指望它自带公网访问:默认只绑内网 IP,要外网访问得自己上反向代理或隧道。
- 别用 0.0.0.0 图省事:DSH 直接拒绝,而且裸 HTTP 暴露在公网不安全。
- 别在它自己的会话里操作它自己的服务:会把自己搞死。
小结
整套下来最容易被卡住的是这三件事:
--host必须写具体 IP,不能0.0.0.0--trusted-host不加,插件市场装不了东西- 数据目录别放 eMMC
剩下的都是耐心等它初始化。装完之后它就是个稳定的 Web 服务,重启自动拉起,平时不用管。