在 DeepSeek Harness 中通过 SSH 使用远程服务器:dsh-remote-ssh 配置与排障指南
在 DeepSeek Harness 中通过 SSH 使用远程服务器:dsh-remote-ssh 配置与排障指南
如果你平时在本地使用 DeepSeek Harness,但代码、数据、Conda 环境甚至 GPU 都在远程服务器上,那么一个很自然的需求就是:
能不能让 DSH 本身继续运行在我的电脑上,但让它像操作本地项目一样操作 SSH 服务器上的项目?
dsh-remote-ssh 就是为这个场景设计的。
它和“把整个 DeepSeek Harness 安装到服务器上”并不是一回事。更有意思的是,它也不是简单地把远程目录同步一份到本机。
它可以让:
本地 Mac│├── DeepSeek Harness├── 模型配置├── API Provider├── Session├── Plugins└── Skills │ │ SSH + AHP ▼远程 Linux Server│├── 项目源码├── 数据集├── Conda / Python 环境├── Bash├── GPU└── 真实文件系统也就是说: Agent 留在本机,执行环境留在服务器。
1. 关于这个插件,以及我维护的 rc.8 Web 版本
原项目:https://github.com/Yan-Zero/dsh-remote-ssh
我基于它维护了一个针对新版 DeepSeek Harness 的版本:https://github.com/Zhong0118/dsh-remote-ssh
上游目前的插件包版本为 0.2.4,主要基于 DeepSeek Harness 0.1.0-rc.6 的 package surface 开发。
我的版本当前位于:0.2.5,主要基于 DeepSeek Harness 0.1.0-rc.8
同时去掉了原项目中的 TUI 相关适配,专门聚焦目前我实际使用的:DSH Web
| 项目 | 上游版本 | 我的版本 |
|---|---|---|
| 插件 | 0.2.4 | 0.2.5 |
| DSH | rc.6 | rc.8 |
| Web | ✅ | ✅ |
| TUI | ✅ 可选 | ❌ 移除 |
| 定位 | Web + TUI | Web 优先 |
后续我也可能继续基于这个版本做一些 Web 侧的功能和体验优化。
2. dsh-remote-ssh 到底做了什么?
这个插件最重要的设计理念其实不是“SSH”,而是:
把远程目录变成 DSH 的一个透明 Workspace。
例如本地项目可能显示为:LOCAL > my-project
远程项目则显示成:Server > aigc_detector
当你进入本地 Workspace 时:
readwritegrepglobbashbackground task这些工具全部操作本机。
进入远程 Workspace 时,同样这些工具则被透明地路由到服务器。 也就是说,模型看到的仍然是:
readgrepbash而不是另一套:
remote_readremote_grepremote_bash这是我比较喜欢这个插件的地方。 上游设计明确要求:当 Workspace 是远程的时,文件系统、搜索、Shell 和后台任务都在对应 SSH 主机执行;如果远程环境失败,也不会偷偷 fallback 到本机。
3. 它不是“同步工具”
这一点特别重要。 假设服务器项目是:
/home/user/projects/aigc_detector把它加入 DSH 后,并不意味着:
Server ↓ rsyncMac ↓本地复制一整份项目真实情况更接近:
DSH Workspace │ ├─ 身份:Server > aigc_detector │ └─ 实际文件仍然位于 ↓/home/user/projects/aigc_detector因此服务器上一个几十 GB 的项目,不会因为你把它加入 DSH 就自动下载几十 GB 到本机。 这也让本地和服务器之间保持了非常清晰的边界。
4. Remote Workspace 和 Backend 是两回事
这是使用这个插件时最容易混淆的地方。
Remote Workspace
这是我日常更推荐的一种模式。 架构是:
Mac│├── DSH├── Agent├── Session├── Model / API├── Plugins├── Skills│└──── SSH + AHP ────► Server │ ├── Files ├── Bash ├── Search ├── Python ├── Conda └── GPU简单说:
脑子在本机,手在服务器。
服务器只是 DSH 的远程执行环境。 这也是本文主要讲的模式。
Full Backend
插件还有另外一种模式:
在 Web 中打开 Backend这个模式完全不同。 此时会变成:
Mac Browser │ │ SSH tunnel ▼Remote Server│├── dsh-host├── Agent├── Session├── Tools├── Workspace└── Harness Backend也就是说:
整个 Harness 后端都跑到了服务器上。
插件会将匹配的 dsh-host runtime 安装在用户目录:
~/.dsh-host不需要 root,也不会通过 apt 去修改服务器系统。
完整 Backend 模式不依赖 VS Code Server 或 AHP;首次安装还会需要 curl、sha256sum、支持 xz 的 tar 以及访问 Node/npm 的网络。
因此二者可以这样理解:
| Remote Workspace | Full Backend | |
|---|---|---|
| DSH 本体 | 本机 | 服务器 |
| Agent | 本机 | 服务器 |
| Session | 本机 | 服务器 |
| Skills / Plugins | 本机 | 服务器环境 |
| 项目文件 | 服务器 | 服务器 |
| Bash | 服务器 | 服务器 |
| GPU | 服务器 | 服务器 |
| VS Code Server / AHP | 需要 | 不需要 |
| 适合 | 日常远程开发 | 完整远程 Harness |
| 如果你的需求只是: |
我本地已经把 DSH、模型、插件、Skill 都配置好了,只想操作服务器项目。
那么通常没必要开 Backend。直接使用 Remote Workspace 更简单。
5. 权限模型:DSH 到底能访问服务器什么?
这里也需要特别注意。 Remote SSH 并不是一个操作系统级 Sandbox。 它最终拿到的权限,就是:
你 SSH 登录这个服务器账号所拥有的权限例如你通过:
User zx登录,那么 DSH 的远程工具本质上也运行在:
zx这个 Unix 用户身份下。 插件当前为了保持本地与远程工具行为一致,采用的是偏向完整访问的策略;README 也明确指出,AHP permission 本身不是 OS sandbox,如果 DSH 策略允许 Full Access,那么同一个 SSH 用户能访问 Workspace 外该 Unix 用户本身有权访问的路径。 所以:
DSH 权限 ≤你的 SSH 用户权限但并不等于:
DSH 只能访问 Workspace 目录如果需要更严格的隔离,真正可靠的方法依然是:
专用 Unix 用户容器虚拟机而不是仅依靠 Workspace 路径。
6. 远程服务器到底需要哪些东西?
测试主机时,你可能会看到类似:
bash ✓pwsh ×rg ✓code ×第一次看很容易误以为:
是不是四个都必须变成 ✓?
其实不是。
bash
Linux 服务器上这是最重要的一项。
DSH 需要通过 Bash 来执行:
pwdlspythongitnpmconda以及 Agent 产生的其他命令。 远端还需要:
base64mkfifo来支撑 Shell 和子进程相关功能。 对于正常 Ubuntu Server 来说,这几个一般都已经存在。
7. rg 是什么,为什么 DSH 需要它?
rg 是:
ripgrepDSH 会用它完成:
grepglob代码搜索文件搜索所以:
rg ×并不是无关紧要的小问题。
如果 rg 不可用,Agent 的代码检索能力会受到明显影响。
8. 最容易踩坑的地方:你明明安装了 rg,DSH 却说没有
这是我实际遇到的一个问题。 服务器中:
conda activate zx之后:
which rg输出:
/home/zhongxu/.conda/envs/zx/bin/rg并且:
rg --version完全正常。
看起来 rg 已经安装成功了。
但从本机测试:
ssh Server 'command -v rg'却什么都没有。 为什么?
9. DSH 使用的不是你平时登录后的交互 Shell
我们可以测试:
ssh Server 'echo "$PATH"'得到:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:...里面根本没有:
/home/zx/.conda/envs/zx/bin于是:
交互登录服务器 ↓conda activate zx ↓rg ✅但是:
DSH ↓非交互 SSH ↓没有 activate zx ↓rg ❌问题根本不在 rg。
问题在 PATH。
10. 真正的关键:.bashrc 顶部那个 return
Ubuntu 默认的 ~/.bashrc 通常开头就有:
# If not running interactively, don't do anythingcase $- in *i*) ;; *) return;;esac它的意思是:
如果当前不是交互 Shell,后面的
.bashrc就不要继续执行了。
而 Conda 初始化一般在文件后面:
# >>> conda initialize >>>...# <<< conda initialize <<<因此 DSH 通过非交互 SSH 执行命令时:
加载 ~/.bashrc ↓发现不是 interactive ↓return ↓Conda 初始化根本没有执行所以即使:
conda activate zx后能找到 rg,DSH 还是看不到。
11. 我最终采用的 rg 解决方案
我不建议让所有非交互 SSH 自动执行:
conda activate zx因为这样等于把:
pythonpip其他二进制全部偷偷切换到了 zx 环境。
更干净的方案是:
只把 DSH 真正需要的
rg暴露出来。
首先创建个人用户命令目录:
mkdir -p ~/bin然后建立软链接:
ln -sf /home/zx/.conda/envs/zx/bin/rg ~/bin/rg现在结构就是:
~/bin/rg │ └──► ~/.conda/envs/zx/bin/rg接下来才是这次配置中非常关键的一步。
编辑:
nano ~/.bashrc在文件最顶部、那个非交互 return 之前增加:
export PATH="$HOME/bin:$PATH"最终类似:
export PATH="$HOME/bin:$PATH"
# ~/.bashrc: executed by bash(1) for non-login shells.
# If not running interactively, don't do anythingcase $- in *i*) ;; *) return;;esac于是非交互执行过程变成:
SSH ↓读取 ~/.bashrc ↓export PATH="$HOME/bin:$PATH" ↓遇到非交互 return ↓停止加载其他环境虽然 Conda 没有激活,但:
~/bin/rg已经进入 PATH。
12. 验证 rg 是否真正解决
不要只在服务器里运行:
rg --version这不能证明 DSH 能看到它。
真正应该从本机测试:
ssh Server 'echo "PATH=$PATH"; echo "rg=$(command -v rg)"; rg --version | head -1'正确结果应该类似:
PATH=/home/zx/bin:/usr/local/sbin:...rg=/home/zhongxu/bin/rgripgrep 15.2.0看到这里:
rg=/home/zx/bin/rg才意味着:
DSH 的非交互远程环境真正能够找到
rg。
这也是我认为这一整套配置里最值得记录的坑之一。
13. code × 又是什么意思?
下一项比较容易误解的是:
code ×很多人第一反应可能是:
那是不是服务器必须安装完整 VS Code?
并不是。
Remote Workspace 需要的是:
VS Code Agent Host插件会依次寻找:
1. PATH 中的 code
2. ~/.dsh-remote-ssh/cli/bin/code
3. 已经存在的 VS Code Server cache这一 fallback 逻辑是插件明确实现的。
所以如果你以前使用过:
VS Code Remote - SSH服务器可能早就已经有:
~/.vscode-server14. 检查现有 VS Code Server
执行:
ls -lah ~/.vscode-server以及:
du -sh ~/.vscode-server如果之前经常使用 Remote-SSH,这个目录可能已经非常大。
例如我的服务器已经有多个版本:
~/.vscode-server/cli/servers/├── Stable-110a328...├── Stable-a5b500...├── Stable-c2d1b1...├── Stable-df53da...├── Stable-e4c7e7...└── Stable-8761a5...这是正常的。
它们本质上是不同 VS Code commit 留下来的 Server 版本。
15. 确认 code-server 是否存在
可以直接执行与插件搜索逻辑基本一致的命令:
find "$HOME/.vscode-server/cli/servers" \ -type f \ -path '*/server/bin/code-server' \ -perm -u+x \ -printf '%T@ %p\n' 2>/dev/null \ | sort -nr \ | cut -d ' ' -f 2-如果输出:
/home/user/.vscode-server/cli/servers/Stable-xxx/server/bin/code-server/home/user/.vscode-server/cli/servers/Stable-yyy/server/bin/code-server...说明现有 VS Code Server 可以被插件检测到。
而且插件并不是只尝试最新版本。
它会从新到旧依次尝试不同缓存,因为:
新版 VS Code Server ↓AHP 协议可能过新 ↓尝试旧版 ↓找到兼容版本这个 fallback 也是源码明确设计的行为。
因此暂时不要随便把旧的 VS Code Server 全删掉。
虽然它们确实可能占掉几 GB 空间,但旧版本有时候恰恰可能成为 Remote SSH 的兼容 fallback。
16. 为什么 code × 也可能完全正常?
这是另一个值得强调的地方。
如果 DSH 测试主机显示:
bash ✓rg ✓code ×并不能直接得出:
Remote Workspace 不可用code × 很可能仅仅代表:
command -v code失败了。
但插件仍然可以进一步找到:
~/.vscode-server/.../server/bin/code-server并使用现有 VS Code Server 建立 AHP。
所以最终判断标准不应该只是 UI 那几个 ✓ / ×。
真正应该测试:
Remote Workspace 能否:
pwd读取文件列目录grepglob执行 bash如果这些都正常,那么:
VS Code Server fallback 已经工作了。
17. pwsh × 是否需要处理?
如果你的服务器是 Linux:
pwsh ×通常完全不用管。
pwsh 指的是:
PowerShell对 POSIX/Linux Remote Workspace 来说,核心 Shell 是:
bash上游也明确区分:
POSIX Remote Workspace → bashWindows Workspace → pwsh当前远程 Workspace 主要支持 POSIX/Linux SSH 主机。
因此 Ubuntu 服务器最终类似:
bash ✓rg ✓pwsh ×code ×完全有可能已经可以正常工作。
18. SSH 本身也要先独立验证
在折腾插件之前,我建议一定先保证:
ssh Server本身可以正常连接。
例如:
Host Server HostName 10.122.xxx.xxx User user Port 22 IdentityFile ~/.ssh/id_ed25519 IdentitiesOnly yes先测试:
ssh Server再进入 DSH。
不要一开始就把:
SSH 配置问题VPN 问题密钥问题DSH 插件问题rg 问题VS Code Server 问题全部混在一起排查。
正确顺序应该是:
SSH ↓Workspace 映射 ↓bash ↓rg ↓VS Code Server / Agent Host ↓实际 Remote Workspace19. 最终测试 Remote Workspace
配置完成后,我比较推荐直接让 Agent 做一个无副作用测试:
请不要修改任何文件,只做环境检查:
1. 输出当前 pwd2. 执行 command -v rg3. 执行 rg --version4. 列出当前工作区一级文件5. 读取 README.md(如果存在)的前 20 行如果结果类似:
pwd/home/user/projects/aigc_detector
command -v rg/home/user/bin/rg同时:
目录可以列出文件可以读取rg 可以执行bash 可以执行那么整条链路实际上已经打通:
DSH Web │ ▼Remote Workspace │ ▼SSH │ ▼VS Code Server / AHP │ ├── File System ├── Search ├── Bash └── Background Tasks │ ▼Remote Project20. 最后总结:真正需要理解的几个关键点
整个配置折腾下来,我认为最容易踩坑的并不是 SSH 本身,而是**“交互环境”和“DSH 远程执行环境并不是同一个环境”**。
尤其是下面这一行:
export PATH="$HOME/bin:$PATH"以及它必须位于:
case $- in *i*) ;; *) return;;esac之前这一点,非常关键。
最终我自己的解决思路可以概括成:
第一步:SSH 本身必须能连接
第二步:把远程目录映射成 DSH Workspace
第三步:确认 bash 正常
第四步:安装 rg
第五步:不要只测试交互式 rg,而要测试非交互 SSH 能否找到 rg
第六步:使用 ~/bin 暴露 rg
第七步:在 ~/.bashrc 的 non-interactive return 前加入
export PATH="$HOME/bin:$PATH"
第八步:如果 code ×,先检查已有 ~/.vscode-server,不要急着重新安装 VS Code
第九步:实际测试 read / grep / bash / pwd,而不是只盯着测试页面的 ✓ / ×配置完成之后,最终得到的是一套我认为很舒服的远程开发结构:
┌───────────────────────────────┐│ Local Mac ││ ││ DSH Web ││ Model / Provider ││ Session ││ Plugins ││ Skills │└───────────────┬───────────────┘ │ SSH / AHP │┌───────────────▼───────────────┐│ Remote Linux Server ││ ││ Project ││ Data ││ Conda ││ Python ││ Bash ││ ripgrep ││ GPU │└───────────────────────────────┘本地仍然是自己的 DSH。
服务器仍然是服务器。
项目不需要完整同步到本地。
模型也不需要使用另一套所谓的 remote_* 工具。
你切换的不是工具,而是 Workspace。
这也是 dsh-remote-ssh 这套设计最吸引我的地方。
相关项目
上游项目:
https://github.com/Yan-Zero/dsh-remote-ssh我维护的 DSH rc.8 / Web 版本:
https://github.com/Zhong0118/dsh-remote-ssh我的版本目前主要服务于 DSH Web + Linux SSH Remote Workspace 这一场景,移除了 TUI 相关部分,并针对 DeepSeek Harness 0.1.0-rc.8 做了适配。后续如果继续长期使用这套工作流,也可能在此基础上继续补充 Web 端的体验和功能。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!