内容
# isopod
[](https://github.com/me1iissa/isopod/actions/workflows/ci.yml)
**适用于 Claude Code 的 Firecracker-microVM 沙盒 — 在快速、硬件隔离的 microVM 中运行命令,该 microVM 在每次调用后被销毁。**
isopod 在大约 **0.4 秒** 内启动一个真正的 [Firecracker](https://firecracker-microvm.github.io/) microVM(使用热池时,恢复时间以毫秒为单位),在其中执行一个命令,然后销毁该 VM。主机文件系统上没有任何内容被共享到 guest 中;隔离是 KVM 硬件边界加上 Firecracker 的 seccomp 过滤器,而不是共享内核。它通过一种共享核心的方式驱动:作为 **MCP 服务器** 为 Claude Code,以及作为 **CLI** 为人类和 CI。
> **状态:** 里程碑 M0-M6 完成(可行性 → 从 Rust 启动 → 执行 → 阶段 → 网络 → MCP+技能 → 热池),然后是安全强化波(默认仅 guest 公共出口,一个可选的无根 jail,边界 guest 控制的 host 接收器,摘要固定 guest 内核)。预 1.0;`main` 是支持线路。参见 [CHANGELOG.md](CHANGELOG.md) 和 [PLAN.md](PLAN.md)。
---
## 快速开始
先决条件:带有 `/dev/kvm` 的 Linux x86_64(您的用户在 `kvm` 组中)。完整细节、WSL2 注释和故障排除:**[docs/getting-started.md](docs/getting-started.md)**。
**选项 A — 安装发布包。** 从 [发布页面](https://github.com/me1iissa/isopod/releases) 获取 `.deb`、`.rpm` 或 tarball;它包含 CLI、MCP 服务器、jail 助手和预构建的 Firecracker + guest-agent 二进制文件,因此不需要 Rust 工具链或源代码构建:
```bash
sudo apt install ./isopod_*_amd64.deb # 或:sudo dnf install ./isopod-*.x86_64.rpm
isopod image fetch-kernel # 固定的、摘要验证的 guest 内核
isopod image build-all # guest rootfs 镜像(无特权)
sudo isopod setup # 一次性主机网络配置 — 唯一 root 步骤
isopod run --stage base --base base-alpine -- python3 -c 'print("hello from a microVM")'
```
**选项 B — 从源代码构建** (需要通过 rustup、 `nftables iproute2 e2fsprogs squashfs-tools` 和 C 工具链来获取 Rust):
```bash
git clone https://github.com/me1iissa/isopod.git
cd isopod
git submodule update --init --recursive # 供应商 Firecracker v1.16.1
cargo build --release
./target/release/isopod dev build-fc # 构建 Firecracker -> ~/.isopod/bin
./target/release/isopod image fetch-kernel
./target/release/isopod image build-all
sudo ./target/release/isopod setup
./target/release/isopod run --stage base --base base-alpine -- \
python3 -c 'print("hello from a microVM")'
```
要从 **Claude Code** 驱动它,请注册 MCP 服务器并重启会话:
```bash
claude mcp add --scope local isopod -- /usr/bin/isopod-mcp # 包安装
claude mcp add --scope local isopod -- "$PWD/target/release/isopod-mcp" # 源代码检出
# 然后,在 Claude Code 中: sandbox_run(cmd="echo hi")
```
---
## 为什么
代理需要一个快速、安全的地方来运行命令、构建代码和执行不受信任或实验性的工作负载。容器设置起来很复杂,清理起来很慢,并且共享主机内核。Firecracker microVM 提供硬件隔离,冷启动时间不到一秒, snapshot 恢复时间只有几毫秒 — 非常适合 **一次操作,一个沙盒** 的代理节奏。
isopod 围绕一个单一的想法构建:
- **沙盒是短暂的。** microVM 仅用于一次操作,然后被销毁。每次运行都是 `启动 → 执行 → 销毁`。
- **阶段是持久的。** 运行可以留下一个 *阶段* — 一个小型的写时复制磁盘层,捕获了它所更改的内容。后续运行 **分叉** 于一个阶段(在其上启动;阶段永远不会被修改)或 **堆叠** 一个新层。阶段是小型的、基于内容的、可移植的文件。除非有其他因素,否则没有任何内容会在 VM 之间存活。
---
## 关键概念
### 短暂的沙盒 vs. 持久的阶段
`sandbox_run`(MCP)/ `isopod run`(CLI)调用是完全短暂的:它启动一个全新的 VM,运行您的命令,捕获输出,然后销毁所有内容。要保留状态 — 已安装的包、构建的二进制文件、克隆的存储库 — 请传递一个提交标签。在干净退出(代码 0)时,isopod 将沙盒的文件系统更改冻结为一个 **不可变的、基于内容的(blake3)阶段**。后续运行 **分叉** 该阶段,方法是按名称、ID 或标签启动,并在其上运行。然后,您可以多次分叉一个阶段,并可以并发运行,它将保持字节不变。
```
运行 + 提交 ──► 阶段(不可变) ──► 分叉 ──► 运行 ──► 提交 ──► 堆叠阶段
│
└─► 分叉 ──► 瞬时运行 (父级不变)
```
### 热池
冷启动很快(~0.4 秒),但热恢复更快。isopod 保留一个 **完整的 VM 内存快照**,用于启动-空闲、无网络的 VM,按其必须匹配的 exact 环境进行键控。新的 `sandbox_run` 如果符合条件(新的基础镜像、网络开启、无提交、默认临时目录 — 完整规则见 [docs/getting-started.md](docs/getting-started.md))将 **热恢复** 该快照到一个空闲的网络时隙,时间以毫秒为单位,而不是冷启动,然后在该时隙中重新应用 IP 并通过 vsock 同步 guest 时钟。任何对密钥的更改(Firecracker 构建、主机内核、CPU 模型、基础风格、vCPU、内存、快照格式)都会静默使缓存失效并回落到冷启动。
---
## 架构
一个二进制核心(`isopod-core`)位于两个前端后面,并通过一个手工滚动的 typed 客户端驱动 Firecracker。所有跨调用状态都存储在 `~/.isopod` 下,文件锁定后允许多个会话共享它。
```mermaid
flowchart TB
CC["Claude Code"] -->|"stdio · rmcp JSON-RPC"| MCP["isopod-mcp<br/>MCP 服务器"]
HUMAN["人类 / CI"] -->|"argv + JSON"| CLI["isopod<br/>CLI"]
MCP --> CORE
CLI --> CORE
subgraph CORE_BOX["isopod-core — 协调库"]
CORE["vm · 阶段 · 快照<br/>网络 · 代理 · 存储 · 镜像"]
end
CORE -.->|"文件锁定状态"| STATE[("~/.isopod<br/>阶段 · 快照 · VM · 网络")]
CORE --> FCLIB["isopod-fc<br/>typed Firecracker 客户端"]
FCLIB -->|"HTTP/JSON over per-VM unix socket"| FCVMM["firecracker v1.16.1<br/>每个 VM 一个进程 · seccomp 开启 · 权限丢弃"]
FCVMM -->|"virtio-blk · 混合 vsock · virtio-net tap"| GUEST
subgraph GUEST_BOX["Guest microVM"]
GUEST["自定义 vmlinux 6.18<br/>isopod-guest-agent = PID 1<br/>overlay 基础 + 阶段 + 临时目录 · vsock RPC · 时钟同步"]
end
```
**板条箱** (参见 [CONTRIBUTING.md](CONTRIBUTING.md) 了解完整映射):
| 板条箱 | 包 | 角色 |
|---|---|---|
| `crates/fc-client` | `isopod-fc` | 类型化的 Firecracker 管理-API 客户端(每个 VM 一个 HTTP 客户端,预启动/后启动阶段保护)。独立的 SDK 候选。 |
| `crates/core` | `isopod-core` | 所有协调逻辑:VM 生命周期、阶段存储、快照/热池、网络、guest 代理 RPC、磁盘存储、镜像管道。 |
| `crates/proto` | `isopod-proto` | 主机↔guest vsock RPC 合同(长度前缀的 serde-JSON 帧)。 |
| `crates/guest-agent` | `isopod-guest-agent` | 作为 PID 1 在 guest 中运行的静态 musl 二进制文件:安装 overlay、pivot_root、同步时钟、在 vsock 上提供 exec/文件 RPC。 |
| `crates/cli` | `isopod` | `isopod` 二进制文件:`run`、`stage`、`vm`、`warmpool`、`setup`、`image`、`dev`。 |
| `crates/mcp` | `isopod-mcp` | 用于 Claude Code 的 rmcp 2.2 stdio MCP 服务器。 |
| `crates/jail` | `isopod-jail` | 可选的无根 microjail,用于包装每个 Firecracker 进程(用户/进程命名空间、最小 chroot、每个 VM 的 cgroup 权限)。 |
### `sandbox_run` 生命周期
```mermaid
sequenceDiagram
participant CC as Claude Code
participant MCP as isopod-mcp
participant Core as isopod-core
participant FcCli as isopod-fc
participant FC as Firecracker VMM
participant Guest as guest-agent PID 1
CC->>MCP: sandbox_run {cmd, 阶段, 网络, ...}
MCP->>Core: run_ephemeral(RunOptions)
Core->>Core: 声明网络时隙 + 临时目录(或热池恢复)
Core->>FcCli: 启动 FC,配置机器 / 启动 / 驱动器 / vsock / 网络
FcCli->>FC: PUT 机器配置,启动源,驱动器,网络,vsock
Core->>FC: 实例启动
FC->>Guest: 启动 vmlinux,执行 PID 1
Guest->>Guest: 安装 overlay,pivot_root,同步时钟,在 vsock:52 上监听
Core->>Guest: 执行 {argv, 环境, 工作目录, 超时} 通过 vsock
Guest-->>Core: 执行流块(stdout / stderr)
Guest-->>Core: 执行完成 {退出代码, 持续时间毫秒}
opt commit_as 已设置且退出代码 == 0
Core->>Guest: 停止 {同步}
Core->>Core: 内容寻址临时目录(blake3),存储为新阶段
end
Core->>FC: 关闭 / 杀死,释放网络时隙
Core-->>MCP: 运行报告 {退出代码, stdout, stderr, ...}
MCP-->>CC: JSON 结果
```
### VM 生命周期状态
```mermaid
stateDiagram-v2
[*] --> 配置中: 声明时隙 + 临时目录
配置中 --> 启动中: 冷启动
配置中 --> 恢复中: 热池命中
启动中 --> 运行中: PID 1 启动,vsock 准备就绪
恢复中 --> 运行中: 恢复 + 重新配置网络 / 时钟
运行中 --> 提交中: 退出 0 且 commit_as
运行中 --> 销毁中: 无提交
提交中 --> 销毁中: 阶段存储(blake3)
销毁中 --> [*]: FC 杀死,时隙释放
```
---
## 用法
### MCP 工具
isopod 暴露了六种工具。`sandbox_run` 是您 80% 的时间使用的工具;其余的工具用于检查和清理存储。
| 工具 | 它执行的操作 |
|---|---|
| `sandbox_run` | 启动一个 VM,通过 `/bin/sh -c` 运行 `cmd`,可选地将结果作为阶段提交,销毁 VM。除非设置了 `commit_as` 并且命令退出 0,否则为短暂的。 |
| `stage_list` | 列出每个已提交的阶段(ID、vanity 名称、标签、父级、基础、大小、创建时间)。 |
| `stage_info` | 完整的元数据加上一个阶段的已解析层链。 |
| `stage_rm` | 删除一个阶段(如果另一个阶段的链仍然从它分叉,则拒绝)。 |
| `vm_list` | 最近的 VM 记录 — 有助于在事后找到一个虚构名称。 |
| `vm_gc` | 清理孤立的 Firecracker 进程并清理旧的 VM 记录目录。 |
**运行一个短暂的代码片段:**
```
sandbox_run(cmd="python3 -c 'print(2**10)'")
```
**一次性构建环境,永久分叉:**
```
# 1. 安装依赖并提交结果(仅在退出 0 时提交)。
sandbox_run(cmd="pip install numpy pandas", commit_as="myproj/data-deps")
# 2. 后续运行分叉该阶段,而不是重新安装 — 毫秒级磁盘设置。
sandbox_run(cmd="python3 -c 'import numpy; print(numpy.__version__)'",
stage="myproj/data-deps")
```
**运行无网络的不受信任代码:
```
sandbox_run(cmd="python3 suspicious_script.py", network=false)
```
除了 `cmd` 之外,`sandbox_run` 还接受 `timeout_s`(**包括启动在内的外部时钟预算**)、`commit_as`、`cwd`/`env`、`stdin`/`stdin_file`、每个 VM 的大小调整(`vcpus`、`mem_mib`、`scratch_mib`)和 `copy_out` 用于将工件流式传输回主机。完整的参数和结果表位于 [docs/mcp-usage.md](docs/mcp-usage.md);每个工具的模式也是自描述的。
### CLI
相同的操作,一个命令和 JSON:
```bash
# 启动基础镜像,安装依赖,并在成功时提交一个阶段。
isopod run --stage base --base base-alpine --commit-as myproj/data-deps -- pip install requests
# 使用名称分叉该阶段(自动使用它所基于的基础)。
isopod run --stage myproj/data-deps -- python3 -c 'import requests; print(requests.__version__)'
# 大型构建:调整 VM 大小,馈送文件 stdin,复制工件输出。
isopod run --stage myproj/data-deps --vcpus 4 --mem-mib 3072 --scratch-mib 8192 \
--copy-out /root/out/artifact:./artifact -- /bin/sh -c 'make -C /root/out'
# 检查和清理存储。
isopod stage list
isopod stage info <id-or-name>
isopod vm gc --keep-last 20
# 热池。
isopod warmpool build
isopod warmpool list
```
每个子命令都精确地打印一个 JSON 对象到 stdout(人类可读的日志输出到 stderr),因此 CLI、MCP 服务器、人类和 CI 都可以驱动相同的核心。
---
## 阶段模型
阶段是一种持久性机制。每个阶段都是一个不可变的 ext4 overlay 层,通过 blake3 进行内容寻址,并存储在 `~/.isopod/stages/<id>/` 下,并附带一个 `meta.json` 记录其父链、标签、基础风味和大小。运行的 VM 从只读的基础 squashfs、只读的阶段层和新的可写临时驱动器组装成单个 overlay 挂载。
```mermaid
flowchart LR
BASE["base-alpine<br/>squashfs, 只读"]
S1["阶段:myproj/data-deps<br/>ext4 层 · 不可变"]
S2["阶段:myproj/data-deps+build<br/>堆叠层 · 不可变"]
BASE -->|"运行 + commit_as"| S1
S1 -->|"分叉 + 运行 + commit_as = 堆叠"| S2
S1 -.->|"分叉 · 只读 · 自由分支"| F1["短暂运行 A"]
S1 -.->|"分叉"| F2["短暂运行 B"]
S2 -.->|"分叉"| F3["短暂运行 C"]
```
- **提交** — 在干净退出后,内容寻址临时目录被存储。只有退出代码 0 才提交,因此失败的设置永远不会静默生成损坏的阶段。
- **分叉** — 在相同的只读下层链上启动一个 VM,并附带一个新的临时目录。毫秒级的磁盘设置,无需复制;下层链由所有并发分叉共享,永不被修改。
- **堆叠** — 在您分叉的阶段之上再次使用 `commit_as`,添加一个新层而不是覆盖它。每个链强制执行单个基础风味。
### 热池恢复
```mermaid
sequenceDiagram
participant Core as isopod-core
participant Cache as 热池缓存
participant FC as 新的 Firecracker
participant Guest as guest 代理
Note over Core,Cache: 键 = fc 构建 · 主机内核 · cpu 型号 · 基础风味 · vcpu · 内存 · 快照格式
Core->>Cache: 按键查找快照
alt 缓存命中(有效)
Cache-->>Core: vmstate + memfile
Core->>FC: 快照/加载 {文件后端, 恢复_vm, 网络覆盖, vsock_覆盖}
FC->>Guest: 恢复(无重启)
Core->>Guest: 配置网络 {ip, 网关, dns} + 通过 vsock 同步时钟
Note over Core,Guest: 数毫秒内恢复 vs 寒冷内核阶段
else 未命中或密钥更改
Core->>FC: 冷启动,然后构建和缓存快照
end
```
---
## 安全
**在运行不受信任的任何内容之前,请阅读 [SECURITY.md](SECURITY.md)。**
简而言之:
- 安全边界是 Firecracker VMM + KVM、消耗 guest 控制字节的主机端代码和 tap/nftables 网络结构 — 而不是 guest 内部。guest 内部,不受信任的代码按设计以 root 身份运行;guest 是可消耗的。
- Firecracker 以 **无特权**(kvm 组)运行,启用了 **seccomp 过滤器**,并丢弃了 **所有功能**。guest→host 和 guest→guest 被阻止,基础镜像是只读的,没有主机文件系统被共享到 guest 中。
- **默认情况下,guest 出口仅限公共网络。** 配置了网络的 guest 可以访问互联网,但不能访问主机的私有网络:RFC1918、CGNAT 和链路本地/元数据目的地被丢弃,并带有每个 tap 的反欺骗功能。(LAN 可达性是一个明确的选择:`isopod setup --allow-lan-egress`。)
- 一个 **可选的无根 jail** (`ISOPOD_JAIL=1`) 将每个 Firecracker 封装在用户/进程命名空间、最小 chroot 和每个 VM 的 cgroup 权限中 — 第二个隔离层,没有特权的主机组件。它在此版本中是可选的;启用它(或保持主机单一租户)后再运行相互不信任的工作负载。
- guest 控制的主机接收器是 **有边界的**:exec/串行日志的大小上限,每个 RPC 主机等待的时间都有边界,并且在启动之前会验证资源请求。
- 对于不受信任的代码,请首选 **`--no-network`(CLI)/`network=false`(MCP)** — 根本不附加网卡;exec 仍然通过 vsock 工作。
要报告漏洞,请使用此存储库上的 **GitHub 私有漏洞报告**(安全 → 建议 → *报告漏洞*)。请勿为安全漏洞开启公共问题。
---
## 项目状态
所有计划的 v1 里程碑均已完成,并增加了一个 post-v1 安全强化波:
| 里程碑 | 范围 |
|---|---|
| **M0** | 可行性冲刺 — 启动,snapshot 往返,NAT 出口,延迟基准。 |
| **M1** | 从 Rust 启动 — 类型化的 `isopod-fc` 客户端,镜像管道,Firecracker 从源代码构建。 |
| **M2** | 执行 — musl PID-1 guest 代理,vsock 执行,`isopod run`。 |
| **M3** | 阶段 — squashfs 基础 + guest overlay 链,内容寻址阶段存储,提交/分叉/堆叠。 |
| **M4** | 网络 — `sudo isopod setup`,用户拥有的 tap + nftables NAT,`--no-network`。 |
| **M5** | MCP + 技能 — rmcp 2.2 stdio 服务器,工作流技能,插件打包。 |
| **M5.5** | 灵活的每个 VM 的 vCPU / 内存大小。 |
| **M6** | 热池 — 完整的快照保存/恢复,恢复后通过 vsock 进行网络 + 时钟重新配置。 |
| **强化** | 默认公共出口,根 jail(`ISOPOD_JAIL=1`),有边界的 guest 控制主机接收器,摘要固定的 guest 内核,流式 `copy_out`,`stdin_file`。 |
积压工作(v2+):默认启用 jail、并发 VM 内存管理器 + I/O 速率限制器、exec/串行日志保留自动 GC、UFFD 延迟恢复 + 快照压缩、`stage flatten`、PTY 执行和主机到 guest 的端口转发。参见 [PLAN.md](PLAN.md)。
---
## 文档
| 文档 | 它涵盖的内容 |
|---|---|
| [docs/getting-started.md](docs/getting-started.md) | 完整的设置指南:先决条件、构建、镜像、网络、首次运行、jail、MCP 注册、故障排除、卸载。 |
| [docs/mcp-usage.md](docs/mcp-usage.md) | MCP 服务器注册(本地范围和插件)、工具列表、`sandbox_run` 参数和结果形状。 |
| [skill/SKILL.md](skill/SKILL.md) | 加载到 Claude 上下文的工作流技能 — 也是人类最简短的概念性介绍阶段模型。 |
| [SECURITY.md](SECURITY.md) | 安全模型:威胁模型、保持的内容、jail、已知限制、操作员指导。 |
| [CONTRIBUTING.md](CONTRIBUTING.md) | 构建、测试、板条箱映射、编码约定、版本策略。 |
| [CHANGELOG.md](CHANGELOG.md) | 发布历史。 |
| [PLAN.md](PLAN.md) | 原始架构计划和里程碑日志(保留为工程记录)。 |
| [docs/sandbox-build.md](docs/sandbox-build.md) | 在自己的沙盒中构建 isopod(狗粮配方)。 |
| [docs/feasibility.md](docs/feasibility.md)、[docs/m4-verify.md](docs/m4-verify.md)、[docs/dogfood-findings.md](docs/dogfood-findings.md) | 工程日志:M0 冲刺结果、M4 网络验证和正在运行的狗粮发现日志。 |
---
## 许可
根据 [Apache License, Version 2.0](LICENSE) 授权。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器