NixOS 使用感受

最近给笔记本电脑更换了硬盘,同时更换到了 NixOS 系统。本文先分享一下安装配置系统的过程和使用感受,再分享一些我的对这种声明式配置系统和容器化等技术的想法。

 

旧的 Linux 发行版对比

我第一次接触的 Linux 发行版是 CentOS,当时是在 VMware 上直接安装了。体验了几天后因为不会很多 Linux 命令就放弃了。第一次在物理机上安装的 Linux 发行版是 Fedora,当时配置了 Windows 和 Fedora 的双系统。Fedora 给我的感觉是比较美观现代,但是我当时对 rpm 包管理器不太熟练,而且一次升级之后找不到旧的 grub 启动项了,所以也就用了两三个月。之后用的比较久的是 Manjaro 发行版。作为 Arch 系列的一员,Manjaro 使用滚动更新,配合 KDE 桌面实现了比较丰富的配置。

除了这些在个人电脑和桌面环境使用的发行版,我也在云服务厂商提供的配置中使用过 Ubuntu 和 Debian,以及容器环境中的 Alpine Linux。Ubuntu 和 Debian 是相当成熟稳定的系统,但是我认为不太适合在我的个人电脑上配置,尤其是 Ubuntu 的 SNAP 包管理系统。我也尝试了在一个 USB 盘上安装了 Alpine Linux,但是这个系统也难以配置,感觉更多的还是在容器里使用。

在使用了 Manjaro 四年多之后,我也遇到了不少问题。首先是双系统和硬盘空间的问题。旧的安装过程中为了和 Windows 兼容,我给磁盘分了 Linux 分区、Windows 分区和数据分区三个分区。数据区使用的是 NTFS 分区,因此缺少了权限控制和一些 Unix 的文件属性。这样的文件分区使得扩容和备份变得困难,尤其是在大的系统更新之后。第二个问题关于桌面管理系统。旧的 Manjaro 使用 KDE 的桌面,但是我自己配置了 dwm 作为窗口管理器。结果就是我对于这些 X11 和 KDE 的包不熟悉,安装了一大堆臃肿的包。而且当我想切换到 Wayland 的合成器时也不知道如何下手(其实 KDE 更新后提供了一个 Wayland 的会话选项,但是我也不知道如何配置)。第三个方面的问题在于主文件夹下的配置文件。除了 Emacs 和少数几个程序我有专门维护过配置,其他大大小小的各个程序的配置文件杂乱地放在主文件夹下面,让我感觉难以整理。

一种常见的方案是使用声明式的发行版,例如 NixOS 和 Guix。Guix 是 GNU 的一个项目,他们一直想推自己的内核 Hurd,当然目前 Linux 也是一个选项。 Guix 使用的是 Scheme 作为配置语言,使用 Shepherd 替代 systemd 来配置系统服务。总的来说我觉得还是 Nix 和 systemd 的生态更完善一些,因此我选择使用 NixOS 来作为新的 Linux 发行版系统。在硬件方面,我打算给整个硬盘分区为一个 EFI 和一个 Btrfs。我打算把旧的 Manjaro 迁移到到一个 Btrfs 的子卷,也做一个双系统。但是旧的 Windows 就不迁移了(近几年来微软和 Windows 的种种设计和营销,让开发者和开源软件没有理由在游戏之外的领域选择他们了)。在桌面问题方面,我决定使用新的 Wayland 合成器和 Sway 窗口管理器(我意识到其实平铺式窗口管理器也有丰富的配置,可以实现很高的效率)。在主文件夹下的配置,我决定使用 Nix flake 结合 home manager 的方式管理。但是对于 Emacs 和少数几个软件,我会直接使用软链接和复制的方式配置,因为我意识到 Emacs 自身也有一个优雅的函数式的配置解决方案。

安装和配置过程

首先是硬件配置和磁盘分区,我首先准备了用 Git 控制的 Nix 配置仓库。使用 Live 镜像进入系统后使用 Btrfs 创建分区,创建网络,然后生成硬件配置。下一步是配置 home-manager 以及一些常用软件,包括 Sway, Emacs, SSH, Podman, Alacritty, Chromium 等。到目前为止配置起来花费了不少功夫,但是大部分效果都实现。稍微有些麻烦的是有些软件的选项没有(要么在 unstable,要么就是没有),得自己写配置文件然后写入到专门的文件夹下面。

NixOS 的可复现性和 devcontainer

说到底,对于这个可复现性我其实用的不多,我感觉现在还是使用初期,很多配置都是最简化能运行的。之后我如果要试验一些新功能,可能就会更多地使用快照和 Git 仓库结合的方式配置。

其实使用这个 NixOS 的时候我也想到了之前配置的 devcontainer。简单来说 devcontainer 利用的是 docker 一类的容器化技术,使用 Dockerfile 或者一些脚本文件来配置一个环境,然后用 配置好的 VSCode 或者其他编辑器通过 SSH 进入到容器环境里开发。这类配置的好处是能够在一个独立的环境中开发,而且和 Git 或者 GitHub 的流程配合的比较好(例如 GitHub Codespaces),缺点是这个 VSCode 插件是专有的,而且包的体积稍大。我之前也了解过 Nix 在容器化方面也有一些应用,可以最小化镜像的体积并且固定版本,但是我确实不知道其在 devcontainer 方面的应用。另外一方面来说,Nix 的工具链也允许不用 docker 而是直接在一个文件夹下使用 nix develop 来开发。

总的来说,我觉得也不算所有方面都要完全可复现性,尤其是在一些个人配置的应用,例如我
Emacs 配置和 Rime 词库输入法。我也觉得单纯在其他的个人使用的电脑上单独使用 Nix 不是一个好主意。在 MacOS 下面,可能一些配置就会与苹果的安全政策冲突,而其他的 Linux 发行版在各方面和 Nix 也有不同(例如很多 Linux 发行版遵循的 FHS 就和 Nix 不完全相同)。 我更看好的是这种可复现性能满足我稳定使用和折腾新功能的需求,另一方面是使用这种集中化的配置来管理计算资源。

评论系统尚未配置。请在 .env 中填写 giscus 所需的环境变量。