Why This Setup Exists
最近诸如 OpenCode、Claude Code 等基于终端(TUI/CLI)的 AI 编码智能体热度极高。相比传统的 Copilot 插件,这类 Agent 拥有真正的 Shell 执行权限、自主工具调用能力以及直接重写本地文件的能力。它们不再只是提供代码建议,而是能像一个真正的初级程序员一样,替你完成“理解需求 -> 修改代码 -> 运行单测 -> 修复 Bug”的完整闭环,也就是现在大家常说的 Vibe Coding。
然而,巨大的生产力背后也潜藏着非常现实的安全隐患:
- 系统权限暴露:AI 在执行复杂指令时可能误删宿主机文件,或者执行了错误的系统命令。
- 供应链攻击风险:AI 可能为了修复 Bug 而从网络下载、安装未经审核的第三方依赖包。如果依赖包里含有恶意后门,宿主机的 SSH Key、浏览器 Cookie、钥匙串及隐私文件都可能受到影响。
- 远程入口风险:为了随时随地调用本地算力和本地开发环境,很多人会暴露 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 有几个问题:
- 公网暴露面太大:即便换端口、只允许密钥登录,SSH 仍然是一个长期暴露的攻击入口。
- 权限边界模糊:一旦登录到宿主机,Agent 理论上就可以访问用户目录下的大量敏感文件。
- 操作不可控: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 使用。
一个典型流程如下:
- 在手机、平板或外部电脑上打开 WebSSH。
- 进入对应项目目录。
- 启动 AI Agent。
- 给它一个明确任务,例如“修复某个测试失败”或“实现某个 issue”。
- Agent 在容器内修改代码、安装依赖、运行测试。
- 确认 diff。
- 由人决定是否提交、推送或发起 PR。
我更推荐把提交和发布权限留给人,而不是完全交给 Agent。也就是说,AI 可以写代码、跑测试、解释 diff,但最终的 git commit、git push、部署和生产发布,最好还是经过人工确认。
如果要进一步自动化,可以给容器挂载一个权限极小的 GitHub Token:
- 只允许访问特定仓库。
- 只允许创建分支和 PR。
- 不给删除仓库、管理 Secret、发布 Release 等高危权限。
- Token 定期轮换。
Hardening Checklist
这套方案的核心不是某一个工具,而是组合后的安全边界。落地时可以按下面的清单检查:
- 网络入口:不开放公网 SSH 端口,只通过 Cloudflare Tunnel 暴露入口。
- 身份认证:Cloudflare Access 必须开启,禁止任何匿名访问。
- 执行环境:AI Agent 只在 Docker 容器里运行,不直接在宿主机运行。
- 文件挂载:只挂载当前项目目录,不挂载用户主目录。
- 用户权限:容器内使用普通用户,避免 root。
- 能力限制:使用
--cap-drop=ALL和no-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 自动化编程方案。