NixOS 的优缺点
优点
- 声明式配置,OS as Code,可以直接用 Git 管理配置
- NixOS 使用声明式配置来管理整个系统环境,只要你的配置文件不丢,系统就可以随时还原到任一历史状态(前面提过了,只有在 Nix 配置文件中声明了的状态才可被 NixOS 还原)。
- 为了提升系统的可复现能力,Nix Flakes 还使用了
flake.lock
作为版本锁文件,它记录了所有相关数据的数据源地址、hash 值。这个设计实际是从 cargo/npm 等一些编程语言的包管理设计中借鉴来的。 - 与 Docker 相比,Dockerfile 实际是命令式的配置,而且也不存在版本锁这样的东西,Docker 容器环境的可复现实际依赖于直接通过 Docker Hub 分享构建结果(Docker 镜像),这可比 Dockerfile 本身大多了。
- 高度便捷的系统自定义能力
- 通过改几行配置,就可以简单地更换系统的各种组件。这是因为 Nix 将底层的复杂操作全部封装在了 Nix 软件包中,只给用户提供了简洁且必要的声明式参数。
- 而且这种修改非常安全,你可以很方便地来回切换各种桌面环境(比如 gnome/kde/i3/sway),几乎不会遇到坑。
- 可回滚
- 可以随时回滚到任一历史环境,NixOS 甚至默认将所有旧版本都加入到了启动项,确保系统滚挂了也能随时回退。所以 Nix 也被认为是最稳定的包管理方式。
- 没有依赖冲突问题
- 因为 Nix 中每个软件包都拥有唯一的 hash,其安装路径中也会包含这个 hash 值,因此可以多版本共存。
- 社区很活跃,第三方项目也挺丰富,官方包仓库 nixpkgs 贡献者众多,也有很多人分享自己的 Nix 配置,一遍浏览下来,整个生态给我一种发现新大陆的兴奋感。
缺点
- 学习成本高: 如果你希望系统完全可复现,并且避免各种不当使用导致的坑,那就需要学习了解 Nix 的整个设计,并以声明式的方式管理系统,不能无脑
nix-env -i
(这类似apt-get install
)。 - 文档混乱: 首先 Nix Flakes 目前仍然是实验性特性,介绍它本身的文档目前比较匮乏, Nix 社区绝大多数文档都只介绍了旧的
nix-env
/nix-channel
,想直接从 Nix Flakes 开始学习的话,需要参考大量旧文档,从中提取出自己需要的内容。另外一些 Nix 当前的核心功能,官方文档都语焉不详(比如imports
跟 Nixpkgs Module System),想搞明白基本只能看源码了... - 比较吃硬盘空间: 为了保证系统可以随时回退,nix 默认总是保留所有历史环境,这非常吃硬盘空间。
- 这在桌面电脑上可能不是啥事,但是在资源受限的云服务器上可能会是个问题。
- 报错信息比较隐晦: 一般的报错提示还是比较清楚的,但是遇到好几次依赖版本有问题或者传参错误提示不出原因,
--show-trace
直接输出一堆的内部堆栈,都花了很长时间才定位到,通过升级依赖版本或者修正参数后问题解决。- 猜测导致这个问题的原因有两个,一是 Nix 是动态语言,各种参数都是运行时才确定类型。二是我用到的 flake 包的错误处理逻辑写得不太好,错误提示不清晰,一些隐晦的错误甚至通过错误堆栈也定位不到原因。
简单总结下
总的来说,我觉得 NixOS 适合那些有一定 Linux 使用经验与编程经验,并且希望对自己的系统拥有更强掌控力的开发者。
我不推荐没有任何 Linux 使用经验的新人直接上手 NixOS,那可能会是一段糟糕的旅程。