OTA 与发布
HomeHarbor 的 OTA 与发布链路覆盖 update bundle、签名、boot payload、安装器 artifact 和 readiness 检查。
Release channel
当前 channel 集合由 HomeHarbor.Tooling.ReleaseChannel 约束。常见 channel:
devdailystable
channel 读取优先级:
HOMEHARBOR_OTA_CHANNEL_FILE指向的文件,默认/var/lib/homeharbor/ota/channel。HOMEHARBOR_CHANNEL。- 默认
dev。
OTA status API
GET /api/ota/status 返回:
- 当前版本:
HOMEHARBOR_VERSION或0.1.0-dev。 - 当前 channel。
- 可用 channel。
- update state:存在 pending manifest 时为
pending-reboot,否则为idle。 - stage/apply endpoint。
POST /api/ota/stage 和 POST /api/ota/apply 目前接收 manifest metadata,返回 accepted。实际 appliance updater 负责验证 bundle、写入 inactive slot、更新 boot 环境并 reboot。
Manifest 要求
manifest 包含这些要求:
bootMode为raw-uki或secure-boot-raw-uki。- channel 必须是当前允许值。
releaseSequence是正整数,并且每次发布都必须递增。packageKind=system时type=full-system。packageKind=kernel时type=kernel-only。
manifest canonical payload(包括 releaseSequence)由固定字段顺序生成。签名算法为 Ed25519,签名校验通过 openssl pkeyutl -verify -pubin -rawin 完成。
执行网络 OTA 时,updater 会把已签名的目标 sequence 与当前 immutable root 和 signed kernel command line 中的可信 sequence 比较。同一 release 的更新被明确拆分, 并且必须按 kernel-first 顺序执行:
- 先应用 sequence N 的
kernel/kernel-onlybundle。它会写入 inactive boot、 modules、firmware 和 recovery slot,并原子更新已签名的 ESP boot selector 以及 已存在的 Secure Boot fallback 路径。 - reboot 进入该 kernel 并 commit。
- 再应用相同 sequence N 的
system/full-systembundle。其 target sequence 必须与 当前正在运行的 signed kernel sequence 完全相等;如果 system bundle sequence 比 当前 kernel 更新,updater 会在写入任何目标分区或 ESP 之前 fail closed,并提示先 应用匹配的 kernel bundle。 - reboot 进入新的 root slot 并 commit。
每个 bundle 都必须严格推进它负责的 component。sequence 缺失、格式错误、重放或 顺序错误都会 fail closed。sequence 与展示用 version 相互独立,不能重置或重复使用。
此检查无法阻止具备物理离线写入能力的攻击者,把当前 root、boot 和验证状态整体替换 成一套更旧但内部一致、签名仍然有效的 artifact。Secure Boot 和 AVB 能证明真实性, 但不能证明新鲜度。要阻止这类 rollback,需要 TPM NV counter 或强制 AVB rollback index 等硬件支持的单调锚点。
System bundle
system/full-system bundle 只更新 root component 及其 AVB metadata,包含:
rootfs.imgvbmeta_a.imgvbmeta_b.img
它不会携带 kernel、modules、firmware、recovery 或 ESP boot asset;这些内容属于 匹配的 kernel bundle,并且必须先启动该 kernel,才能 stage system bundle。
Kernel bundle
kernel/kernel-only bundle 包含:
modules.imgfirmware.imgrecovery.imgboot.efiHomeHarborBoot.efiBOOTX64.EFI- 启用 Secure Boot 时的
mmx64.efi
HomeHarborBoot.efi 及其已签名的 bootloaderHash 是必需项。apply 时,updater 会把它原子安装到 /EFI/HomeHarbor/HomeHarborBoot.efi,更新已存在的 /EFI/BOOT/BOOTX64.EFI,并在 Secure Boot 模式下更新已存在的 grubx64.efi 和 mmx64.efi 兼容路径。每个临时文件都会先 flush,再在 ESP 上 rename,随后回读并 校验 hash;ESP 完成 sync 后,才会修改 one-shot boot state 或 pending metadata。
每个 payload 都应有 hash,manifest 记录这些 hash,并对 canonical payload 签名。
A/B 与 AVB
镜像布局包含 boot A/B、recovery A/B、vbmeta A/B 和 super 内 root/modules/firmware A/B 逻辑分区。构建过程会把 EROFS payload 写入固定大小逻辑镜像,并附加 AVB hashtree。 AVB descriptor 的 partition name 是 slot-transparent 的(root、modules、firmware、recovery);vbmeta_a.img 和 vbmeta_b.img 是为了 A/B 分区布局保留的镜像副本。
generic boot cmdline 携带 sealed boot inputs,实际 A/B 选择由 boot selector 通过 EFI state 发布:
rd.homeharbor.verity=1homeharbor.boot_modehomeharbor.boot_generichomeharbor.superhomeharbor.kernel_releasehomeharbor.vbmeta_a_digesthomeharbor.vbmeta_b_digesthomeharbor.modules_a_verityhomeharbor.modules_b_verityhomeharbor.firmware_a_verityhomeharbor.firmware_b_verityhomeharbor.recovery_a_verityhomeharbor.recovery_b_verityhomeharbor.release_sequencehomeharbor.version
Secure Boot
HOMEHARBOR_SECURE_BOOT=1 时 boot mode 为 secure-boot-raw-uki。默认 Secure Boot enrollment 流程依赖 Microsoft-signed shim 和 MokManager。HomeHarbor 安装 signed boot selector,使 shim 能通过已 enrollment 的 MOK 验证。
release 构建不能使用 unsigned 例外。非 dev channel 缺少 release public key、Secure Boot 签名 key 或启用 unsigned flag 时应失败。
常用构建命令
查看 plan:
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- plan 0.1.0-dev
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- system-plan system/x86_64/system/manifest.yml 0.1.0-dev "$(pwd)"
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- kernel-package-plan system/x86_64/kernel 0.1.0-dev "$(pwd)"生成基础镜像和 OTA 输入:
HOMEHARBOR_RELEASE_SEQUENCE=1234 \
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- \
system-build system/x86_64/system/manifest.yml 0.1.0-dev "$(pwd)"该值必须为正数,并且大于同一 appliance lineage 过去发布的所有 sequence; release-build 也有相同要求。
构建 Arch 包和 kernel-channel artifacts:
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- arch-package 0.1.0-dev "$(pwd)"
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- kernel-package-build system/x86_64/kernel 0.1.0-dev generic "$(pwd)"直接构建 boot helpers:
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- build-efi-loader artifacts/HomeHarborBoot.efi "$(pwd)"
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- build-homeharbor-avb artifacts/homeharbor-avb "$(pwd)"
dotnet run --project tools/system-build/src/HomeHarbor.ImageBuilder/HomeHarbor.ImageBuilder.csproj -- build-homeharbor-init artifacts/homeharbor-verity "$(pwd)"Channel metadata
release metadata 由 C# 构建流水线生成,并由 GitHub release workflow 消费。
GitHub release workflow
GitHub release workflow 会从 artifacts/channels/{version} 发布 daily 和 stable 资产。上传内容包括 system OTA artifact、generic 与 ZFS kernel-channel OTA artifact、live installer ISO 和 channel metadata。
workflow 会把单调递增的 GitHub run_number 作为 HOMEHARBOR_RELEASE_SEQUENCE 传进 image-build container。
workflow 在 artifact build 阶段设置 HOMEHARBOR_RELEASE_SKIP_FULL_E2E=1, 因此不会自己完成 appliance VM 验证。正式 appliance 发布前,需要单独运行并归档 VM 证据,例如 FullE2E/interactive report、screenshot、log 或测试输出。