CubeSandbox 本地开发环境搭建指南:用 QEMU/KVM 跑起可弃置的 OpenCloudOS 9 沙箱开发 VM
2026/9/15 13:49:52 网站建设 项目流程

CubeSandbox 本地开发环境搭建指南:用 QEMU/KVM 跑起可弃置的 OpenCloudOS 9 沙箱开发 VM

【免费下载链接】CubeSandboxInstant, Concurrent, Secure & Lightweight Sandbox for AI Agents.项目地址: https://gitcode.com/GitHub_Trending/cu/CubeSandbox

本文是 CubeSandbox 官方开发环境(dev-env/)的完整使用指南。它面向只有笔记本电脑或云主机、没有专用裸金属服务器,却想完整体验 Cube Sandbox(在 AI Agent 场景下即时、并发、安全、轻量的沙箱运行时)或想在其上做二次开发的开发者:通过在宿主机上启动一台可弃置的 OpenCloudOS 9 虚拟机,用三步命令就能获得一个与宿主机隔离、内部又具备嵌套 KVM 能力的完整沙箱实验场。读完本文,你将掌握开发 VM 的镜像制备、启动、登录、一键安装、资源调整、自检排障以及"改代码 → 同步进 VM → 重启服务验证"的完整迭代闭环。

适用场景:为什么要用开发 VM

dev-env/目录位于仓库根目录(dev-env),用一组 Shell 脚本把"下载官方镜像 → 制备镜像 → 启动 VM → 自动登录"整个流程串起来。官方文档明确给出它的适用边界:

  • 想要一个干净的 OpenCloudOS 9 环境来端到端体验 Cube Sandbox;
  • 手头只有带 KVM 与嵌套虚拟化的笔记本电脑或云 VM,而非物理服务器;
  • 希望在不污染宿主机的前提下,反复迭代 Cube Sandbox 的源码并看到修改后的真实运行效果。

⚠️ 这不是生产部署方式。官方文档明确声明这是一个development / evaluation(开发/评估)环境,是刻意设计为单节点、密码认证、可弃置的。生产环境请参考 Quick Start 或 Multi-Node Cluster 在裸金属上部署。

需要强调的核心约束:Cube Sandbox 会在 guest 内部再运行一层 KVM MicroVM(沙箱本身就是虚拟机),因此宿主机必须支持嵌套虚拟化,否则 guest 内没有可用的/dev/kvm,沙箱创建必然失败。

前置条件与宿主机要求

官方文档要求脚本运行在以下三种宿主机之一:

  • Windows 上的 WSL 2(要求 Windows 11 22H2+ 且开启 WSL 嵌套虚拟化);
  • 一台 Linux 物理机
  • 一台开启了嵌套虚拟化的 Linux VM(云主机或本地 VM 均可)。

三种情况共同的前提是宿主机能用 KVM——/dev/kvm必须存在且可读写。

宿主机需要安装的软件依赖如下:

依赖说明
Linux x86_64 或 aarch64 (ARM64)且 KVM 已启用(/dev/kvm存在)
嵌套虚拟化必须在宿主机开启
qemu-system-x86_64(ARM64 为qemu-system-aarch64)、qemu-imgQEMU 与磁盘工具
curlsshscpsetsid下载镜像、自动化 SSH 登录
EDK2/AAVMF 固件(仅 aarch64)ARM64 上 VM 以 QEMUvirt机型 + UEFI 固件启动,需安装QEMU_EFI.fd(如qemu-efi-aarch64包)

从源码看,run_vm.sh 会自动探测宿主机架构(TARGET_ARCH默认取uname -m,必要时可用环境变量覆盖);在 aarch64 上它会依次在多个发行版路径中查找 UEFI 固件(Debian/Ubuntu 的/usr/share/qemu-efi-aarch64/QEMU_EFI.fd、Fedora/RHEL/OC9 的/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw等),找不到时给出明确的安装提示。

快速开始:三步启动开发 VM

克隆仓库并进入dev-env/

git clone https://gitcode.com/GitHub_Trending/cu/CubeSandbox cd CubeSandbox/dev-env

总共三个命令:前两个在同一个终端执行,第三个需要另开一个终端

Step 1:制备镜像(一次性)

./prepare_image.sh

该脚本从腾讯镜像站下载官方 OpenCloudOS 9 qcow2,并执行初始化。每份全新镜像只需运行一次——除非你删除了生成的.workdir/目录,才需要重新执行。

从源码看,prepare_image.sh 的流程是:检查镜像是否已缓存 → 用qemu-img resize将 qcow2 就地扩容到默认 100G → 以后台模式调用run_vm.sh启动 VM → 通过 SSH(借助SSH_ASKPASS自动填充默认密码)依次上传并执行 guest 内的初始化脚本 → 最后优雅关机,产出一份"金镜像"。

Step 2:启动 VM

./run_vm.sh

QEMU 串行控制台会挂接在当前终端上。注意不要用Ctrl+a再按x强行退出 QEMU——这种粗暴退出可能损坏 guest。正确做法是另开终端用./login.sh登录,在 guest 内执行poweroff

源码层面,run_vm.sh 在 x86_64 上使用 q35 机型、aarch64 上使用 virt 机型,均以-enable-kvm -cpu host直通宿主机 CPU,并通过 QEMU 用户态网络的hostfwd一次性建立 5 组端口转发。

Step 3:登录(新终端)

./login.sh

login.sh以 root 身份登录 VM——Cube Sandbox 的安装器要求 root 权限。从源码看,login.sh 通过setsid+SSH_ASKPASS自动完成密码认证(无需提前配置 SSH 密钥),默认执行sudo -i切换到 root shell,可用LOGIN_AS_ROOT=0保留普通用户身份。

在 VM 内安装 Cube Sandbox

进入 root shell 后,运行标准的一键安装器:

curl -sL https://github.com/tencentcloud/CubeSandbox/raw/master/deploy/one-click/online-install.sh | bash

::: tip 中国大陆使用腾讯云镜像加速

curl -sL https://cnb.cool/CubeSandbox/CubeSandbox/-/git/raw/master/deploy/one-click/online-install.sh | MIRROR=cn bash

:::

安装完成后,按官方 Quick Start 的指引在 VM 中创建模板并运行你的第一个沙箱。安装完成的标志是核心进程存活:cubemastercube-apicubelet(旧的独立网络运行时现已嵌入cubelet);可在 VM 内执行curl -sf http://127.0.0.1:3000/health && echo OK验证。

dev-env 中的 cubecow 存储

Cubelet 默认使用仅依赖 reflink 的cubecow存储后端。开发 VM不需要 LVM/dm-thin 工具或额外裸盘,只需data_path指向的路径位于支持 reflink 的文件系统上(例如以-m reflink=1挂载的 XFS,或 Btrfs)。文档说明:默认的[plugins."io.cubelet.internal.v1.storage".cow.*]配置会在<data_path>/../cubecow-reflink下创建 reflink 卷。

对照仓库中的实际配置,Cubelet/config/config.toml 中可以看到storage_backend = "cubecow"data_path = "/data/cubelet/storage"的默认值,其注释同时指出 cubecow 的 reflink 卷落在<data_path>/xfs/objects(要求底层文件系统支持 FICLONE)。从源码结构还可以推断:cubecow-reflink是重构前遗留的 reflink 池目录名(见 Cubelet/storage/s3_snapshot_layout.go 的legacyReflinkDirName与 Cubelet/storage/legacy_reflink_cleanup.go 的清理逻辑),新版本对象存放在xfs/objects下。因此如果你在 VM 中看到cubecow-reflink目录,不必惊慌——它是兼容旧数据的布局,开发场景下关键在于data_path所在文件系统必须支持 reflink。

宿主机自检:确认 KVM 与嵌套虚拟化

先做快速健康检查:

ls -l /dev/kvm # Intel cat /sys/module/kvm_intel/parameters/nested # AMD cat /sys/module/kvm_amd/parameters/nested

如果nested参数读出来是N0,需要先在宿主机开启嵌套虚拟化。Intel 示例:

echo 'options kvm_intel nested=1' | sudo tee /etc/modprobe.d/kvm.conf sudo modprobe -r kvm_intel && sudo modprobe kvm_intel

从源码看,run_vm.sh 在启动前会强制校验:只要REQUIRE_NESTED_KVM=1(默认),若嵌套参数不是Y/1就直接报错退出——除非显式设置REQUIRE_NESTED_KVM=0(此时 OS 能启动但沙箱无法运行)。

宿主机 ↔ guest 端口映射

run_vm.sh会自动配置以下转发(源码见 run_vm.sh 的hostfwd参数):

宿主机Guest用途
127.0.0.1:10022:22SSH 登录开发 VM
127.0.0.1:13000:3000Cube Sandbox E2B 兼容 API
127.0.0.1:11080:80CubeProxy HTTP
127.0.0.1:11443:443CubeProxy HTTPS
127.0.0.1:12088:12088WebUI HTTP

其中 SSH 与 Cube API 两组是官方开发环境文档明确列出的,后三组(CubeProxy/WebUI)可在 dev-env/README.md 与 run_vm.sh 的头部注释中确认。默认资源配置为 4 vCPU、8192 MB 内存。

prepare_image.sh 在 guest 内部做了什么

官方文档把镜像制备的 guest 内动作归纳为四项,每项都能在dev-env/internal/下找到对应脚本:

  1. 扩容根分区与文件系统,占满整块 100 GB 虚拟盘。实现见 internal/grow_rootfs.sh:脚本先用findmnt/lsblk定位根设备与文件系统类型,若根在 LVM 上则走pvresize+lvextend -r -l +100%FREE;普通分区则用growpart扩分区、再按文件系统类型调用xfs_growfs /(XFS 在线扩容)或resize2fs(ext 系列),对NOCHANGE情况有专门容错。
  2. 将 SELinux 切换为 permissive(运行时 + 持久化到/etc/selinux/config)。原因在 internal/setup_selinux.sh 的注释中写得很清楚:Cube Sandbox 的 MySQL 容器把宿主目录 bind-mount 到/docker-entrypoint-initdb.d,在 enforcing 模式下容器进程会被container-selinux策略拒绝(Permission denied),导致 MySQL 反复重启;开发环境是"可弃置"的,所以最稳的办法就是切到 permissive。
  3. 确保/usr/local/{sbin,bin}同时在登录 PATH 和 sudo 的secure_path。实现见 internal/setup_path.sh:前者通过写入/etc/profile.d/cubesandbox-path.sh实现;后者生成/etc/sudoers.d/00-cubesandbox-path,且在安装前先执行visudo -cf校验语法,避免因 sudoers 语法错误把 sudo 锁死。
  4. 安装欢迎横幅/etc/profile.d/cubesandbox-banner.sh。见 internal/setup_banner.sh,每次登录 shell 都会显示Welcome to the Cube Sandbox development environment!以及 guest 内 Cube API 地址等提示。

此外,当SETUP_AUTOSTART=1(默认)时,prepare_image.sh 还会通过 internal/setup_autostart.sh 在 guest 内安装cube-sandbox-oneclick.service这个 systemd 单元(借助ConditionPathExists在未安装一键脚本时静默空转),但不会 enable——启用是后续的显式动作。

常用覆盖变量(环境变量)

三个脚本都支持环境变量覆盖(源码中的默认值可在各脚本头部确认):

# 仅下载 + 扩容,跳过 guest 内自动初始化流程 AUTO_BOOT=0 ./prepare_image.sh # 分配更多资源,或更换转发的 Cube API 端口 VM_MEMORY_MB=16384 VM_CPUS=8 CUBE_API_PORT=23000 ./run_vm.sh # 不要求嵌套 KVM 也能启动(OS 可启动但沙箱跑不起来) REQUIRE_NESTED_KVM=0 ./run_vm.sh # 以普通用户而非 root 登录 LOGIN_AS_ROOT=0 ./login.sh

各变量默认值汇总如下(结合官方文档与 dev-env/README.md):

脚本变量默认值说明
prepare_image.shAUTO_BOOT1是否自动启动 VM 执行 guest 内初始化
SETUP_AUTOSTART1是否安装自启 systemd 单元(仍不启用)
IMAGE_URLOpenCloudOS 9 官方镜像覆盖镜像源地址
TARGET_SIZE100Gqcow2 虚拟磁盘最终大小
SSH_PORT10022宿主机转发到 guest 22 的端口
run_vm.shVM_MEMORY_MB/VM_CPUS8192/4guest 内存与 vCPU
SSH_PORT10022SSH 转发
CUBE_API_PORT13000Cube API 转发(guest:3000
CUBE_PROXY_HTTP_PORT/CUBE_PROXY_HTTPS_PORT11080/11443CubeProxy HTTP/HTTPS 转发
WEB_UI_PORT12088WebUI 转发
REQUIRE_NESTED_KVM1嵌套 KVM 关闭时拒绝启动;0跳过
login.shLOGIN_AS_ROOT10保持普通用户身份

让 Cube Sandbox 开机自启(可选但强烈建议)

默认情况下,guest 内的一键栈是以裸进程方式启动的,VM 重启后不会自动恢复。若要 systemd 在每次开机时拉起整套组件,请在宿主机上执行:

./cube-autostart.sh # 默认子命令:enable

脚本会请求确认,然后在 guest 内启用cube-sandbox-oneclick.service(实现见 cube-autostart.sh,它通过 SSH 远程执行systemctl enable --now)。此后每次开机都会运行up-with-deps.sh,把 MySQL/Redis、cube-proxy、coredns、cubemaster、cube-api、cubelet 一起拉起。其它子命令:

./cube-autostart.sh status # 查看 is-enabled / is-active ./cube-autostart.sh disable # 回滚(STOP_NOW=0 可只禁用不停止)

开发迭代闭环:改代码 → 同步 → 重启验证

这是dev-env/存在的核心价值,流程在 dev-env/README.md 中有完整说明:

  1. 保持一个./login.sh的 root shell 常开;
  2. 在宿主机 shell 中构建并同步二进制:
    make all ./sync_to_vm.sh bin cubelet cubemaster

    sync_to_vm.sh现在只负责拷贝文件进 VM,不再负责构建、重启、回滚。它支持bin [NAME ...](同步_output/bin下的已知组件,省略 NAME 则全量)与files [--remote-dir DIR] PATH ...(推送任意文件)两种模式;

  3. 把脚本打印的重启命令粘贴进./login.sh会话:
    systemctl restart cube-sandbox-oneclick.service
  4. 故障时用./copy_logs.sh把 guest 内/data/log打成data-log-<时间戳>.tar.gz拉到宿主机排查。旧二进制在 VM 中保留为*.bak,必要时可手动回退。

推送 WebUI 可用make -C .. web-sync-dev-env;手动发版流程为make manual-release后用sync_to_vm.sh files上传发布包,再在 guest 内执行bash /tmp/deploy-manual.sh /tmp/cube-manual-update-*.tar.gz

重置与清理

  • 重置 VM 状态:停止正在运行的run_vm.sh,删除dev-env/.workdir/,再执行一次./prepare_image.sh
  • 开发 VM 刻意设计为可弃置:每当已安装状态变得不可用时,直接重建即可。生成的 qcow2、QEMU PID 文件、串行日志都位于.workdir/下。

故障排查速查表

症状可能原因修复方法
guest 内没有/dev/kvm宿主机未开启嵌套 KVM在宿主机开启嵌套虚拟化并重启 VM
./login.sh连不上VM 未启动完成,或宿主机 10022 端口被占用确认./run_vm.sh仍在运行;或改用SSH_PORT
cube-sandbox-mysql反复重启且报Permission deniedguest SELinux 仍为 enforcing重跑./prepare_image.sh;或在 guest 内:setenforce 0 && sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config && docker restart cube-sandbox-mysql
guest 内df -h /依旧很小自动扩容步骤未完成检查.workdir/qemu-serial.log,然后将internal/grow_rootfs.shscp 进 guest 手动执行
宿主机 13000 端口被占用其它服务占用了转发端口使用CUBE_API_PORT=23000 ./run_vm.sh,并同步更新E2B_API_URL;若 11080/11443/12088 同样冲突,可一并覆盖
VM 重启后组件消失未启用自启单元执行一次./cube-autostart.sh
同步新二进制后重启失败新构建有问题查看 guest 内/data/log/;必要时手动恢复*.bak旧二进制后再重启

目录布局速览

dev-env/ ├── prepare_image.sh # 一次性:下载 + 扩容 + guest 侧初始化 ├── run_vm.sh # 日常:启动 VM ├── login.sh # 日常:SSH 登录并切换 root ├── cube-autostart.sh # 启用/停用/查看 guest 内自启单元 ├── sync_to_vm.sh # 把宿主机产物同步进 guest(不构建不重启) ├── copy_logs.sh # 拉取 guest 内 /data/log 日志归档 ├── internal/ # 由 prepare_image.sh 在 guest 内调用的辅助脚本 │ ├── grow_rootfs.sh # 扩容根文件系统至 qcow2 虚拟大小 │ ├── setup_selinux.sh # SELinux 切 permissive(Docker bind-mount 兼容) │ ├── setup_path.sh # PATH 与 sudo secure_path 修正 │ ├── setup_banner.sh # /etc/profile.d/ 登录横幅 │ └── setup_autostart.sh # 安装 cube-sandbox-oneclick.service(不启用) ├── README.md └── README_zh.md

整套脚本的简短总览可进一步阅读仓库中的 dev-env/README.md。需要再次强调的是:这个环境是单节点、密码认证、可弃置的开发/评估用途,请勿在其中承载真实业务负载。

【免费下载链接】CubeSandboxInstant, Concurrent, Secure & Lightweight Sandbox for AI Agents.项目地址: https://gitcode.com/GitHub_Trending/cu/CubeSandbox

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询