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、随机链接)可以与可复现的软件包共存,因为随机性可以在经过验证的制品安装后再应用。