Why This Setup Exists

最近诸如 OpenCode、Claude Code 等基于终端(TUI/CLI)的 AI 编码智能体热度极高。相比传统的 Copilot 插件,这类 Agent 拥有真正的 Shell 执行权限自主工具调用能力以及直接重写本地文件的能力。它们不再只是提供代码建议,而是能像一个真正的初级程序员一样,替你完成“理解需求 -> 修改代码 -> 运行单测 -> 修复 Bug”的完整闭环,也就是现在大家常说的 Vibe Coding。

然而,巨大的生产力背后也潜藏着非常现实的安全隐患:

  1. 系统权限暴露:AI 在执行复杂指令时可能误删宿主机文件,或者执行了错误的系统命令。
  2. 供应链攻击风险:AI 可能为了修复 Bug 而从网络下载、安装未经审核的第三方依赖包。如果依赖包里含有恶意后门,宿主机的 SSH Key、浏览器 Cookie、钥匙串及隐私文件都可能受到影响。
  3. 远程入口风险:为了随时随地调用本地算力和本地开发环境,很多人会暴露 SSH、Web IDE 或代理服务。一旦鉴权和网络边界没做好,就等于把开发机挂在了互联网上。

所以我想解决的是一个很明确的问题:既要随时随地远程调用 AI 帮我写代码,又要尽可能保证宿主机安全

本文记录的方案,是将 WebSSH + Cloudflare Tunnel + Docker 沙箱 + AI Agent CI 融合起来的一套本地自动化编程环境。它的目标不是宣称“永远不可能被攻破”,而是在工程上把风险压缩到一个可控的容器边界内。


Architecture

整体架构遵循两个原则:

  • 最小权限原则:AI Agent 只拿到完成任务所需的目录、网络、令牌和系统能力。
  • 数字侧隔离:所有高风险命令、依赖安装、测试运行和代码修改,都发生在 Docker 容器内部,而不是宿主机。

可以把整个系统理解成四层:

Browser
  |
  | Cloudflare Access / WebSSH
  v
Cloudflare Tunnel
  |
  v
Local Docker Host
  |
  v
AI Agent Sandbox Container
  |
  v
Mounted Project Workspace

其中:

  • Cloudflare Tunnel 负责把本地服务安全地暴露到外部,不需要公网 IP,也不需要在路由器上做端口转发。
  • Cloudflare Access 负责身份认证,可以接入邮箱、GitHub、Google、OIDC 或其他 Zero Trust 策略。
  • WebSSH 提供浏览器内远程终端入口,用来访问受控的 AI Agent 环境。
  • Docker Sandbox 是真正运行 AI Agent 的执行层,所有危险操作都限制在容器内。
  • 项目目录挂载 只暴露需要修改的代码仓库,不把整个宿主机文件系统交给 AI。

Why Not Expose SSH Directly?

最直接的远程开发方案当然是开 SSH。但对于 AI Agent 场景,裸 SSH 有几个问题:

  1. 公网暴露面太大:即便换端口、只允许密钥登录,SSH 仍然是一个长期暴露的攻击入口。
  2. 权限边界模糊:一旦登录到宿主机,Agent 理论上就可以访问用户目录下的大量敏感文件。
  3. 操作不可控:AI 可能执行 rm -rf、安装全局依赖、修改 shell 配置,甚至污染宿主机开发环境。

Cloudflare Tunnel 的优势是:本地机器只需要主动连接 Cloudflare,不需要开放入站端口。再配合 Cloudflare Access,外部访问必须先过身份认证和策略校验。

这并不意味着 SSH 本身不安全,而是说在 AI Agent 这种“会自己执行命令”的场景里,不要让它直接站在宿主机上操作


Docker Sandbox

真正的安全边界来自 Docker 容器。

一个比较稳妥的容器设计应该满足:

  • 不挂载宿主机根目录。
  • 不挂载 ~/.ssh~/.config、浏览器目录、钥匙串目录等敏感路径。
  • 只挂载单个项目工作区。
  • 使用非 root 用户运行 Agent。
  • 限制容器能力,尽量关闭不必要的 Linux capabilities。
  • 对高风险任务使用一次性容器,任务完成后销毁。
  • API Key 和 Token 使用环境变量或 Secret 注入,不写死在镜像里。

示例启动命令:

docker run -it --rm \
  --name sandbox-runner \
  --hostname sandbox \
  --user 1000:1000 \
  --cap-drop=ALL \
  --security-opt no-new-privileges:true \
  --memory=4g \
  --cpus=2 \
  -v "$PWD:/workspace" \
  -w /workspace \
  -e OPENAI_API_KEY \
  agent-sandbox:latest

这里的关键点不是命令本身,而是权限模型:

  • Agent 只能看到 /workspace
  • 容器退出后,除了挂载的项目目录,其他运行痕迹全部消失。
  • 即使依赖安装脚本有问题,影响范围也主要限制在容器文件系统内。

Build the Agent Image

可以准备一个专门用于 AI 编程的基础镜像,里面预装常用开发工具、语言运行时和 Agent CLI。

示例 Dockerfile

FROM node:22-bookworm

RUN apt-get update && apt-get install -y --no-install-recommends \
    git \
    curl \
    ca-certificates \
    openssh-client \
    ripgrep \
    jq \
    python3 \
    python3-pip \
    build-essential \
  && rm -rf /var/lib/apt/lists/*

RUN useradd -m -u 1000 agent

USER agent
WORKDIR /workspace

RUN npm install -g opencode-ai

CMD ["bash"]

构建镜像:

docker build -t agent-sandbox:latest .

这类镜像可以根据自己的技术栈继续扩展,比如加入:

  • Go / Rust / Python / Java 工具链
  • pnpm / uv / cargo / bun
  • GitHub CLI
  • 项目常用的 lint、test、build 工具

但我建议保持一个原则:镜像里放通用工具,项目依赖仍然在容器内按项目安装。这样可以避免把某个项目的脏状态固化到基础镜像里。


Expose WebSSH Through Cloudflare Tunnel

本地可以运行一个 WebSSH 服务,例如容器化的 SSH 网关,或者一个只连接到沙箱容器的 Web Terminal。然后用 Cloudflare Tunnel 暴露它。

cloudflared 的配置可以类似这样:

tunnel: <tunnel-name>
credentials-file: /path/to/cloudflared/credentials.json

ingress:
  - hostname: <your-private-subdomain.example.com>
    service: http://127.0.0.1:<webssh-port>
  - service: http_status:404

启动 Tunnel:

cloudflared tunnel run <tunnel-name>

然后在 Cloudflare Zero Trust 里为对应的私有子域名配置 Access Policy:

  • 只允许自己的邮箱或组织账号访问。
  • 开启一次性验证码、GitHub / Google 登录或硬件密钥。
  • 设置会话有效期,不要无限期保持登录。
  • 对敏感入口可以增加地理位置、设备状态或 IP 策略。

这样外部访问链路就变成了:

Browser -> Cloudflare Access -> Cloudflare Tunnel -> Local WebSSH -> Docker Sandbox

Use the Agent Like a CI Worker

有了稳定的远程入口和沙箱环境之后,就可以把 AI Agent 当成一个本地 CI Worker 使用。

一个典型流程如下:

  1. 在手机、平板或外部电脑上打开 WebSSH。
  2. 进入对应项目目录。
  3. 启动 AI Agent。
  4. 给它一个明确任务,例如“修复某个测试失败”或“实现某个 issue”。
  5. Agent 在容器内修改代码、安装依赖、运行测试。
  6. 确认 diff。
  7. 由人决定是否提交、推送或发起 PR。

我更推荐把提交和发布权限留给人,而不是完全交给 Agent。也就是说,AI 可以写代码、跑测试、解释 diff,但最终的 git commitgit push、部署和生产发布,最好还是经过人工确认。

如果要进一步自动化,可以给容器挂载一个权限极小的 GitHub Token:

  • 只允许访问特定仓库。
  • 只允许创建分支和 PR。
  • 不给删除仓库、管理 Secret、发布 Release 等高危权限。
  • Token 定期轮换。

Hardening Checklist

这套方案的核心不是某一个工具,而是组合后的安全边界。落地时可以按下面的清单检查:

  • 网络入口:不开放公网 SSH 端口,只通过 Cloudflare Tunnel 暴露入口。
  • 身份认证:Cloudflare Access 必须开启,禁止任何匿名访问。
  • 执行环境:AI Agent 只在 Docker 容器里运行,不直接在宿主机运行。
  • 文件挂载:只挂载当前项目目录,不挂载用户主目录。
  • 用户权限:容器内使用普通用户,避免 root。
  • 能力限制:使用 --cap-drop=ALLno-new-privileges 降低逃逸风险。
  • 资源限制:设置 CPU、内存上限,防止异常任务拖垮宿主机。
  • 密钥管理:Token 只给最小权限,避免把长期主密钥塞进容器。
  • 人工确认:提交、推送、发布等动作保留人工关口。
  • 日志审计:保留 Tunnel、Access、容器和 Git 操作记录,方便回溯。

需要强调的是:Docker 不是虚拟机,容器隔离也不是绝对安全边界。如果你要执行极高风险的未知代码,更严格的方案应该是独立虚拟机、一次性云主机,甚至专门的隔离物理机。

但对于日常 AI 编程任务,Docker 沙箱已经能显著降低误操作和供应链攻击对宿主机的影响。


Who This Is For

我认为它特别适合以下场景:

  • 经常使用 OpenCode、Claude Code、Codex CLI 等终端 AI Agent。
  • 希望在外部网络也能远程调用受控开发环境。
  • 不想把 SSH、IDE 或内网服务直接暴露到公网。
  • 担心 AI Agent 误删文件、污染环境或乱装依赖。
  • 希望把受控计算环境变成一个低成本、可审计的 AI Coding Worker。

它不适合追求“开箱即用”的用户。因为这套方案涉及 Cloudflare Zero Trust、Tunnel、Docker、WebSSH、权限模型和密钥管理,需要一定 DevOps 基础。


Summary

AI Agent 正在把编程从“人写代码、AI 补全”推进到“人下达目标、AI 执行任务”的新阶段。越是强大的工具,越不能随手丢到宿主机上裸跑。

我的最终设计思路很简单:

远程访问交给 Cloudflare
身份认证交给 Zero Trust
命令执行交给 Docker
代码审查和发布决策留给人

通过 Cloudflare Tunnel 和 WebSSH,我可以随时随地进入自己的本地 AI 编程环境;通过 Docker 沙箱,我又能把 Agent 的破坏半径限制在单个项目里。

这不是绝对意义上的“无敌安全”,但它是一个足够实用、成本很低、边界清晰的个人 AI Agent CI 自动化编程方案。