NixOS 可复现构建:最小 ISO 已成功被独立重建
NixOS 已经达成一个里程碑:其最小安装 ISO 可以被独立重建并达到逐位一致,这也引发了对“可复现性”在实践中真正意味着什么的更广泛讨论。评论者区分了 Nix 的输入级可复现性(相同配置得到相同环境)与完整的二进制可复现性,将 NixOS 当前的覆盖范围与 Debian、Arch 和 Guix 的努力进行比较,并探讨了确定性工具链、从极小受信任二进制引导启动,以及这些内容如何与安全、包签名和软件供应链风险交织在一起。除了技术上的赞赏,几位发言者也强调了 NixOS 陡峭的学习曲线,并将其与 Docker、Ansible 和 Fedora Silverblue 等更传统的工具进行对比。
可复现性的定义
- 强调区分:
- 输入可复现性:相同的 Nix 表达式 + 完全相同的带哈希输入 ⇒ 相同的环境和行为(“完美的缓存失效”)。这是 Nix/NixOS 的核心保证。
- 输出可复现性:在不同机器上,从相同源代码得到逐位完全相同的二进制文件。这个 ISO 里程碑针对的是更难的这个问题。
- 澄清 Nix store 的哈希(在大多数情况下)是输入寻址的,而不是默认内容寻址;实验性的内容寻址派生已经存在,但不能取代可复现构建。
NixOS 与其他发行版的现状
- 最小 NixOS ISO 现在已经可以被独立重建到逐位一致;GNOME ISO 可能是下一步。
- 约 8 万个 nixpkgs 包中,只有一小部分被系统性测试;确实发生过回归(例如 Python 优化问题)。
- 其他项目(Debian、Arch、Guix)会系统性测试其仓库中更多内容,当前报告的覆盖率更高;由于生态和包数量不同,确切对比被称为“并不清楚”。
- 更新的 Nix 基础设施(
reproducible.nixos.org)取代了旧的 r13y.com。
可用性与学习曲线
- 一些用户期望“容易复用的配置”,但感到沮丧(例如,在 Nix 上使用 Hyprland 与在 Arch 上快速搭建的对比)。
- 关于是否从 flakes 开始,建议分歧很大:有人说它们仍处于实验阶段且令人困惑,另一些人则认为它们显著改善了 UX 和一致性。
- 推荐使用入门配置仓库和 home-manager 来降低上手门槛。
非确定性的技术来源
- 常见原因:时间戳、构建时的“版本字符串”、非确定性的 hashmap 迭代、基于指针的排序、并行性和对竞态敏感的算法、随机化运行时。
- 采用了可复现构建社区的模式,例如
SOURCE_DATE_EPOCH(比如 Python 的构建日期由源归档时间戳派生)。 - 文件系统/镜像创建顺序(例如 ISO extent)需要特定工具和调用方式的调整。
引导启动与“信任信任”
- Guix 因另一个里程碑而受到关注:通过一个多阶段的十六进制/汇编链,从 357 字节的种子引导完整工具链。
- 这项工作与 Nix 的 ISO 工作被视为朝着端到端可验证系统迈出的互补步骤。
- 可复现构建有助于应对“信任信任”问题,但不能完全解决;多样化双重编译和完整环境引导被提及为更深入的方法。
安全、包签名与供应链
- 对 Nix 缺乏维护者级包签名存在强烈分歧:
- 一方认为:Nix 关注可复现、沙箱化的构建;用户可以重建并验证输出,因此维护者签名的价值有限。
- 另一方认为:如果没有签名的表达式/提交以及信任网络,通过被攻破的开发者账户或基础设施发起的供应链攻击仍然太容易;他们认为其他发行版的签名实践更好。
- Nix 的二进制缓存输出由中心密钥签名,但并没有标准化机制去要求或验证包定义上的开发者/维护者签名。
- 一些人认为这是为了保持 Nix 的可组合性和去中心化而刻意做出的设计选择;批评者则建议在其上层构建一个精选的、面向安全的层或分支。
与其他系统的比较
- Docker:Nix 可以将 OCI 镜像构建为输入的纯函数,避免 Dockerfile 的可变性和网络抓取。
- Fedora Silverblue / ostree 和 Ansible:与 NixOS 完全声明式、不可变、但无需重启的模型形成对比。
- OpenBSD:说明安装后随机化(例如 ASLR、随机链接)可以与可复现的软件包共存,因为随机性可以在经过验证的制品安装后再应用。