跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

参考

Barn 读取的 Pigsty Inventory 与命令行的准确契约。

本参考描述 Barn 0.9.0 发布候选。编写脚本前先核对 barn version, 发布进度见当前状态。

  • 配置:发现顺序、变量、默认值、磁盘、共享、命名与漂移。
  • 命令行:命令、关键参数、输出模式与退出码。
  • Mac 命令:尚未发布的 barn mac 的命令、JSON 结果与失败原因。
  • 镜像:签名 Catalog、别名、本地缓存、拉取、导入与清理。
  • 镜像流水线:Candidate 校验与离线归一化。

Barn 不提供受支持的 Go Library API;internal/ 下的包都是实现细节。

1 - 配置

Barn 读取的 Pigsty Inventory 字段、默认值与节点级漂移行为。

本参考描述 Barn 0.9.0 发布候选。编写脚本前先核对 barn version, 发布进度见当前状态。

发现顺序

依次查找:显式 -f、当前目录的 barn.yml、barn.yaml、pigsty.yml、 pigsty.yaml。所有文件名都使用同一种 Pigsty 兼容 YAML Inventory。

plan、up、reload、recreate 找不到文件时,如果 deployment 已存在,会回退到 已应用规格;validate 不会回退。配置必须是最大 4 MiB 的普通非符号链接文件。 发现顺序中第一个存在的文件生效;它若无效会直接报错,不会继续尝试下一个文件名。 重命名文件或切换目录不会产生另一套部署,已应用状态保存在 BARN_HOME。

完整配置示例

all:
  vars:
    admin_ip: 10.10.10.10
    vm_image: u24
    vm_cpu: 2
    vm_mem: 4GiB
    vm_disk: 64
  children:
    lab:
      hosts:
        10.10.10.10: { nodename: meta }
        10.10.10.11:
          nodename: worker
          vm_mem: 8GiB
          vm_disks:
            - { path: /data, size: 128, fs: auto, persistent: true }

这里定义了两个托管节点,控制节点为 meta。保存为 barn.yml 后,可以先检查而不启动 VM:

barn validate -f barn.yml
barn --json validate -f barn.yml
barn plan -f barn.yml

JSON 校验结果包含 valid、source、spec_hash、resolved。0.9 候选版本的 validate 还会解析 Catalog 镜像引用,并接受 --repo;Catalog 无法读取时会报告警告, 不会声称镜像已检查;local-* 镜像字节校验仍由 up 完成。配置校验不能证明宿主资源、 共享访问、网络、镜像字节或客机就绪可用,也不会启动 VM 或下载镜像。

Barn 读取什么

Barn 读取主机 IP、nodename、admin_ip、pg_cluster、pg_seq、 node_admin_username、node_admin_uid 与已记录的 vm_* 变量。admin_ip 只从 all.vars 读取,用于选择控制节点;没有匹配时使用第一台托管主机。所有节点必须解析为 同一个登录用户名;默认用户 dba 的显式 node_admin_uid 必须为 88。 自定义用户名下,node_admin_uid 仍需通过整数校验,但不会设置客机 UID;Barn 没有提供任意定制客机 UID 的配置契约。

其余内容完全不读,也不会产生 drift。这里指 pg_role、pg_version、repo_*、 node_packages 等未消费字段,不能泛化为所有 pg_* 或 node_*。

命名空间内严格校验:未知 vm_*、错类型、Jinja 表达式、非法地址、同级分组冲突都会报错。 继承顺序是 all.vars → 更深层的 children.<group>.vars → 主机变量。 主机上的 vm_disks 等列表整体替换继承列表,不会追加。相同深度的组给出不同值时, 必须在主机层覆盖消除冲突。支持 YAML 锚点与合并键:显式键优先,合并序列中靠前的映射优先。 重复映射键和多个 YAML 文档都会报错。

即使 vm_skip: true,主机键也必须是 IPv4 地址。跳过的主机不计入 20 节点上限、也不参与 托管子网推导,但至少要有一台托管主机。跳过已应用节点只会将它标为从配置移除,不会销毁 VM。

0.9 候选版本改进了错误诊断,在可定位时显示规则、错误值、行号,并提示相近的 vm_* 拼写;这些诊断改进没有增加新的 Inventory 变量。

VM 变量

变量 默认值 含义
vm_skip false 不虚拟化这台真实/外部主机
vm_image u24 镜像 Family、Channel 引用或 image@version Selector
vm_version 未设置 匹配 9、9.7 等数值前缀的最新版本
vm_arch native 部署级 Guest 架构:native、amd64 或 arm64
vm_cpu 2 vCPU 数量
vm_mem 4096 MiB 整数,或 8GiB 等尺寸
vm_disk 64 根盘:GiB 整数或 64GiB 等显式尺寸
vm_disks [{path: /data}] 额外数据盘,默认一块挂载到 /data 的 128 GiB 非持久盘
vm_alias [] Guest /etc/hosts、SSH config 与可选宿主别名
vm_shares [] QEMU 9p 宿主目录共享

空主机条目就是一台完整 VM。每套 deployment 支持 1–20 台托管主机;vm_cpu 范围 1–256,内存至少 512 MiB。内存裸整数单位为 MiB,磁盘裸整数单位为 GiB。 显式尺寸字符串支持正整数加 B、KiB、MiB、GiB、TiB、KB、MB、GB、TB (区分大小写)。8GiB 合法,8G、1.5GiB 和无单位的引号字符串 "8192" 不合法。 根盘与数据盘尺寸必须为正值;up 还会检查根盘不小于所选基础镜像的虚拟尺寸。

省略 vm_image 时默认选择 Ubuntu 24.04。使用 Debian 13 时,在 all.vars 中 写明 vm_image: d13;修改已有 Barn 配置后先查看 barn plan。

vm_version 将简短的版本意图与镜像 Family 分开:

vm_image: el9
vm_version: 9.7

Catalog 中存在完全相同的版本时优先精确匹配;否则只在点分量边界匹配,并选择数值语义上 最新的结果:9.7 选择最新 9.7.* Build,9 选择最新 9.x Release。各分量按整数 比较,因此 9.10 晚于 9.9。vm_version 不能与已经带 :channel 或 @version 的 vm_image 同时使用。

vm_arch 比普通逐主机字段更严格:出现时必须在所有托管主机上解析为同一个值,因此 应只在 all.vars 定义一次。修改它属于 deployment envelope 变化,必须整体重建。 Linux setup 只安装宿主原生模拟器;外来架构还需要对应 qemu-system-* 与固件。

数据盘

vm_disks:
  - path: /data
    size: 128
    fs: auto
    persistent: false

path 同时是磁盘身份与挂载点;fs 为 auto(默认)、xfs 或 ext4。空白的 auto 磁盘在 guest 有 mkfs.xfs 时格式化为 XFS,否则为 ext4,与 Vagrant 流程的 行为一致;显式 xfs、ext4 不会降级,健康的已有文件系统直接复用。persistent: true 在普通 destroy 后保留;vm_disks: [] 表示不要额外盘。每项 size 默认 128 GiB, 整数单位为 GiB,也接受显式尺寸字符串。

挂载点需是 /data、/data/pg 等规范绝对路径。磁盘身份由路径去除首尾 /,再把中间的 / 替换为 -,必须匹配 [a-z][a-z0-9-]{0,31};单个节点内磁盘身份与挂载点均不得重复。 /、/etc、/usr、/root、/var/lib/barn 等系统路径及与它们重叠的父子路径会被拒绝。 修改持久盘身份或声明可能需要显式迁移;persistent 不表示任意新定义都能自动复用旧盘。

数据盘按可丢弃的测试存储处理。 up 会将无法识别或确认损坏的文件系统清空重建为 配置的类型,并报告旧数据已丢弃。这同样适用于 persistent 盘:持久性控制销毁、重建 VM 时是否保留盘,不保证保留损坏内容。探测失败、设备暂缺、挂载占用或底层 I/O 故障不会 触发格式化;系统盘和宿主共享目录不属于此恢复范围。

目录共享

macOS 限制: Barn 的目录身份保护共享方式尚不支持 macOS,配置了 vm_shares 的节点无法启动;候选版本还会在 validate、plan 时发出警告。新建 macOS 实验环境 应先省略共享;完整共享支持仍待完成。修改已有节点的共享配置需要 recreate,会替换 根盘,请先保留所需数据。Barn 不会退回未经身份校验的宿主路径。

vm_shares:
  - host: /absolute/owned/source
    guest: /src
    readonly: true

readonly 默认为 true,每个节点最多八个共享。宿主与客机路径必须是规范绝对路径, 不会展开 ~ 或相对路径。源目录必须已经存在、属于调用者,路径的任何分量都不能是 符号链接,也不能与 BARN_HOME 重叠。Linux 上请优先使用真实路径(realpath /path/to/source);0.9 候选版本 会在符号链接错误中提示应该填写的真实路径。

同一节点内宿主源目录、客机目标目录均不得相互重叠;不同节点只有全部只读时才允许宿主 源目录重叠。客机目标不能覆盖数据盘挂载点、保留系统路径或登录用户的 .ssh 目录。 9p 只适合可信开发文件,不能放 PostgreSQL 数据。 请求可写共享但客机无法写入时,Barn 尝试只读访问并报告限制;修正权限后再次 up 即可重试。Barn 不会递归修改宿主文件的属主。

Barn 的 up、start 会将源目录缺失的影响限制在对应节点,其余选中节点 继续执行。恢复原目录或宿主挂载后,再重试该节点;Barn 不会创建空目录代替。 restart、reload、recreate 会在停止已有节点前校验源目录。

名称与地址

节点名依次取 nodename、<pg_cluster>-<pg_seq>、node-<IP末段>,且必须唯一。 名称长度为 1–63,只能包含小写字母、数字和连字符,不能以 - 开头或结尾。 非空显式 nodename 优先,此时无需使用其他 pg_cluster、pg_seq 值派生名称。 vm_alias 是小写 DNS 风格名称列表,不能与节点名或部署内任何其他别名重复。

所有托管主机必须位于同一个 RFC1918 /24:.1 属于宿主,.2–.8 保留,节点使用 .9–.254。

Guest 内部,固定 IP 网卡就是承载 Inventory 地址的那块网卡(ip -br addr);其名称不是 Barn 契约。

漂移

Barn 对每个解析后节点计算哈希。新增主机由 up 创建;选中的已停止节点会启动, 运行中同伴保留进程,同时重试未完成的客机初始化。VM 定义变化需要节点级 recreate;删除主机条目只报告、绝不销毁。 deployment 架构、用户或子网变化需要整体重建。plan/up 会把镜像选择器解析为精确镜像身份, 因此 Catalog 更新后即使 Inventory 文本未改动,也应检查计划。修改用于派生节点名的字段会表现为旧节点 missing 加新节点,建议使用稳定、显式的 nodename。

2 - 命令行

Barn 命令、关键参数、结构化输出与退出码。

本参考描述 Barn 0.9.0 发布候选。编写脚本前先核对 barn version, 发布进度见当前状态。

barn [--json|--yaml] [-v|--verbose] <command> [flags] [node...]

已安装的二进制是当前版本最准确的参考。每一条可见命令都自带操作边界与可复制样例:

barn --help
barn setup --help
barn image pull --help

直接运行 barn 会显示简短欢迎信息和下一步命令,以 0 退出, JSON/YAML 输出 actions[]。barn image 这样的裸命名空间仍以 2 退出,文本模式打印帮助,JSON/YAML 模式返回结构化用法错误。显式 --help 始终输出 供人阅读的帮助文本并以 0 退出。用 barn --version 或 barn version 查看构建身份。

命令

范围 命令
准备 setup、init、validate、doctor
生命周期 plan、up、start、stop、restart、reload、recreate、status、destroy、purge
访问 ssh、exec、logs、provision、ssh-config、hosts install/uninstall
镜像 update、image list/info/pull/import/sync/prune/reset、repo scan/build/verify
宿主网络 network status/install/uninstall
macOS 客机(尚未发布) mac …,见 Mac 命令
其他 version、completion

没有命令会隐式刷新 Catalog。update 获取配置仓库的 Catalog,校验并激活; image sync 是为精确 URL 或文件准备的显式恢复路径。普通命令只使用当前本地 Catalog。 两者都不更新 Barn 可执行文件。

常用命令提供作用域明确的短别名:

命令 别名 命令 别名
setup s validate v
plan pl recreate rc
status st destroy de
ssh-config sc image images、im
doctor dt network n、net
exec / logs ex / l version ver

up、ssh、init、start、stop、restart、reload、provision、hosts、 completion 没有别名。请使用明确的 barn purge 拼写;rm 不是命令别名。 命名空间内部,hosts 与 network 的 install/uninstall 使用 i/u,network status 使用 st;image 使用 list=ls、info=in、pull=p、 prune=pr、sync=sy、import=i。

Barn 在选定的 BARN_HOME(默认 ~/.barn)中管理一套部署,其身份与 Inventory 所在目录无关。使用已应用状态的命令可在任意目录运行。配置来源由命令决定,-f 刻意不做全局参数:

命令 期望状态来源
setup [template] 显式 -f,否则发现配置,否则生成 meta;模板与 -f 互斥
init [template] 生成新 Inventory,不读取期望状态;--force 显式替换输出文件
validate 显式 -f,再发现配置;绝不回退到已应用状态
plan、up、reload、recreate 显式 -f,再发现配置,最后回退到已应用规格
其他生命周期/访问命令 不读取期望配置;使用已应用状态

没有配置文件且没有已应用部署时,交互式 up 可以生成默认配置;它也能准备缺少的宿主 依赖、恢复完整但未激活的 Barn 网络。该内部准备流程接受 setup 计划,sudo 仍可能 请求凭据;可先用 setup --dry-run 查看宿主计划。脚本应显式执行 setup --yes, 没有配置文件时无需另行 init。

关键参数

参数 含义
--json、--yaml stdout 机器可读;进度仍写 stderr;刻意不设短参数
-v、--verbose stderr 有界诊断
-c、--cidr 为 init/setup 生成模板或宿主网络检查/安装选择 RFC1918 /24
-f、--file 为读取期望状态的命令选择 Inventory
-r、--repo 在提供此参数的命令上选择仓库;覆盖 --mirror 与 BARN_REPO;validate 在 0.9 候选版本新增此参数
--mirror 为 setup、Catalog 与需要解析镜像的生命周期命令选择中国官方仓库
-m、--mode 在提供该参数的命令中选择 macOS host/shared 网络模式
-d、--dry-run 只展示 setup/image 计划,不改变状态
-y、--yes 应用已展示的宿主/setup/image 计划
--force(init、destroy、recreate) 覆盖生成文件或跳过输入确认词;因为 -f 用于选择 Inventory,所以只保留长参数
-n、--no-wait QEMU 运行后即返回,跳过 Guest 就绪检查、恢复与元数据刷新
--rollback(up、reload) 清除本次运行中 prepare 失败节点的残留产物
--delete-persistent 整体销毁时也删持久盘;不能与节点选择器一起使用
--purge 整体处置:删除磁盘、密钥与 deployment 状态,保留镜像

参数属于各自命令,下表列出容易混淆的作用域:

命令 专用参数
init --output/-o(默认 ./barn.yml,- 表示打印)、--cidr/-c、--force
plan --file/-f、--repo/-r;没有 --mirror 或 --dry-run
start、restart --no-wait/-n;没有 --file 或仓库选择参数
provision 必须提供 --script/-s;--sudo 使用客机 sudo -n;--parallel/-p 为 1–4,默认 1;--timeout/-t 为正值、最多 24h,默认 1h
ssh-config --install/-i 与 --remove 互斥;--name 默认为 barn;移除不接受节点,也不要求部署状态存在
logs --source/-s serial|qemu|events,默认 serial;--follow/-f;events 不接受节点
image info、image pull 可选镜像选择器、--arch/-a amd64|arm64、--repo/-r;只有 pull 接受 --mirror
image import --sha256/-s;指定 --name local-* 还必须提供 --boot/-b bios|uefi 与 --source-user/-u
image prune --dry-run/-d 与 --yes/-y 互斥;--repo/-r
image sync URL 或路径、--repo/-r、显式 --allow-downgrade
network install --cidr/-c 默认 10.10.10.0/24,--mode/-m 默认 host,--yes/-y;--archive/-a、--interface-id/-i 仅限 macOS
network status 可选 --cidr/-c;没有 --file
network uninstall、hosts install/uninstall --yes/-y

setup --dry-run 与 setup --yes 互斥。--cidr 用来调整生成模板的网段,不能重写显式 选择的 Inventory。validate --repo 是 0.9 候选版本新增参数,没有对应的 --mirror; 需要检查中国仓库时使用 --repo https://repo.pigsty.cc/barn。

0.9 候选版本中,network 与 hosts 的 install/uninstall 会在终端展示计划并询问确认 (安装默认同意,卸载默认拒绝);非终端只展示计划,除非传入 --yes。 macOS 首次网络安装使用 setup;候选版本 的 network install 会在 sudo 提示前引导到该命令。--yes 接受 Barn 计划,不能提供 sudo 密码。

--mirror、--force、--rollback、--remove、--allow-downgrade、--sudo、 --delete-persistent、--purge 等低频或扩大风险边界的参数只保留长版本。读取 Inventory 的命令中 -f 始终选择文件;logs -f 保留惯用的 --follow。 -n 始终表示 --no-wait,-d 始终表示 Dry-run。

存在部署时,barn purge 与 barn destroy --force --purge 执行相同的整体处置, 且无需确认。它不接受节点或 Inventory,删除整套 Deployment、 持久盘、密钥、状态和默认 SSH Fragment,保留镜像与宿主网络。没有部署时幂等成功, 也可清除能够证明归属的保留盘;缺少状态文件绝不会授权按路径删除无法证明身份的遗留节点工件。 0.9 候选版本中,没有部署时的普通整体 destroy 也返回成功;但 destroy --force --delete-persistent 和 destroy --force --purge 会报错,提示改用 purge。

结构化失败(0.9 候选版本)

下列统一失败契约描述 Barn 0.9.0 发布候选。

普通失败会在 stderr 输出 error: <消息>;外部工具失败时附上它 stderr 的最后几行; 有明确下一步时再输出一行 next:。SSH 子进程退出失败不会重复打印错误,直接保留子进程输出。 如果命令没有提供更丰富的类型化结果,结构化模式会输出通用失败对象,包含 error、message,以及适用时的稳定 reason、next、operation_id 和外部程序详情 command(name、argv、exit_status、signal、timed_out、stderr),然后返回退出码。 已携带失败状态的结果后面不会追加第二份 JSON/YAML 文档。 通用对象的 error 使用下方表格中的固定类别;recreate_required 和 nodes_removed 改为 error: "conflict" 下的 reason,旧的 resource_conflict 类别改为 resource。

非零退出不保证 stdout 一定是这个通用对象。 doctor、network、provision、 生命周期操作与远端命令可以返回各自的报告结构。SSH 子进程退出在内部归类为 remote_exit, 但公开结果包含 success、exit_code、stdout、stderr 等字段,可选 error 也不服从 通用错误分类契约。自动化应始终保留进程退出码,再按具体命令解释 payload。

生命周期结果

plan 是只读操作,即使 action 为 recreate 或 blocked-removal 也返回成功;自动化必须 检查 action 与 create、start、recreate、missing、blocked 字段。对于 Catalog 镜像,计划只读取本地配置和 Catalog,无需先安装 QEMU 或宿主网络;已注册的 local-* 镜像还会校验缓存,需要 qemu-img。计划不会下载镜像;它显示精确镜像、资源总量、变更原因 和磁盘影响。0.9 候选版本还逐项列出数据盘,包括隐式的 128 GiB /data。 宿主能力与地址可用性由 up 在执行前检查。up 会创建缺失节点、启动已停止 节点、复查运行中节点的就绪状态,并根据完整的 applied deployment 重写 Barn 安装的 SSH 客户端配置;recreate 同样执行全量刷新,节点级 destroy 删除旧条目,整体 destroy 移除该配置。start 启动已停止节点并复查运行中节点的就绪状态,start 与 restart 也会刷新 SSH 别名。 破坏性 drift 返回冲突,并给出下一步命令:先 barn plan,再 barn recreate <node> 或 barn destroy <node>;终端上这两条命令会要求输入确认词,--force 仅用于脚本。 如果 VM 生命周期成功但 SSH 客户端配置无法写入,命令会给出警告并返回成功; barn ssh 仍然可用。结构化输出通过 warnings[] 报告集成问题。 0.9 候选版本不修改符号链接或硬链接形式的 ~/.ssh/config,会发布独立配置片段, 并提示需手动加入的 Include 行。

就绪边界是管理 SSH 可用。可选初始化问题通过 nodes[].warnings 报告,已完成的恢复 操作(包括数据盘重置)写入 nodes[].repairs。客机可用但有这些限制时返回 0;重复 up 会重试未完成步骤,无需重启运行中的 VM。要求全部配置功能可用的自动化应检查警告字段。

生命周期批处理出现可隔离的节点级失败时,即使所有选中节点都失败也可能返回 5,并报告 N of M node(s) failed: <node> (<stage>: <error>); ...。常见阶段包括 prepare、start、 readiness、bootstrap、guest-setup、stop、status;readiness 或 bootstrap 失败会追加 run \barn logs ` for the guest console。结构化输出携带 failures[](node、stage、error,**0.9 候选版本**还有可选 reason);当 –rollback清除了 从未提交节点的 prepare 产物时,还会带上rolled_back`。参见 节点未就绪。

status 默认展示节点、状态、IP、精确镜像和 CPU/内存;--verbose 展示 SSH 端口、 架构、加速器与 PID。TCG 在普通文本中也有标记。一个节点异常时,仍保留其他节点的 状态,并返回 5;结构化输出包含逐节点 error 和 failures[]。running 表示 VM 正在运行,不代表本次 status 检查了 guest 就绪状态。

启动命令完成后还会刷新运行中 guest 的 Barn hosts 和控制节点 SSH 配置;停止中的 节点在下次启动时更新。--no-wait 会跳过 guest 就绪检查、恢复和刷新,随后执行 up 补齐。 局部 recreate 若仍受未选节点的配置变化影响,会在停机、删盘前拒绝;按提示一次选择 需要重建的节点。

控制节点中由 Barn 管理的 SSH 条目不固定 guest 主机密钥,也不写入 known_hosts, 因此重建实验节点后可以直接连接。用户自行添加的 SSH 配置会保留。

恢复行为

up、start 按节点隔离宿主共享目录 缺失的影响;up 在新节点准备失败后仍会启动独立的已有停止节点。部分成功保留退出码 5 和成功节点。重试提示保留配置文件、镜像仓库及适用参数,start 的重试仍为 start。

setup 与随后生命周期重试使用同一个 operation_id。首次 setup 失败、尚无部署状态时, 也可通过 barn logs --source events --json 读取有大小上限的阶段日志。setup 日志不记录 命令参数和认证信息,详细根因以命令输出为准;setup --dry-run 不写日志。 destroy --delete-persistent 与 purge 成功摘要只描述最终删除、保留的资源;purge 仍保留镜像缓存和宿主网络。 先删除某个节点后留下的受管持久盘,不再阻断其余节点的销毁。普通 destroy 继续保留 这些盘,只有显式删除持久盘或 purge 才会移除它们。

macOS 新网络安装先完成 Homebrew 发现/安装或固定归档下载,再申请管理员认证。 这避免了 Homebrew 清除先前 sudo 凭据导致的安装失败,不扩大特权操作范围; 下载失败时不会提前要求输入密码。

中断操作恢复(0.9 候选版本)

候选版本会把已被无关进程复用的 QEMU PID 识别为节点停止。stop 中断而 VM 仍运行时, 状态会恢复为 running;其他未完成过渡会指出用于完成它的命令。destroy 会自行处理 中断过渡。首次 up 失败后可以编辑 Inventory 再重试,因为未提交产物按照日志记录回滚。

日志与环境变量

logs 默认读取客机串口;--source qemu 读取 QEMU 诊断,--source events 读取有大小 上限的部署事件日志。使用 --follow 时,文本流式输出字节,JSON 输出 NDJSON 记录, YAML 输出文档流。0.9 候选版本将普通 events/qemu 日志读取显示为可读记录, 只有 --verbose 才显示 QEMU argv。

环境变量 用途
BARN_HOME 绝对路径的私有状态目录,默认 ~/.barn;不能是符号链接或用户主目录等范围过大的目录
BARN_REPO 默认仓库;被命令提供的 --mirror、--repo 依次覆盖
BARN_OUTPUT text、json、yaml;展示参数优先
BARN_VERBOSE 布尔诊断默认值;展示参数优先
BARN_VMNET_ARCHIVE macOS setup 使用的固定 socket_vmnet 归档绝对路径,仍执行摘要检查
NO_COLOR 非空时关闭颜色

SSH 透传与命令补全

barn ssh [node] [--] [command ...] 打开会话或运行可选命令; barn exec [node] [--] <command ...> 必须给出命令并透传退出码。-- 之前的展示参数 属于 Barn。ssh 中 -- 之后的参数会像普通 SSH 一样以空格连接,再交给远端 shell 解释; exec 保留多个参数的边界,需要 shell 展开或管道时请显式使用 sh -c; 单个命令字符串仍保留 shell 简写行为。 有 -- 时,其前面只能是空或一个已知节点。为方便交互使用,也接受省略 --:已知 首参数选节点,否则把整段当成默认节点上的命令,并显示 warning。0.9 候选版本会检查 包含数字或 - 的首参数是否像节点名误拼:长度不超过四个字符时最多一个编辑距离, 更长时最多两个。符合时会拒绝执行;ls、df、wc 等普通命令仍可运行。脚本中请明确写 --。

加载 barn completion bash|zsh|fish|powershell 可获得命令与作用域准确的参数补全, 同时补全命令别名、模板、镜像别名、枚举参数,以及从期望/已应用规格只读解析出的节点名。 0.9 候选版本还会让 -f 补全只列出 YAML 文件。

退出码

此表列出 Barn 0.9.0 发布候选的退出码契约。缺少配置、未知镜像均为 usage(2); setup/network 失败按原因区分为 runtime(1)或 capability(3)。

代码 error 含义
0 成功,包括客机可用但可选功能受限
1 runtime 操作已执行但失败(外部工具、下载或客机失败)
2 usage 命令行或 Inventory 有误
3 capability 宿主缺少工具、Barn 网络或权限
4 conflict Deployment 当前状态不允许,或另一个 barn 命令正持有它
5 partial 节点级批处理失败;检查 failures[],已经成功的同伴会保留
6 resource 宿主地址、端口、网段或磁盘被占用
7 integrity 已校验的摘要、签名、身份或属主不一致
130 cancelled 被中断(SIGINT/SIGTERM)或拒绝确认

0.9 候选版本中,修改类命令遇到另一个 Barn 命令持有部署锁时,最多等待 10 分钟 并指出对方;超时以 4 退出,reason 为 deployment_busy。status、ssh、exec、 ssh-config、hosts 不等待。status 在显示已记录状态时通过 note 报告并发操作; 这不代表该部署操作已完成。

ssh 与 exec 原样透传 SSH 子进程退出码,包括 255;255 可能是 SSH 连接失败, 也可能是远端命令返回该值。文本、JSON 与进程退出码保持一致。

3 - Mac 命令

barn mac 的命令与参数、机器规则、JSON 结果、失败原因、网络与文件。
重要

Barn 0.9.0 发布候选,尚未发布。 当前验证结果与发行前检查见 当前状态。请以实际运行的 barn mac --help 为准。

barn [--json|--yaml] [-v|--verbose] mac <command> [flags] [name...]

barn mac 需要 Apple 芯片与 macOS 27 或更高版本,以已登录用户身份运行,拒绝以 root 运行。在其他宿主上该命令默认隐藏,需要 Mac 组件的命令会以 mac_host_unsupported 失败。不带子命令的 barn mac 等同于 barn mac ls。

命令

命令 用途
ls 列出所有机器的状态、地址、SSH、macOS 版本、资源与共享;别名 list、status、st
up [name] 按需创建机器,启动并等待 SSH 与 sudo 可用
start [name...] 启动已有机器
stop [name...] 正常关机,两分钟后仍未停止则断电
restart [name] 先停后启,使配置变更生效
open [name] 显示桌面,机器已停止时先启动
ssh [name] 交互式终端;-- 之后是交给客机 shell 的命令行
exec [name] -- cmd 执行命令并保留参数边界
configure name 修改机器设置
recreate name 用全新的 macOS 替换机器,保留其设置
destroy name... 删除机器
password [name] 显示或复制登录密码
ssh-config 打印、安装或移除 OpenSSH 条目
logs [name] 最近的运行日志
setup 只准备 macOS 基础镜像,不创建机器
image ls 列出恢复镜像与基础镜像及使用它们的机器;别名 list
image update 把 Apple 最新的 macOS 27 准备为默认基础镜像
image prune 列出不再使用的镜像,加 --yes 才删除
doctor 检查宿主、组件、基础镜像与每台机器

各命令的参数

命令 参数
up --cpu --memory --disk --user --share --clipboard --subnet --ipsw -y/--yes -n/--no-wait --open
start --all -n/--no-wait --open --recovery
stop --all --force
restart -n/--no-wait --open
configure --cpu --memory --share --unshare --clipboard --subnet
recreate --update --force -n/--no-wait
destroy --force
password -c/--copy
ssh-config -i/--install --remove
logs -n/--lines(默认 100,最多 10000)
setup --ipsw --disk -y/--yes
image update --ipsw -y/--yes
image prune --installers -y/--yes

不带机器名称的命令作用于唯一的一台机器或 mac1;有多台机器且没有 mac1 时会要求 指定名称。start 与 stop 可接收多个名称或 --all。destroy 与 recreate 会先说明 将删除的内容,并要求输入命令名确认;没有终端时用 --force 确认。

参数取值

参数 取值
--cpu 虚拟 CPU 数,至少 2,不超过 Mac 的逻辑 CPU 数;默认 4
--memory 16G、16GiB、16GB 或字节数;至少 4 GiB,不超过物理内存;默认 8 GiB
--disk 基础镜像容量,至少 32 GiB;默认沿用已准备的基础镜像,即 100 GiB。其他容量会安装另一个基础镜像
--user 管理员账号;默认你的 macOS 用户名,该名称不合法时为 barn
--share [name=]path[:ro|:rw],可重复,最多 8 个;名称默认取路径最后一段;~/ 展开为主目录
--clipboard on 或 off;默认 on
--subnet 规范的私有 /24,例如 10.10.30.0/24;auto 表示第一个空闲网段

up 遇到与已有机器不同的创建参数时直接拒绝而不是忽略,并在 next: 行给出修改方法。 CPU、内存、共享、网段与剪贴板用 configure 修改。账号与磁盘容量在机器的整个生命周期内 固定,recreate 也会保留它们:需要其他取值时请另建机器。更换 macOS 版本需先执行 image update,再执行 recreate --update。

机器

  • 名称:1–32 个小写字母、数字或中间连字符,以字母开头,例如 mac1、dev、build-2。
  • 运行上限:每台 Mac 同时运行两台 macOS 虚拟机,其他工具与 macOS 安装过程也计算在内。 Barn 从不为腾出名额而停止任何机器。
  • 账号:管理员账号,免密 sudo、SSH 密钥登录、桌面自动登录,并开启远程登录; SSH 密码登录被关闭。登录密码随机生成,保存在机器目录的 password 文件中。
  • 客机名称:电脑名称即机器名;本地主机名为 barn-<name>,因此客机以 barn-<name>.local 应答。
  • 共享:一个由 macOS 挂载到 /Volumes/My Shared Files/<name> 的 VirtioFS 设备。 共享必须是已存在的目录,不能是符号链接,只能在机器停止时修改。
  • 剪贴板:纯文本,在窗口获得或失去焦点时经这台机器的 SSH 连接同步;最大 1 MiB; 标记为敏感的内容不会发送。
  • 停止:通过客机中的 macOS 正常关机;两分钟后仍在运行则断电,结果中带 "forced": true。--force 立即断电。

网络

每台机器的网络由它自己的 runner 进程在启动时创建,停止时随之消失,不涉及任何守护进程或 root 权限。

项目 取值
网段 在 10.10.20.0/24 到 10.10.59.0/24 之间选择第一个空闲的私有 /24,避开宿主路由和其他机器;也可用 --subnet 指定
网关 .1,即 Mac
客机地址 .10,通过对机器 MAC 地址的 DHCP 保留分配
可达性 经 NAT 访问 Mac 与互联网;不能访问其他机器与局域网

宿主路由(例如 VPN)与机器网段重叠时,start 会以 mac_subnet_in_use 拒绝启动。 SSH 主机密钥绑定到机器实例而不是地址,因此 configure --subnet 后信任关系不变。

macOS 的“本地网络”隐私控制会阻止未获授权的第三方程序连接这些网络,报错为 “No route to host”;需要在隐私与安全性 → 本地网络中允许对应应用。Barn 自身通过 Apple 的 /usr/bin/nc 与 /usr/bin/ssh 连接,不受该限制。

JSON 输出

所有命令都支持 --json 与 --yaml,进度信息输出到标准错误。

ls

{
  "schema_version": 2,
  "root": "/Users/alice/.barn/mac",
  "prepared": true,
  "base": {"version": "27.0", "build": "26A428", "base_id": "26A428-e16af589f4b705ca397f5b21"},
  "machines": [
    {
      "name": "mac1",
      "kind": "macos",
      "state": "running",
      "ready": true,
      "ssh": "ready",
      "address": "10.10.20.10",
      "address_stable": true,
      "ssh_host": "10.10.20.10",
      "ssh_port": 22,
      "user": "alice",
      "image": {"version": "27.0", "build": "26A428", "base_id": "26A428-e16af589f4b705ca397f5b21"},
      "cpus": 4,
      "memory_bytes": 8589934592,
      "disk": {"capacity_bytes": 107374182400, "allocated_bytes": 1202647040},
      "network": {"subnet": "10.10.20.0/24", "gateway": "10.10.20.1", "address": "10.10.20.10"},
      "shares": [{"name": "src", "host": "/Users/alice/src", "guest": "/Volumes/My Shared Files/src", "readonly": false}],
      "clipboard": true,
      "pid": 2545,
      "instance_id": "b1482ffc-2da7-45d9-ace5-c5f3193a9172",
      "warnings": []
    }
  ],
  "running": 1,
  "limit": 2
}
字段 取值
state prepared(尚未完成首次启动)、starting、running、stopping、stopped、unknown
ready 仅当本次检查通过 SSH 登录客机并验证 sudo 时为 true
ssh ready、pending(首次启动进行中)、unavailable、offline、unchecked
observed 客机报告的 macOS 版本与基础镜像不同时出现
window_visible 桌面窗口显示期间出现
error、warnings 最近一次记录的失败,以及本次检查发现的 SSH 问题

生命周期结果

up、restart、open、recreate 与 configure 返回单个结果;start、stop 与 destroy 返回 {"machines": [...]},每台机器一项,只指定一台时也是如此。

{"name": "mac1", "action": "created", "state": "running", "ready": true,
 "address": "10.10.20.10", "user": "alice", "version": "27.0", "build": "26A428"}
字段 取值
action created、started、running(已在运行)、restarted、recreated、opened、configured、stopped、powered_off、already_stopped、destroyed、absent
forced 正常关机未完成、只能断电时为 true
window 显示了桌面时为 true
warnings 不影响结果的后续事项,例如下次启动才生效的变更

exec --json 返回与 Linux barn exec --json 相同的对象:node 为机器名, exit_code、stdout 与 stderr 来自客机。交互式 ssh 没有 JSON 形式。

失败

退出码与 Barn 命令行一致;远程命令自身的退出码经 ssh 与 exec 原样返回。JSON 失败结果带有稳定的 reason 与 next 命令:

Reason 退出码 含义与下一步
mac_host_unsupported 3 不是 Apple 芯片,或 macOS 低于 27
mac_runner_missing 3 命令行旁边没有安装 Mac 组件
mac_runner_protocol 3 命令行与组件来自不同构建,请一起安装
mac_root 2 请以普通登录用户运行,不要使用 sudo
mac_download_consent 2 没有终端时下载 macOS 需要 --yes,或改用 --ipsw
mac_machine_absent 4 没有该名称的机器;执行 barn mac up NAME
mac_not_initialized 4 机器尚未完成首次启动;执行 barn mac up NAME
mac_not_running 4 ssh/exec 需要机器正在运行;执行 barn mac start NAME
mac_running 4 该变更需要先停机;执行 barn mac stop NAME
mac_configuration_conflict 4 up 的参数与已有机器不同;按提示执行 configure 或其他命令
ssh_config_linked 4 ~/.ssh/config 是链接;请手动加入打印出的 Include 行
mac_vm_limit 6 已有两台 macOS 虚拟机在运行;停止提示中的那台
mac_subnet_in_use 6 宿主路由与机器网段重叠;执行 configure NAME --subnet auto
disk_full 6 可用空间不足以下载或安装 macOS
mac_machine_damaged 7 启动过的机器丢失了磁盘或身份文件;其目录原样保留
mac_readiness_interrupted 130 stop 中断了首次启动时的 SSH 等待

文件

$BARN_HOME/mac/
  config.json                        安装标识与默认基础镜像
  images/ipsw/<build>.ipsw(.json)    Apple 恢复镜像;下载中为 .partial
  images/base/<id>/                  只读、从未启动过的 macOS 基础镜像
  slots/<name>/state.json            机器记录(schema 2)
  slots/<name>/disk.asif             基础镜像之上的写时复制磁盘层
  slots/<name>/machine-id.bin        Apple 机器标识
  slots/<name>/auxiliary-storage.bin 启动存储
  slots/<name>/id_ed25519(.pub)      机器的 SSH 密钥对
  slots/<name>/known_hosts           固定的主机密钥,别名为 barn-mac-<instance>
  slots/<name>/password              登录密码,权限 0600
  slots/<name>/runner.log            运行日志(barn mac logs)

运行时 socket 位于 /tmp/barn-mac-<uid>-<hash>/。ssh-config 写入 ~/.ssh/barn-mac_config,并在 ~/.ssh/config 中加入一个 # barn-mac:include 区块,与 Linux 的 # barn:include 区块互不影响。桌面窗口位置保存在 ~/Library/Preferences/io.pgsty.barn.mac-runner.plist。

Barn 在客机中写入 ~/.ssh/authorized_keys、/private/etc/sudoers.d/80-barn、 /etc/ssh/sshd_config.d/000-barn.conf,设置电脑名称与本地主机名,并用 pmset 关闭睡眠。

4 - 镜像

签名 Catalog、内置别名、仓库选择、本地缓存校验、导入与清理。

Barn 使用物化的静态 Catalog 与不可变 qcow2 工件。官方与 HTTP Catalog 必须签名; 用户显式选择的本地或 HTTPS 仓库可以不签名。更新 Catalog 不需要发布新的 Barn 二进制,但二进制决定信任哪些签名公钥与镜像安全规则。

警告

EL7、EL9 9.3/9.6 与 EL10 10.0 是 deprecated 兼容镜像;其余内置版本均为 supported。

别名与拉取顺序

Barn 0.9.0 内置 Catalog 2026092902,包含 9 个 Family、39 个工件。el7 只有 amd64,其余 Family 均有 amd64 与 arm64。 EL9 包含 9.3、9.6、9.7、9.8;EL10 包含 10.0、10.1、10.2。 默认请求为本机架构的 u24:stable(Ubuntu 24.04)。

以下 stable 均覆盖 amd64 和 arm64。这是内置 Catalog 快照,不是实时仓库列表。 运行 barn update,再用 barn image list 查看选定仓库当前的目录。带日期的公开 端点检查与 Guest 小版本观测见当前状态。

Family 内置 stable 发行版系列
d12 20260923.2610.1 Debian 12
d13 20260914.2601.2 Debian 13
el8 8.10.20240528.2 Rocky Linux 8.10
el9 9.8.20260525.2 Rocky Linux 9.8
u22 20260926.0.0 Ubuntu 22.04 LTS
u24 20260926.0.0 Ubuntu 24.04 LTS
u26 20260927.0.0 Ubuntu 26.04 LTS

Debian 保留离线安装的 XFS 工具和已生成的 en_US.UTF-8,默认 locale 仍为 C.UTF-8。Ubuntu 保留 Canonical 原始镜像,账户与网络由启动时的 cloud-init 配置。 Debian 12 的 9 月 23 日上游构建仍缺少 XFS 工具和 en_US.UTF-8,这两项定制仍然 必要。上述 Ubuntu 原版已包含二者,amd64、arm64 均于 9 月 29 日通过 locale 和 XFS 数据盘检查。 更新 Catalog 只改变新解析的 stable;既有 VM 和显式锁定版本继续引用原来的基础镜像。

别名 发行版 架构 启动 状态
el7 CentOS Linux 7.9 / 2211 amd64 BIOS deprecated
el8 Rocky Linux 8.10 amd64、arm64 UEFI supported
el9 Rocky Linux 9.7 / 9.8 amd64、arm64 UEFI supported
el9 Rocky Linux 9.3 / 9.6 amd64、arm64 UEFI deprecated
el10 Rocky Linux 10.1 / 10.2 amd64、arm64 UEFI supported
el10 Rocky Linux 10.0 amd64、arm64 UEFI deprecated
d12、d13 Debian amd64、arm64 UEFI supported
u22、u24、u26 Ubuntu amd64、arm64 UEFI supported
barn image list
barn image info d13
barn image info d13:stable
barn image info el9@9.7
barn image pull d13@20260914.2601.2
barn image pull d13 --arch arm64
barn update

Catalog 状态只表达支持策略,不是启动开关:supported 表示已通过声明的支持门禁; testing 可在显式测试/风险接受下使用,但不受支持;deprecated 只为 EOL 兼容保留; unknown 尚无支持分类。非 supported 条目仍可运行,但会打印警告。

拉取时 Barn 会:

  1. 为整条命令读取一次选定仓库的本地 Catalog:即本次构建内置的 Catalog,或最近一次 为该仓库通过 barn update/image sync 激活的 Catalog;
  2. 解析 image[:channel] 或 image@version-prefix,官方 Catalog 缺省为 u24:stable; 独立 image pull 默认使用本机架构,可通过 --arch 覆盖;生命周期解析遵循 vm_arch;
  3. 只有尺寸、SHA-256、qcow2 结构全部匹配时才复用本地文件;
  4. 否则下载 Catalog 指定的准确工件,并支持重试和断点续传;两个官方仓库可互相回退, 自定义仓库仍为唯一来源。接受的字节始终须匹配 Catalog;不可变 Upstream URL 只用于溯源。

Release 构建默认使用 https://repo.pigsty.io/barn;仅有长参数的 --mirror 选择 https://repo.pigsty.cc/barn。优先级依次为 --repo、--mirror、BARN_REPO、 全球默认仓库,两个官方根都保持规范的签名 Catalog 信任。仓库选择同时决定本地 Catalog 槽位和下载来源;即使字节已缓存,仍需选择相同的自定义仓库。Barn 不会自动刷新 Catalog,已有激活目录与已校验缓存时,普通镜像解析可以离线进行。 运行 barn update 可获取、校验并激活选定 仓库当前的 Catalog。Catalog 更新使用该指定源,失败时直接报错;镜像下载则在所有 允许的来源均无法提供通过校验的字节时失败。 仅改变 --repo 不会获取或激活该仓库的 Catalog;使用它的自定义别名前,先运行 barn update --repo <root>。

已校验但可写的缓存文件会恢复为只读;损坏且未被引用的缓存会先保留为带 .corrupt-<timestamp> 后缀的文件,再重新下载。仍被 VM 引用的基础镜像保持原位并报错。

运行时策略

匹配架构正常使用原生 HVF/KVM,只有一个 Catalog 已知例外:Stock EL8 arm64 的 64K Granule Kernel 无法通过 Apple HVF 运行,因此 Apple Silicon 会自动选择可见的同架构 TCG。显式外来 vm_arch 也会使用 TCG;arm64 宿主上的 amd64 Guest 使用单翻译线程, 以保留 x86 内存序。TCG 结果不能作为性能证据。

EL7 刻意仅支持 Linux/amd64 原生运行。Linux setup 只安装宿主原生 QEMU;外来架构必须 先安装对应 System Emulator 与 UEFI 固件,up、recreate 才会继续;plan 无需 这些工具就能解析 Catalog 镜像与运行时;但 local-* 命名导入在解析时会检查缓存字节, 仍然需要 qemu-img。

barn image pull d13 --mirror
barn image pull d13 --repo https://mirror.example/barn
BARN_REPO=/absolute/local/repository barn up

未签名仓库必须是本地路径或 HTTPS。HTTP 仓库必须提供可信密钥签名;不可变 Upstream 工件 URL 必须使用 HTTPS。

信任与校验

当前普通构建已经内置两把生产校验公钥;私有签名密钥不在源码仓库中。Catalog 激活会拒绝 未知密钥、畸形内容、同 Revision 异内容,以及低于该仓库独立 High-water Mark 的 Revision;只有操作者显式允许时才可降级。

镜像必须是尺寸与 SHA-256 匹配的纯 qcow2,不得有 backing file、外部数据文件、加密或 未知不兼容 Feature。通过校验的 Base Image 变成只读;节点根盘使用 Overlay,永不修改 Base。

barn update
barn image sync --repo https://repo.example/barn \
  https://repo.example/barn/catalog.json
barn image sync --repo /absolute/repo --allow-downgrade /absolute/repo/catalog.json
barn image reset

image reset 恢复二进制内置的 Catalog,但不会清除防回滚 High-water Mark。

barn update 立即检查仓库并激活更新的 Catalog。Barn 不会自动刷新 Catalog;每个版本 内嵌的 Catalog 会一直使用到你运行 update。image sync 是指定精确 URL 或文件(含降级)的 恢复路径。

按仓库恢复时要显式传入同一个根目录:

barn image sync --repo /srv/barn --allow-downgrade /srv/barn/catalog.json
barn image reset --repo /srv/barn

--repo 决定独立的活动 Catalog 与 High-water 槽,位置参数中的源不会改变这个选择。 image sync、image reset 接受 --repo,不接受 --mirror;省略 --repo 时使用 BARN_REPO 或编译期默认值。未签名自定义 Catalog 的精确源必须是选定根下的 catalog.json。

静态仓库格式

发布根刻意保持很小:

barn/
├── repo.yaml
├── catalog.json
├── catalog.json.minisig       # 官方与 HTTP 仓库必需
└── images/
    └── <image>-<version>-<arch>.qcow2

repo.yaml 保存人工意图:默认值、别名、Channel、精确版本、架构、启动模式、状态和可选、 只用于溯源的 Upstream URL。source_user 记录镜像声明的源登录身份,例如上游镜像的 rocky,或经过 Barn 官方归一化后的 dba。流水线清理候选镜像时另行接收上游账号。 Catalog/导入元数据不会替换 deployment SSH 用户(默认 dba),也不会自行归一化镜像。 该文件不保存任何生成的摘要或大小;catalog.json 保持同一逻辑树, 但为每个 Variant 物化文件名、SHA-256、工件大小和虚拟大小。repo.yaml 是 schema: 1; 生成的 catalog.json 则是 Barn 内嵌并签名的 Schema-3 Catalog。

schema: 1
revision: 1
defaults: { image: u24, channel: stable, arch: native, boot: uefi }
images:
  u24:
    aliases: [ubuntu24, noble, ubuntu]
    channels: { stable: "1" }
    versions:
      "1":
        status: unknown
        variants:
          amd64: {}
          arm64: {}

不显式设置 file 时,两个预期工件分别是 images/u24-1-amd64.qcow2 与 images/u24-1-arm64.qcow2;已有自定义文件可在 Variant 中覆盖为安全 basename。

Channel 与数值前缀都是可移动 Selector。存在精确 Key 时优先精确匹配;否则只在点分量 边界匹配并选择数值语义最新版本(el9@9.7 选择最新 9.7 Build,el9@9 选择最新 9.x Release)。不可变工件身份仍是 (image, exact version, arch):

d13:stable + native
  -> d13@20260914.2601.2 + arm64
  -> images/d13-20260914.2601.2-arm64.qcow2

barn repo scan 只读;build 执行严格 YAML 校验、完整 qcow2 inspect/check, 并原子替换 Catalog,永不修改 repo.yaml 或 QCOW 字节;verify 要求新鲜物化结果与 现有 Catalog 逐字节一致。build、verify 需要本机 qemu-img,scan 不需要。 应在安装 QEMU 的机器上构建,先发布不可变工件,最后发布 Catalog 与匹配签名,尽量 一起切换两者;正文与签名不一致时验签会失败。 修改 Catalog 内容时必须增加 revision。

本地布局与导入

镜像位于 BARN_HOME/images(默认 ~/.barn/images):各 Family 目录保存下载工件, manifests/ 保存当前激活的 Catalog 与每个仓库独立的 High-water 状态,local/ 与 local-images.json 保存导入镜像。

barn image import --sha256 <digest> /path/to/base.qcow2
barn image import --name local-mybase --boot uefi \
  --source-user ubuntu --sha256 <digest> /path/to/base.qcow2

CLI 中 --sha256 是可选参数;提供独立获得的可信摘要,才能在必做的 qcow2 检查之外加入 显式真实性校验。导入只复制和校验文件,不会清理凭据、安装 cloud-init、识别 Guest CPU 架构或证明镜像可启动。

命名本地别名必须以 local- 开头,避免未来签名 Catalog 遮蔽它们。--name、--boot、 --source-user 必须同时提供。命名导入记录执行导入的宿主原生架构,没有 image import --arch 参数;外来架构镜像应使用声明明确 Variant 的静态仓库。 别名不可变,镜像字节或元数据改变时应使用新名字。在 Inventory 中通过 vm_image: local-mybase 选择命名导入;不指定名字的导入只填充缓存。

清理

barn image prune --dry-run
barn image prune --yes

不带参数的 prune 与 --dry-run 只报告候选,--yes 才执行删除。保护集合是选定活动 Catalog 中的全部工件、已应用节点的镜像摘要,以及注册的本地别名。因此,即使没有 VM 使用,当前 Catalog 镜像和命名导入仍会保留。未被保护的镜像与识别出的过期 Staging File 才是候选;不安全或损坏的文件会导致报错。检查自定义 Catalog 的缓存策略时,要传入 相同 --repo。执行 destroy、destroy --purge 与 purge 后镜像仍会保留。

使用 go run ./tools/catalogexport /absolute/new/catalog.json 可逐字节导出编译期 Schema-3 Catalog。 公开 Catalog 若使用相同版本,就必须使用完全相同的字节;同版本不同内容会按 equivocation 拒绝。Release 签名与镜像 Catalog 签名仍属于不同信任域。

5 - 镜像流水线

不下载、不上传、不签名地校验或离线归一化显式 qcow2 Candidate。

底层 packaging/image-pipeline/build.sh 接受一份已下载的不可变 qcow2 与独立获得的 SHA-256。它绝不下载、上传、修改 Barn 运行时/网络状态、读取签名密钥,也不会把镜像 标成 supported。

以下命令从 Barn 源码目录执行。需要 Python 3 与 qemu-img;offline 还需要可用的 libguestfs virt-customize、virt-cat。这是镜像构建宿主的依赖,与 barn setup 为运行 VM 安装的依赖是不同边界。

模式

  • validate:复制并重哈希,强制 qcow2 检查,校验单元素 Backing Chain,运行 qemu-img check,输出明确不可发布的证据 Bundle;不会修改 Guest 凭据。
  • offline:额外在 Staged Copy 上使用 libguestfs virt-customize --no-network 与 virt-cat。它拒绝无关 UID/GID 88 占用,归一化锁定的 dba/admin 身份,关闭密码与 Root SSH,清理密钥/历史/Host Identity/cloud-init Cache,恢复定向 SELinux Label, 并回读确定性 Marker。

官方 Candidate 矩阵

build-official.py 在同一离线边界上封装固定的八目标矩阵:Debian 12/13 与 Rocky Linux 8/9,各自覆盖 amd64、arm64。每份上游 qcow2、RPM/DEB 输入、Release 名称、Digest 与 Source Epoch 都锁定在 official-v1.json。

./packaging/image-pipeline/build-official.py --list

./packaging/image-pipeline/build-official.py \
  --source-cache /absolute/source-cache \
  --package-cache /absolute/package-cache \
  --output /absolute/existing-output-root \
  --target d13/arm64 --fetch

不加 --fetch 时,全部锁定输入必须已经位于两个 Canonical Cache 目录;加上后,Wrapper 也只下载固定 HTTPS URL,并在调用离线归一化前拒绝任何 Digest 不匹配。Debian 12/13 安装锁定的 XFS 用户态闭包;Rocky Linux 8 安装锁定的 python36 与 python3-pip RPM,并在 cloud-init 启用 NTP 时使用镜像已有的 RHEL chrony 模板与 chronyd 服务; Rocky Linux 9 不需要额外软件包输入。SELinux 标签恢复属于归一化步骤,不是另一组软件包输入。

Debian 同时生成 en_US.UTF-8,并保留 C.UTF-8 作为默认 locale;归一化脚本和 宿主端 Marker 校验都会检查这两项。镜像更新也会保留这两项客机要求。Ubuntu 使用固定 日期的官方原始镜像,不经过这套离线定制流程。

每份结果仍是未签名的 testing Candidate。不传 --target 时构建全部八个目标,重复 该参数可以选择多个目标。--list 显示当前源码锁定的精确版本;目前包含 Debian 20260923.2610.1/20260914.2601.2 与 Rocky Linux 8.10.20240528.2/9.8.20260525.2。

组装接收的是包含按名称命名的 Bundle 的父目录,不是各 Bundle 自身目录。若八个 构建都放在同一个输出根下,执行:

./packaging/image-pipeline/build-official.py \
  --assemble-from /absolute/existing-output-root \
  --output /absolute/new-candidate-repository

构建分散在不同根时,可以重复 --assemble-from。八个目标都必须有且只有一个 Bundle; 组装会创建新的静态仓库,并调用 PATH 中的 barn 执行 repo build 与 verify, 也可用 --barn /absolute/path/to/barn 指定程序。构建模式使用已存在的输出根, 组装模式的目标目录则必须不存在。生成仓库使用 candidate Channel,而不是 stable, 例如应选 d13:candidate。此过程不包含真机 Smoke、签名、上传或 Catalog 发布。

校验一个已下载镜像

SOURCE_DATE_EPOCH=1787486400

./packaging/image-pipeline/build.sh \
  --mode validate \
  --source /absolute/source.qcow2 \
  --expected-sha256 <digest> \
  --output /absolute/new/evidence-directory \
  --name u24 --release 20260801.0.0 --arch amd64 \
  --source-user ubuntu --boot uefi \
  --source-uri https://immutable.example/source.qcow2 \
  --artifact-url 'https://images.example/u24/{sha256}.qcow2' \
  --license NOASSERTION \
  --source-date-epoch "$SOURCE_DATE_EPOCH" \
  --manifest-version 2026082903

Source/Output 必须是绝对路径;Source 必须 Canonical、普通、非符号链接、复制期间稳定, 且不超过 16 GiB;Output 必须不存在。Builder 使用相邻排它锁、0700 Staging 与一次最终 Rename;失败只删除受保护的 Staging。

成功 Bundle 包含只读 qcow2、Recipe、SLSA Provenance、SPDX Boundary SBOM、状态为 testing 的 manifest-candidate.json、Validation Evidence 与 Checksums。候选 Manifest 是流水线证据格式;仓库组装才会生成运行时使用的 Schema-3 catalog.json。SPDX 文件 描述声明的输入/构建边界,并不是 Guest 文件系统的完整软件包清单。签名刻意位于流水线 之外。固定输入/工具下 validate 模式逐字节可复现;offline Mutation 必须构建两次并比较, 才能成为 Release Evidence。

发布仍需要对每条声明的宿主/Guest 路径进行运行时 Smoke,明确审查支持状态与溯源, 增加 Catalog Revision,进行生产签名,并校验公开工件。构建成功不能直接把 Candidate 改成 supported,也不能证明它已经公开可用。