sandbox-ubuntu:在 Windows 上开出一台用完即删的"全新 Ubuntu 云机"

写部署文档、写一键安装脚本的人,大概都踩过同一个坑:脚本在自己机器上跑得顺顺当当,丢到一台干净的服务器上却直接报错——因为脚本悄悄依赖了机器上三年前就装好的某个东西,而你自己都忘了它存在。

要验证"这套东西在新机器上到底能不能装起来",传统做法都不便宜:在主力机上试会污染环境;装虚拟机快照要手动还原;租按量云主机每次开一台就是几分钟、还得记得销毁;用容器跑倒是快,但容器里的 systemd 不是 PID 1,装服务类软件(systemctl enable/start)的演练会失真——而服务类软件恰恰是最需要验证的那一类。

最近自己写了个小工具 sandbox-ubuntu,想解决的就是这个具体问题。本文从设计思路、保真基线、与同类方案的对比,到最近补上的一个亮点——GitHub 身份注入——逐一拆开说,也把几处"做不到什么"如实写出来。

目录

一、它是什么

一句话:跑在 WSL2 上的一次性「全新 Ubuntu 云机」模拟器(仅 Windows)。双击 start-sandbox.cmd,选一个 Ubuntu 版本和一个「新机档案」,进到一个 root 直进、systemd 真正运行的 shell,用完输 exit,机器被校验式销毁、主机零残留。MIT 协议开源。

进到 shell 那一瞬间的真实样子(已脱敏):

实机截屏:初始化与沙箱就绪

前置只要两条:Windows 10(19041+)/ Windows 11,且已装好 WSL2(wsl --install,家庭版可用)。下载项目双击 start-sandbox.cmd,菜单里选 Ubuntu 版本和新机档案,没构建过就联网构建母版(几分钟,之后有缓存),进到 root shell 就能用。唯一正确的退出是在沙箱里输 exit——直接点窗口 X 会留下约 2GB 的 vhdx 残留(下次启动自动清除,或 cleanup.cmd 手动兜底)。

二、保真基线:按"全新 VPS 出厂状态"定义

这是它和"装个干净 Ubuntu"最大的区别——烤进母版的东西,是照着全新云主机出厂状态定义的:

  • 有:sshd、cloud-init、ca-certificates——新 VPS 自带的,必须有;cloud-init clean 已执行,所以每次启动都跑一遍新机首启流程;systemd 运行中,systemctl 可用;默认 root 直进;主机名固定 ubuntu。
  • 没有:git、pip、gcc、node、docker 一律不烤。新机上没有的就没有,apt install git 本身就是模拟的一部分——它要验证的正是你的部署流程在新机上走得通,每次启动自检也确实会确认 git 缺席。
  • apt 包列表已清空:第一次 apt update 需要你自己跑,跟真机一致。
  • 隔离:/etc/wsl.conf 关掉 automount(看不到宿主硬盘)、interop(调不到 Windows exe)和 appendWindowsPath。

系统母版保真基线示意

三、新机档案:模拟的是哪家的云

同样装 Ubuntu 24.04,腾讯云新机和阿里云新机的 apt 软件源是不一样的,GCP/AWS/Azure 的新机则用 Ubuntu 官方源。这个差异会直接影响 apt 行为,所以做成了可选项(profile):

  • stock:保持官方源 archive.ubuntu.com,对应 GCP/AWS/Azure,海外用户默认;
  • tencent:对齐 mirrors.cloud.tencent.com,对应腾讯云新机(项目默认);
  • aliyun:对齐 mirrors.aliyun.com,对应阿里云新机。

机制上:母版每版本只构建一个,始终保持出厂官方源;源对齐发生在沙箱每次启动时,只作用于本次实例,随销毁一起消失。所以新增一家云只是在 versions.json 里加几行配置,母版和磁盘成本不随云的数量翻倍。

一个能看出态度的细节:对齐用的是公网等价源,而不是照抄云厂商内网域名。后者在你的机器上根本不可达,照抄只会模拟出真实云用户遇不到的假障碍。

四、支持矩阵与下载

刻意等于"云厂商在售的 LTS",这是保真度的一部分,不是限制:

版本官方 rootfs 来源apt 源格式
24.04 LTS(Noble)releases.ubuntu.com(.wsl)deb822
22.04 LTS(Jammy)cloud-images.ubuntu.com(rootfs.tar.gz)传统 one-line
26.04 LTS(Resolute)releases.ubuntu.com(.wsl)deb822

所有 rootfs 的 SHA256 固定在 versions.json,下载后强校验,构建出的母版每次启动还会再校验一次。下载走多源:官方优先,国内镜像(TUNA/USTC/NJU)回退,带低速熔断——20 秒内低于 100KB/s 就换源,每源还有一次断点续传补救。实测国内网络下官方源约 150KB/s(ETA 40 分钟+)时自动切 NJU 镜像可达约 4MB/s。

五、和 docker / Multipass / 真云比

方案Windows 家庭版新机首启(systemd/cloud-init)每次全新+销毁保证云源对齐后续启动
sandbox-ubuntu可用是校验式是30–60s
docker run --rm可用否构造级否~10s
Multipass需 Hyper-V/Pro是(NoCloud)需记得 –purge否~1min
VM 快照VBox 可是需记得还原否~2min
真云按量—是需记得销毁是5–10min

和 docker run --rm 的本质区别:systemd 与 cloud-init 的「新机首启」语义 + 校验式销毁 + 云新机源对齐。容器里 systemd 不是 PID 1,服务安装演练会失真。

六、还能喂给 AI agent 无人值守跑

设计上即可无人值守调用:无交互、机器可读结果、确定性退出码。推荐形态:

start-sandbox.cmd -SkipShell -Version 22.04 -Profile stock -NoIdentity -Force

-SkipShell 不开交互 shell,跑完构建→验证→清理退出;-NoIdentity 强制纯净模式(跑不完全信任代码的推荐姿势);-Force 验证失败直接清理。结果判定:退出码 0 = 验证通过且确认零残留清理,1 = 任一环节失败;logs\result-latest.txt 首部 status=OK|FAIL 即凭证,检查项用英文稳定键(systemd / apt-sources / isolation-interop …),不随界面语言漂移。

七、GitHub 身份注入:连你的私有仓库也能验

这是最近补上、我个人最看重的亮点。默认进来是「纯净模式」——沙箱里没有任何凭据,适合验证开源的安装脚本和部署文档。但真实的部署往往还涉及你自己的私有仓库:私有配置、内部工具、还没公开的部署脚本——这些在全新机器上能不能 clone 加构建,恰恰是最该验证、却又最难用普通沙箱验证的部分。

做法克制而清晰:把项目里的 token.example.txt 复制为 token.txt,填入一个 fine-grained PAT(建议只勾选需要的仓库、Contents 只读、7~30 天有效期)。文件存在即启用身份模式,删掉就回到纯净,也可以用 -NoIdentity 强制纯净。

身份模式下会多跑三段验证:GitHub 网络可达、身份有效、git 握手成功。其中 git 握手这段有个巧妙之处——沙箱里没有 git(基线要求),所以 setup 不走 git 二进制,而是用 Python 直接发 *.git/info/refs?service=git-upload-pack 加 Basic 认证,返回 200 加 advertisement 就等价于 git ls-remote 成功。它验证的是"凭据 + 网络 + 握手"整条链路,而不需要先装 git。

而凭据的传递是整套设计里我最欣赏的部分:token 经由 WSLENV 内存桥进入沙箱,不落盘传输;在实例内只落在 /root/.git-credentials(600 权限),随 vhdx 一起销毁;任何日志都不打印 token。默认无凭据、存在才启用,等于把"最小暴露面"设成了默认值。

一个诚实的边界必须说清楚:WSL2 不是安全边界。身份模式下,任何在 guest 内以 root 运行的代码都能读走这个 token 并外传。所以作者建议很明确——跑不完全信任的代码,保持纯净模式(-NoIdentity)。这也是"默认无凭据"这一默认值背后的取舍逻辑。

把"验开源"和"验私有"两种需求都覆盖,又不让凭据长期留痕,这件事它想得很周到。

GitHub 身份注入示意

八、几点实话(已知保真边界)

  • 仅 Windows(依赖 WSL2);macOS/Linux 宿主不支持;
  • WSL 定制内核 ≠ 云厂商内核(linux-aws / linux-gcp 等),内核参数/驱动/DKMS 类演练无法复现;
  • 云厂商私有 agent(阿里云助手 / SSM Agent / 云监控)不模拟——它们不改变新机 apt/基线行为,属刻意边界;
  • cloud-init 的 datasource 是 WSL 而非云厂商;metadata service 不存在;
  • 网络出口走你本机链路,不是云机房线路;
  • 安全边界:WSL2 不是安全边界,纯净模式给的是"干净环境"而非对抗性沙箱;身份模式下 guest 内 root 能读走 token,跑不完全信任代码请用 -NoIdentity。销毁是校验式的,失败会红字报警而不是谎报成功。

九、开源

sandbox-ubuntu 由 geekkkk404 开发,以 MIT 协议开源,公开仓库在 GitHub,国内镜像在 Gitee——Gitee 通过 Actions 自动同步代码,发行版也同步发布;提交 Issue 请统一到 GitHub。威胁模型细节见 docs/threat-model.md。

它源于"每次测安装脚本都要重装系统或租真机"的真实痛点。如果你也需要反复验证"这套东西在新机器上能不能装起来",而不是想在自己电脑上反复糟蹋环境,它提供的是一条折中路线:比真云快,比容器真,用完就消失。GitHub 身份注入让"验私有仓库"也不再需要租真机或污染主机。已知边界我一律写进了文档,不做无法兑现的承诺。