深入 Lume:用 Apple Virtualization Framework 离线无人值守创建 macOS 虚拟机
【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua
Lume 是 cua 仓库中基于 Apple Virtualization Framework 的 macOS/Linux 虚拟机 CLI 与框架,本文以 libs/lume/README.md 为主体,逐层展开它的核心能力:用lume create --unattended从 IPSW 恢复镜像离线完成 macOS 客户机初始化(建用户、开 SSH、自动登录、禁用睡眠与锁屏)的完整流程、参数语义,以及内置预设 YAML 与遥测隐私边界,帮助你在没有 GUI 操作的情况下批量产出可直接 SSH 访问的干净 macOS 虚拟机。
Lume 是什么
Lume 的定位一句话概括:一个面向 macOS 和 Linux 虚拟机的 CLI 和框架,底层使用 Apple Virtualization Framework 管理磁盘、网络和 VM 生命周期。从 Swift 包声明 libs/lume/Package.swift 可以看到它的技术栈:
- 最低平台要求为
macOS(.v14),即宿主必须是 macOS; - 依赖
swift-argument-parser构建 CLI 子命令、Yams解析无人值守预设 YAML、swift-nio/swift-nio-ssh实现内置 SSH 客户端、MCPswift-sdk提供 MCP 服务端能力; - 可执行目标
lume将Resources/unattended-presets目录整体打包进二进制资源 Bundle,这是后面“预设名”机制能离线工作的原因。
主源码位于 libs/lume/src/,与本文主题直接相关的目录包括Commands/(CLI 子命令)、Unattended/(离线无人值守安装)、VM/(虚拟机模型)、Telemetry/(遥测客户端)。
创建一台 Vanilla macOS 虚拟机
README 给出的最小完整流程是两步:
lume create macos-tahoe --ipsw ~/Downloads/macos-tahoe.ipsw --unattended tahoe lume run macos-tahoelume create以 IPSW(Apple 官方恢复镜像)为源安装 macOS,--unattended tahoe指定离线无人值守预设;lume run启动 VM。
内置的sequoia和tahoe两个预设会不依赖 GUI 自动化地配置安装完成的客户机:创建lume用户、启用 SSH、配置自动登录、禁用睡眠与锁屏。默认 SSH 凭据为lume/lume。
README 明确了两点适用性事实:Tahoe 预设已经过本地 IPSW 的端到端验证;Sequoia 在首次带显示器启动时仍可能出现 Setup Assistant 的 Accessibility 步骤,这是仓库已跟踪的已知问题。要使用另一个预设,把--unattended参数从tahoe换成sequoia,并使用匹配的 VM 名即可。
lume create参数说明
从子命令实现 libs/lume/src/Commands/Create.swift 可以补全各选项的默认值与取值范围:
| 选项 | 默认值 | 说明 |
|---|---|---|
位置参数name | 必填 | VM 名称 |
--os | macOS | 安装的系统,可选macOS/linux |
--cpu | 4 | CPU 核数 |
--memory | 8GB | 内存大小,接受8、8GB、8192MB形式,无单位按 GB 处理 |
--disk | macOS100GB/ Linux50GB | 磁盘大小,同样支持大小单位;低于最小推荐值(macOS 30GB / Linux 10GB)会直接校验失败 |
--display | 1024x768 | 显示分辨率,格式WIDTHxHEIGHT |
--ipsw | 无 | macOS 恢复镜像路径,macOS VM 必填;也可传latest下载最新受支持版本 |
--storage | 无 | VM 存储位置或 VM 存放目录的直接路径 |
--network | nat | 网络模式:nat、bridged(自动选接口)或bridged:<interface>(如bridged:en0) |
--unattended | 无 | 离线无人值守预设名或 YAML 路径,仅支持 macOS VM |
--vnc-port | 0(自动分配) | 验证阶段临时 VNC 服务端口 |
--no-display | 见下 | 无显示运行 |
--debug/--debug-dir | 关 | 兼容保留标志,离线流程会忽略 |
两个源码层面的细节值得注意:
--unattended与--os组合不合法时会被校验拒绝:对非 macOS 系统传入该参数会抛出--unattended is only supported for macOS VMs(Create.swift);- 只要指定了
--unattended,noDisplay会被强制置为true,即无人值守流程天然是无头(headless)验证的(Create.swift)。
离线无人值守安装是怎么工作的
预设之所以“不需要 GUI 自动化”,是因为整套安装由 libs/lume/src/Unattended/UnattendedInstaller.swift 中的UnattendedInstaller分阶段编排:
阶段一:物化首启状态(materializeFirstBootState)。无显示启动 VM,通过解析宿主 DHCP 租约表轮询 VM 的 IP(最长 120 秒),让 macOS 完成必要的“首次启动”落盘,然后停止 VM。这一步存在的原因是:纯离线状态下部分首启标记尚未生成,需要先跑一次让系统自己写全。
阶段二:离线磁盘补丁(MacOSOfflineSetupPatcher)。libs/lume/src/Unattended/MacOSOfflineSetupPatcher.swift 是整个流程的核心。它用DiskImageSession以读写方式附加 VM 磁盘,定位 APFS 容器中的 Data 卷并挂载,然后在“离线磁盘”上直接编辑客户机文件系统:
- 建用户:不通过系统命令,而是直接读写 dslocal 数据库(
private/var/db/dslocal/nodes/Default/users/lume.plist)。lume用户固定uid 501/gid 20,并追加进admin与staff组。密码以ShadowHashData形式写入,散列由源码内手工实现的 PBKDF2-SHA512(50000 次迭代、32 字节随机盐)生成,认证方式标记为SALTED-SHA512-PBKDF2; - 跳过 Setup Assistant:写入
/var/db/.AppleSetupDone标记,并向用户与系统两级com.apple.SetupAssistant.plist写入DidSeeCloudSetup、DidSeePrivacy、DidSeeSiriSetup等布尔位; - 自动登录:改写
com.apple.loginwindow.plist设置autoLoginUser = lume,同时移除FirstLogins条目——源码注释指出,若残留FirstLogins,即使存在.AppleSetupDone,下次图形登录仍会重新拉起 Setup Assistant;登录密码另以经典 12 字节 XOR 密钥编码写入/private/etc/kcpassword; - 启用 SSH:在 launchd 的
disabled.plist中把com.openssh.sshd置为false(即启用),并写入disabled.migrated标记文件; - 禁用睡眠与锁屏:向系统级
com.apple.PowerManagement.plist写入显示/系统/磁盘睡眠定时器全为 0,并向 ByHost 每主机 plist 写入TTYSPreventSleep、SleepServices等键,保证 VM 长时间运行不被锁屏打断; - 用户主目录(
Library/Preferences、Desktop等)与屏幕保护“不要求密码”等偏好也在此阶段一并落盘。
补丁器源码头部有一条重要实现注记:部分 macOS 系统 plist 采用就地编辑(打开已存在文件、截断、重写)而非原子替换,因为 launchd/loginwindow 在下次启动时可能忽略被原子替换过的文件(MacOSOfflineSetupPatcher.swift)。这类“反直觉”细节正是离线补丁方案的实际经验所在。
阶段三:启动验证(verifySetup)。补丁完成后再次无显示启动 VM(遇到 auxiliary storage 锁冲突会自动重试,最多 3 次),等待 DHCP IP(最长 300 秒)后执行配置中的健康检查;预设默认是 SSH 检查:lume用户、lume密码、单次超时 5 秒、最多重试 60 次、间隔 5 秒。
阶段四:客户机收尾。健康检查通过后,Lume 通过内置 SSH 客户端把guestFinalizationScript以 base64 编码经sudo在客户机内执行:再次touch /var/db/.AppleSetupDone(并修正属主为 root:wheel)、defaults write固化 loginwindow 与 SetupAssistant 偏好、launchctl enable system/com.openssh.sshd、执行diskutil apfs updatePreboot将离线创建的账户发布到已配对的 Recovery 环境,最后以MARKER_OWNER=0:0输出作为成功断言。若配置了post_ssh_commands,还会在同一 SSH 会话能力下顺序执行,然后停止 VM,安装结束。
这一链路也解释了为什么 Tahoe 可以做到全离线无人值守:真正需要“机器自己启动一次”的只有首启状态物化与 SSH 验证,GUI 层没有自动化脚本参与。
无人值守预设:YAML 配置参考
两个内置预设 tahoe.yml 与 sequoia.yml 内容完全一致:
# Offline macOS unattended setup preset. # # Lume patches the installed disk offline, creates the `lume` user, enables # autologin and SSH, disables sleep/screen locking, boots once to verify SSH, # then stops. boot_wait: 0 boot_commands: [] health_check: type: ssh user: lume password: lume timeout: 5 retries: 60 retry_delay: 5结合解析器 libs/lume/src/Unattended/UnattendedConfig.swift,各字段语义如下:
| 字段 | 默认值 | 说明 |
|---|---|---|
boot_wait | 60 | VM 启动后等待多少秒再开始自动化;离线流程置0 |
boot_commands | [] | 兼容保留的启动命令列表,离线流程忽略 |
health_check.type | — | 健康检查类型(如ssh) |
health_check.user/password | — | SSH 检查使用的凭据 |
health_check.timeout | 30 | 单次检查超时(秒) |
health_check.retries | 3 | 失败重试次数(预设覆盖为 60) |
health_check.retry_delay | 5 | 重试间隔(秒) |
post_ssh_commands | 无 | 健康检查通过后经 SSH 执行的命令列表,源码注释说明其比经 VNC 在 Terminal 里打字更可靠 |
加载规则值得记住:UnattendedConfig.load(from:)先按预设名匹配(查二进制内unattended-presets资源目录),匹配不到才把参数当作 YAML 文件路径处理(支持~展开)。因此--unattended tahoe与--unattended ./my-preset.yaml走的是同一入口。当预设缺失时,错误信息会列出availablePresets()扫描到的全部可选预设名。如果健康检查完全未配置,UnattendedInstaller会回退到与预设相同的默认 SSH 检查参数(lume/lume、5 秒、60 次、间隔 5 秒,见 UnattendedInstaller.swift)。
需要提醒的是:预设中lume/lume是明文默认凭据,适合本地实验环境;用于生产或对外服务前请自行更换。
可选依赖:lume sip与 vncdotool
README 指出,lume sip子命令通过 VNC 控制 macOS Recovery 来启用/禁用 SIP,它依赖vncdotool。只有需要操作 SIP 时才安装:
pip3 install vncdotool其他 Lume 命令均不需要这个包。对应实现入口见 libs/lume/src/Commands/Sip.swift。
遥测与隐私边界
Lume 遥测默认开启,记录去标识化的安装、发布、命令与 API 事件元数据;不收集提示词、VM/镜像名、文件路径、命令参数或 VM 内容。控制命令为:
lume config telemetry status lume config telemetry disable lume config telemetry disable lume config telemetry reset-id行为细节(与 docs/content/docs/reference/lume/telemetry.mdx 一致):
LUME_TELEMETRY_ENABLED仅对当前进程覆盖已持久化的偏好;- 常规卸载会保留遥测偏好与去标识化安装 ID,重装可识别为“回访”;
uninstall.sh --purge才会删除 ID、标记、配置、缓存与 VM; - schema-v3 事件固定携带
telemetry_schema_version(恒为 3)、product_version、os_family、os_major、arch、is_ci、is_synthetic、transport(cli/http/mcp_stdio)、process_session_id(每进程随机、不持久化)、id_persisted等字段; - 事件类型是白名单固定的(如
lume_install、lume_vm_started、lume_provisioning_started/completed、lume_mcp_tool_completed),且明确排除 VM/镜像名、路径、URL、命令参数、MCP 参数与结果、SSH 命令与输出、未值守配置、VNC 凭据、VM 内容与截图; - 每个进程每小时常规遥测上限 1000 条事件;
- 更新检查是独立于遥测的只读请求,可用
LUME_UPDATE_CHECK=false单独关闭。
适用前提与限制
- 宿主机必须是 macOS(
Package.swift声明最低macOS 14),Linux 仅作为可安装的客户机系统; --unattended仅对 macOS VM 有效,Linux VM 传入该参数会被直接拒绝;- 磁盘低于 30GB(macOS)/ 10GB(Linux)会在创建前校验失败;
- Sequoia 预设首启可能停留在 Accessibility 步骤,属已跟踪问题;Tahoe 预设经本地 IPSW 端到端验证。
综合来看,Lume 的无人值守方案把“创建一台可用 macOS VM”拆解为“物化首启状态 → 离线补丁客户机磁盘 → 无头 SSH 验证 → 客户机内收尾”四个可独立失败、可重试的阶段,所有 GUI 层配置都转化为对 dslocal、loginwindow、launchd 与 PowerManagement 等具体文件的确定性写入。这套机制既适合本地快速搭机,也是 cua 在规模化构建跨 OS 计算环境(fleets)时自动化产出 macOS 节点的基础设施。
【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考