使用DevSpace 让 ChatGPT 能够远程操作本机项目

要解决的问题

购买了codex的plus版本,但额度有限,我希望 ChatGPT 能安全地连接到自己的远程 Linux 电脑,直接读取、修改和运行本机项目中的文件,而不是每次都手动复制代码、日志和命令输出。

最终要实现的效果是:

  • ChatGPT 可以通过 DevSpace 访问我明确授权的项目目录。
  • VS Code、本机终端和 ChatGPT 操作的是同一份文件。
  • 电脑重启后 DevSpace 可以自动恢复,不需要重新创建 ChatGPT 应用。
  • 外网访问走 Tailscale Funnel,不需要单独购买域名或配置公网 IP。

整体链路如下:

ChatGPT Web
    │ HTTPS + OAuth
    ▼
https://<设备名>.<tailnet>.ts.net/mcp
    │ Tailscale Funnel
    ▼
http://127.0.0.1:7676/mcp
    │ DevSpace
    ▼
本机已授权项目目录

本文记录的是本次部署中真正必要的步骤。已验证环境:Ubuntu 22.04、Node 22、@waishnav/devspace@1.0.1、Tailscale。
可直接把链接复制给codex,让其复现。

1. 安全边界

DevSpace 连接成功后,ChatGPT 可以在已打开的 workspace 中读写文件并运行命令,权限等同于启动 DevSpace 的 Linux 用户。

因此需要注意:

  • 不要用 root 用户启动 DevSpace。
  • Allowed root 只授权项目目录或项目父目录,不要授权整个磁盘。
  • 不要泄露 ~/.devspace/auth.json~/.local/share/devspace/oauth-state.json 和授权页面中的 Owner 密码。
  • Tailscale Funnel 是公网入口,日志中看到扫描请求是正常现象;真正的 MCP 调用仍需要 OAuth 授权。
  • 涉及写文件、运行命令时,应在 ChatGPT 里明确限定操作范围。

2. 准备变量和基础依赖

在仓库根目录执行。本文假设端口为 7676,授权目录按实际情况修改:

export DEVSPACE_PORT=7676
export DEVSPACE_ALLOWED_ROOT="$HOME/IsaacLab"
mkdir -p "$DEVSPACE_ALLOWED_ROOT"

sudo apt update
sudo apt install -y curl git jq patch ripgrep

如果希望 ChatGPT 同时操作多个项目,建议把 DEVSPACE_ALLOWED_ROOT 设为它们共同的父目录,例如 $HOME$HOME/projects。授权范围越大,风险越高。

3. 安装 Node 22 和 DevSpace

安装 Volta:

curl https://get.volta.sh | bash
source "$HOME/.bashrc"

安装 Node 22:

volta install node@22
node --version
npm --version

安装固定版本 DevSpace:

npm install -g @waishnav/devspace@1.0.1
volta which devspace

本文后面的补丁只针对 @waishnav/devspace@1.0.1,不要直接套到其他版本。

4. 应用 OAuth 持久化补丁

原版 DevSpace 1.0.1 把 OAuth 客户端和令牌保存在进程内存中。DevSpace 一旦重启,ChatGPT 仍持有旧 client_id,服务端却不认识它,会出现:

{"error":"invalid_client","error_description":"Invalid client_id"}

本仓库补丁会把 OAuth 状态持久化到:

~/.local/share/devspace/oauth-state.json

应用补丁:

export DEVSPACE_CLI="$(readlink -f "$(volta which devspace)")"
export DEVSPACE_ROOT="$(dirname "$(dirname "$DEVSPACE_CLI")")"
export DEVSPACE_PATCH="$PWD/scripts/devspace/devspace-1.0.1-persistent-oauth.patch"

jq -r '.name + "@" + .version' "$DEVSPACE_ROOT/package.json"

输出必须是:

@waishnav/devspace@1.0.1

备份并打补丁:

test -e "$DEVSPACE_ROOT/dist/oauth-provider.js.upstream" || \
  cp -p "$DEVSPACE_ROOT/dist/oauth-provider.js" \
    "$DEVSPACE_ROOT/dist/oauth-provider.js.upstream"

test -e "$DEVSPACE_ROOT/dist/server.js.upstream" || \
  cp -p "$DEVSPACE_ROOT/dist/server.js" \
    "$DEVSPACE_ROOT/dist/server.js.upstream"

patch --dry-run -d "$DEVSPACE_ROOT" -p1 < "$DEVSPACE_PATCH"
patch -d "$DEVSPACE_ROOT" -p1 < "$DEVSPACE_PATCH"

node --check "$DEVSPACE_ROOT/dist/oauth-provider.js"
node --check "$DEVSPACE_ROOT/dist/server.js"
node scripts/devspace/test_persistent_oauth.mjs "$DEVSPACE_ROOT"

测试通过时应看到:

OAuth persistence test passed

如果提示 Reversed (or previously applied) patch detected,说明可能已经打过补丁。先检查:

rg 'oauth-state.json' "$DEVSPACE_ROOT/dist/server.js"

以后如果重新安装 DevSpace,补丁可能被覆盖,需要重新检查并应用。

5. 安装并配置 Tailscale Funnel

安装并登录 Tailscale:

curl -fsSL https://tailscale.com/install.sh | sh
sudo systemctl enable --now tailscaled
sudo tailscale up

允许当前用户管理 Funnel:

sudo tailscale set --operator="$USER"

生成固定公网地址:

export TAILSCALE_DNS_NAME="$(tailscale status --json | jq -r '.Self.DNSName | rtrimstr(".")')"
export DEVSPACE_PUBLIC_BASE_URL="https://$TAILSCALE_DNS_NAME"
printf 'MCP URL: %s/mcp\n' "$DEVSPACE_PUBLIC_BASE_URL"

开启 Funnel,把公网 HTTPS 转发到本机 DevSpace 端口:

tailscale funnel --bg --yes "http://127.0.0.1:$DEVSPACE_PORT"
tailscale funnel status

预期能看到类似结构:

https://<设备名>.<tailnet>.ts.net (Funnel on)
|-- / proxy http://127.0.0.1:7676

6. 初始化 DevSpace

执行:

devspace init

按提示填写:

  • Allowed root$DEVSPACE_ALLOWED_ROOT 的实际路径。
  • Port7676
  • Public base URL$DEVSPACE_PUBLIC_BASE_URL 的实际值,末尾不要加 /mcp

检查配置:

devspace doctor
devspace config get
stat -c '%a %n' "$HOME/.devspace/config.json" "$HOME/.devspace/auth.json"

config.jsonauth.json 权限应为 600

如果公网地址填错,可以改:

devspace config set publicBaseUrl "$DEVSPACE_PUBLIC_BASE_URL"

7. 配置 DevSpace 自动启动

使用仓库脚本生成用户级 systemd 服务:

scripts/devspace/install_user_service.sh --dry-run
scripts/devspace/install_user_service.sh

验证服务:

systemctl --user is-enabled devspace.service
systemctl --user is-active devspace.service
systemctl --user status devspace.service --no-pager -l
curl -fsS "http://127.0.0.1:$DEVSPACE_PORT/healthz"

正常健康检查返回:

{"ok":true,"name":"devspace"}

本配置是“用户登录后自动启动”。如果无人登录也要启动,需要额外配置 systemd linger,但这会让远程入口更早暴露,默认不建议开启。

8. 验证公网链路

curl -fsS --max-time 20 "$DEVSPACE_PUBLIC_BASE_URL/healthz"
curl -fsS --max-time 20 "$DEVSPACE_PUBLIC_BASE_URL/.well-known/oauth-authorization-server"
curl -fsS --max-time 20 "$DEVSPACE_PUBLIC_BASE_URL/.well-known/oauth-protected-resource/mcp"

需要确认:

  • /healthz 返回 {"ok":true,"name":"devspace"}
  • OAuth 元数据里的 URL 都是当前固定的 *.ts.net 域名。
  • 不应残留 trycloudflare.com 或旧地址。

9. 在 ChatGPT 中创建应用

在 ChatGPT Web 中:

  1. 打开 Settings → Apps

  2. 打开 Advanced settings → Developer mode

  3. 点击 Create app

  4. 名称填写 DevSpace

  5. MCP URL 填写:

    https://<你的设备名>.<tailnet>.ts.net/mcp
    
  6. 保存并连接。

  7. 在 DevSpace 授权页输入 ~/.devspace/auth.json 里的 Owner 密码。

  8. 新建对话,在加号菜单里选择 Developer mode,并启用 DevSpace 应用。

不要把 Owner 密码发给 ChatGPT,也不要截图分享。

10. 端到端测试

在 ChatGPT 中要求它只做只读操作,例如:

只使用 DevSpace:打开 /home/j/IsaacLab,读取 README.md,执行 git status。不要修改文件。

本机查看日志:

journalctl --user -u devspace.service -n 100 --no-pager

应该能看到 /mcp 请求、mcp_session_created 和 HTTP 200

再测试重启持久化:

systemctl --user restart devspace.service
systemctl --user is-active devspace.service
stat -c '%a %n' "$HOME/.local/share/devspace/oauth-state.json"

oauth-state.json 权限应为 600。回到同一个 ChatGPT 应用再次执行只读任务,不应出现 invalid_client

11. 日常检查命令

export TAILSCALE_DNS_NAME="$(tailscale status --json | jq -r '.Self.DNSName | rtrimstr(".")')"
export DEVSPACE_PUBLIC_BASE_URL="https://$TAILSCALE_DNS_NAME"

systemctl is-active tailscaled
systemctl --user is-active devspace.service
tailscale funnel status
curl -fsS "$DEVSPACE_PUBLIC_BASE_URL/healthz"

重启 DevSpace:

systemctl --user restart devspace.service

查看实时日志:

journalctl --user -u devspace.service -f

12. 常见问题

invalid_client

通常是 OAuth 持久化状态失效或补丁被覆盖。

检查:

export DEVSPACE_CLI="$(readlink -f "$(volta which devspace)")"
export DEVSPACE_ROOT="$(dirname "$(dirname "$DEVSPACE_CLI")")"

rg 'oauth-state.json' "$DEVSPACE_ROOT/dist/server.js"
stat "$HOME/.local/share/devspace/oauth-state.json"
devspace config get

如果补丁不存在,确认版本仍是 1.0.1,重新应用第 4 节补丁并重启服务。

公网无法访问

systemctl status tailscaled --no-pager -l
tailscale status
tailscale funnel status
systemctl --user status devspace.service --no-pager -l

重新提交 Funnel:

tailscale funnel --bg --yes "http://127.0.0.1:$DEVSPACE_PORT"

DevSpace 服务启动后立即退出

可能是 Node 或 DevSpace 的真实路径变了,重新生成用户服务:

volta which node
volta which devspace
scripts/devspace/install_user_service.sh

日志中出现 /.env/.git/config 等扫描

这是公网入口常见扫描。只要 MCP 调用仍需要 OAuth,且 Allowed root 没有授权过大,一般不影响使用。仍建议保持系统和依赖更新。

13. 紧急关闭

关闭公网入口:

tailscale funnel reset

停止 DevSpace:

systemctl --user disable --now devspace.service

恢复使用:

systemctl --user enable --now devspace.service
tailscale funnel --bg --yes "http://127.0.0.1:$DEVSPACE_PORT"

14. 最终验收标准

部署完成后,应同时满足:

  • 本地 /healthz 返回 HTTP 200。
  • 公网 /healthz 返回 HTTP 200。
  • OAuth 元数据都指向同一个 *.ts.net 域名。
  • ChatGPT 能读取授权目录内文件并执行只读命令。
  • 重启 DevSpace 后,同一个 ChatGPT 应用仍能连接,不出现 invalid_client
  • ~/.devspace/auth.json~/.local/share/devspace/oauth-state.json 权限为 600

参考资料

  • DevSpace README
  • Volta Getting Started
  • Tailscale Install on Linux
  • Tailscale Funnel
  • OpenAI ChatGPT Developer mode
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐