
字节笔记本
2026年10月6日 · 约 8 分钟读完
把已有 SSH 服务器接进 Codex 当远程工作区
把 VPS、家里的 NAS 或者公司跳板机接进 Codex,让它直接在远程机器上干活,听起来应该是件简单事,实际却常被卡住:官方生态里围绕云厂商的插件大多面向开一台新机器,而多数人手里已经有现成的服务器。ssh-workspace 是一个 MIT 开源的 Codex 插件,定位很明确:不创建新机器,不绑定任何云厂商,只把你已经拥有的服务器接成 Codex 的远程工作区。
它解决什么问题
Codex 桌面版支持把远程 SSH 主机当作工作区,但接入过程要做不少琐碎事:维护 SSH 别名、编辑 ~/.ssh/config、确认主机可达,再进设置页面把主机添加进去。ssh-workspace 把这整条链路包成一句自然语言指令。你在 Codex 里说连一台服务器,插件就会读取你的服务器清单、让你选一台、自动配好本地 SSH 并验证连通,最后生成一条深链,把剩下的交接动作交给 Codex App 完成。
整个流程只依赖插件自带的两个 Python 脚本和本机的 OpenSSH 工具(ssh 与 ssh-keygen),不需要安装额外依赖,也不会把密钥或密码发往任何远端。项目结构很小,一个 SKILL.md 流程单加两个脚本,总共不到两百行代码,方便改造和审计。

五步工作流
插件的执行流程是一条单行道,共五步:
- 读取清单。list_servers.py 解析 ~/.codex/servers.yml,把服务器列表以 JSON 输出。配置文件不存在时脚本以退出码 2 结束并打印示例配置;文件为空或条目缺少 alias、host 字段时以退出码 3 结束。两种情况都会停下来等用户先补配置,插件不会替你擅自创建文件。
- 让用户选机器。插件把清单渲染成编号表格,用户回复编号或别名。回复不在清单内会被再次询问,不会把未登记的值透传给后续步骤。
- 配置本地 SSH。configure_ssh.py 按所选条目在 ~/.ssh/config 写入一个 Host 块,先用 ssh-keyscan 刷新 known_hosts,再进入探测阶段。
- 验证连通。脚本用 BatchMode 的 ssh 反复探测,每 5 秒一试,最长等 120 秒,看到 CODEX_SSH_OK 回显即就绪;如果走密码认证,BatchMode 会返回 Permission denied,脚本把主机可达、认证待输入也视为通过,密码留到真正连接时再输入。
- 深链交接。插件返回一条 codex://settings/connections/ssh/add 形式的链接,点开后 Codex 直接进入添加 SSH 主机的流程,选中别名和远程目录即可开始干活。链接失效时也可以走手动路径:Codex App 的 Settings、Connections、Add SSH Host 里选同一别名。
一份 servers.yml 就够了
所有服务器都登记在一个文件里,每台至少要有 alias 和 host 两个字段,其余可选:
# ~/.codex/servers.yml
- alias: prod-box
host: 203.0.113.10
port: 22
user: ubuntu
key_path: ~/.ssh/id_ed25519
workdir: /home/ubuntu/projects
note: 生产服务器
- alias: homelab
host: 198.51.100.20
user: root
key_path: ~/.ssh/homelab_key
note: 家里 NAS
- alias: jump
host: jump.example.com
user: dev
port: 2222
use_password: true
note: 跳板机字段说明如下:
| 字段 | 必填 | 默认值 | 说明 |
|---|---|---|---|
| alias | 是 | 无 | SSH 别名,也是 Codex 里显示的名字 |
| host | 是 | 无 | IP 地址或域名 |
| port | 否 | 22 | SSH 端口 |
| user | 否 | root | 登录用户 |
| key_path | 否 | 无 | 密钥文件路径,与 use_password 二选一 |
| use_password | 否 | false | 改用密码登录 |
| workdir | 否 | $HOME | 提示 Codex 打开的远程目录 |
| note | 否 | 无 | 备注信息 |
workdir 只是展示给用户看的提示项,Codex 本身并不强制要求它。

写进 ~/.ssh/config 的东西
configure_ssh.py 为每台机器写入的 Host 块形如:
# --- prod-box (added by codex ssh-workspace) ---
Host prod-box
HostName 203.0.113.10
Port 22
User ubuntu
IdentityFile ~/.ssh/id_ed25519
StrictHostKeyChecking accept-new
ServerAliveInterval 60细节上有四处设计值得单独说:
- 幂等:重跑时脚本会先移除同别名的旧块再写入新块,反复执行不会在配置文件里留下越积越多的重复段落。
- accept-new:StrictHostKeyChecking 设为 accept-new,首次连接自动记录主机指纹,之后再变化就会被拒绝,能防中间人劫持。
- 探测节奏:每 5 秒试一次、总超时 120 秒,适配刚开机 sshd 还没就绪的机器。
- 退出码约定:configure_ssh.py 正常就绪返回 0,探测失败或写配置失败返回 1,参数缺失返回 2;加上 list_servers.py 的 2 和 3,每一步失败都有明确信号,插件据此停下来而不是继续猜。
安全边界
这个插件明确不做的事和它做的事同样重要:
- 不创建、不供应任何新服务器,只连接清单里登记过的已有机器,要开新云主机请用云厂商插件。
- 密钥与密码只在本地 ~/.ssh 目录内处理,从不下发到远端,脚本也不修改你的密钥文件,只读取 servers.yml 里指定的路径。
- 只允许自带的两个 Python 脚本和本机 OpenSSH,不调用其他 SSH 客户端,避免行为不可控。
和云厂商插件的分工
| 云厂商插件 | ssh-workspace | |
|---|---|---|
| 场景 | 开一台新的云机器 | 连已有的服务器 |
| 依赖 | 需绑定云厂商应用 | 不依赖任何云服务 |
| 计费 | 新机器按小时计费 | 无新增成本 |
| 适合 | 临时要干净环境 | 固定的开发机、跳板机、NAS |
小结
如果你的 Codex 工作经常发生在已有的某台机器上,比如固定的开发机、跳板机或家里的 NAS,ssh-workspace 提供了一条配置最少的接入路径:写一份 servers.yml,说一句连一台服务器,剩下的配置、验证与交接都由插件自动完成。项目以 MIT 协议开源,脚本短小,想按自己的习惯改造清单格式或探测策略,成本也很低。



