前言

与 archlinux 不同, NixOS(以下简称 Nix)因其可复现构建的特性而更加适合服务器。简单来说,在 archlinux 上,你在不同的时间构建同一个版本的软件,构建出来很可能是不一样的,而在 Nix 上,不同时间构建出来的同一份软件应当是二进制级别的相同,而这种特性就非常适合服务器。同时 Nix 每个包的依赖都是独立的,都放在 /nix/store下面的子文件夹,文件夹名称通常是 对应构建的 id,不同版本的依赖直接自动链接到对应的文件。 但是 Nix 由于不支持 FHS 规范,个人认为不太适合当成个人电脑的系统,个人电脑上也不需要可复现的构建(至少我作为打包者也不关心,我只要最新的,不要可复现)。还有就是 Nix 应该会在 /nix/store 下面存放好多个不同版本的软件(作为依赖引入嘛),所以磁盘空间会消耗得比较快(服务器上当然无所谓啦)。

闲话就说到这。我之前申请了甲骨文的 ARM 免费服务器,配置为 4c24g,100G. 由于 arch 没有官方的 arm 支持,所以后来装了 Nix, 但是我还不太会 Nix, 当时是用 cloudinit 脚本一键安装的,安装完完全不会用。想要学也不知道从何开始。因为非常羡慕 NickCao 把 他的 Nix 配置直接放在 github,然后服务器自己去拉取最新配置(也可能是push 的时候自动触发服务器来拉取),总之就非常的炫,管理起来也非常方便, 因而我一心想要学习 Nix 的 flake 使用。但是我完全不懂 Nix, 看了些资料也没明白我要如何开始直接用 flake, 而不是手动去维护一堆 /etc/nixos/ 下面的文件。

后来想到,我当初怎么学 archlinux 的? 去手动安装它啊!遇到不懂的就去查手册、查wiki 呀。我决定也这样子开始学一下 Nix。因此有了这篇从零开始的 Nix 安装教程。

安装

前期准备

我打算新建一个 qemu 虚拟机用来跑 Nix, 首先去 NixOS 下载页 下载最新的 NixOS 镜像,我有 arch 的经验,因此更偏好于 minimal installation, 而且我的目的也是用在服务器上面,不需要图形界面。

下载完毕之后直接进 qemu (我用 virtmanager),新建 nixos 的虚拟机,这一步不展开说。

我们启动 新建好的 虚拟机,跟着官方的安装教程一步步开始走。

进入 livecd 之后,默认登录的用户是 nixos, 我们使用 sudo su 来切换到 root. 然后检查网络是否正常,可以通过 ip a 查看。一般来说都是正常的,我们是通过虚拟机共享的宿主网络。

磁盘分区

然后我们就可以开始给磁盘分区了,官方教程用的 gparted 我更喜欢用 fdisk。先用 fdisk -l 看下我们的虚拟磁盘叫什么名字,不出意外是叫 vda (我打命令的时候老是打成 sda)。

现在我们使用 fdisk 对磁盘进行分区。

1
fdisk /dev/vda

接下来在 新建一个boot 分区,输入 n (表示 new), 起始点默认,大小选择 +512M 然后回车。接着创建主分区,输入 n 然后一路回车(我们把剩下所有空间都分给它)。

接着调整分区类型,输入 t (表示 type),先选 1(这是我们的 boot 分区), 然后类型输入 EF (表示 EFI), 接着继续输入 t, 选择 2, 类型选择 linux
更改完类型之后输入 w (表示 write) 然后输入 q 退出。

我们还要格式化磁盘,首先格式化 boot 分区为 FAT32 格式。

1
mkfs.fat -F 32 -n boot /dev/vda1

格式化主分区为你喜欢的格式(这里我选的 btrfs, 你也可以使用 ext4, 反正随便尝试嘛,我就想试试这个,我自己笔记本电脑上还是用的 ext4).

1
mkfs.btrfs -L nixos /dev/vda2

现在我们已经调整好磁盘了,开始准备 chroot了。

开始安装

先将 主分区 vda2 挂载到 /mnt 下面

1
mount /dev/vda2 /mnt

然后在 /mnt 下面创建 boot 目录并挂载 vda1 到 该目录

1
2
mkdir /mnt/boot
mount /dev/vda1 /mnt/boot

接着就可以生成配置文件了

1
nixos-generate-config --root /mnt

我们先修改配置文件(在这一步我踩了好多坑,改了好多次配置文件才通过),你不喜欢 nano 的话可以用 vim, 我自己也使用 vim (不会 nano)

1
nano /mnt/etc/nixos/configuration.nix

我选择的是用 grub 启动,所以把 grub 相关的选项都启用了(删掉行首的 #)。值得注意的是,需要修改以下这些行

1
2
boot.loader.efi.efiSysMountPoint = "/boot" #这里本来是 /boot/efi
boot.loader.grub.device = "/dev/vda" # 这里本来是 sda,但是我们是虚拟机,是 vda

其他的时区、键盘、网络这些我都先没有改。我下一个改的是

1
2
3
4
enviroment.systemPackages = with pkgs; [
vim
wget
];

不然默认没有 vim 用,而且要记得取消掉最后那个]; 的注释,我之前就是因为这个,安装的时候,配置文件检查始终不通过。

我还启用了 OpenSSH daemon

1
services.openssh.enable =true

改好了之后退出(nano 下面提示的 ^ 表示 Ctrl

最后我们就可以运行 nixos-install 来安装啦。如果没成功,你可以使用如下命令来看哪里有问题

1
nixos-install --show-trace

并返回上一步去修改 /mnt/etc/nixos/configuration.nix,再重新执行 nixos-install
成功了的话,在最后一步, nixos-install 会提示你设置 root 密码。

1
2
3
setting root password...
New password: ***
Retype new password: ***

最后执行 reboot 重启就装好了。

装好 Nix 之后我们仍然可以继续修改 /etc/nixos/configuration.nix ,要切换到修改后的配置需要手动运行

1
nixos-rebuild switch

使用 SSH 连接

接着我打算采用远程 VNC 登录,毕竟我的 virtmanager 比较简陋,现在还没法从外面复制然后在虚拟机粘贴,而 remmina 可以将剪贴板通过击键的方式发送到远程(有字数限制)。
在 qemu 对应的虚拟机界面找到 VNC(如果没有先自己添加),虚拟机启动后会显示端口。
VNC 端口

我们下面就可以在 remmina 中使用 VNC 通过 localhost:5901 连接到虚拟机。

接着我们在 configuration.nix 里面添加上 ssh 公钥,之后我们就可以通过 ssh 从主机连到虚拟机了,各种复制粘贴也都可以很方便地使用了。(这里你需要自己学习生成 ssh 密钥)

1
2
3
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFzXaUe7Y/3ptNG+xdAf+jC7g1Z7Kj+yXdfcQKZpvsy4 sukanka"
];

现在开始我们在虚拟机里面执行 ip a 来查看虚拟机的 ip.

1
2
3
4
5
6
7
8
[root@nixos:/etc/nixos]# ip a
...
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:2c:d5:fd brd ff:ff:ff:ff:ff:ff
inet 192.168.122.50/24 brd 192.168.122.255 scope global dynamic noprefixroute enp1s0
valid_lft 3109sec preferred_lft 2484sec
inet6 fe80::5054:ff:fe2c:d5fd/64 scope link
valid_lft forever preferred_lft forever

这里这个 192.168.122.50 就是我们需要的 ip. 之后就可以在外部通过如下的命令连接虚拟机 (~/.ssh/YOU_PRIVATE_KEY 替换成你的私钥文件路径)

1
ssh root@192.168.122.50 -i ~/.ssh/YOU_PRIVATE_KEY

添加 flake 支持

首先还是按照 arch 用户的惯例,换上 unstable 源再说。在这里我也踩了个坑。
刚开始看的 reddit 帖子
添加了 unstable 源, 然后我居然把默认的 nixos 源移除了,后来 nixos-rebuild switch 怎么都过不了。结果看到 Nix-Channels 上面说,必须要添加一个基础源,而且源的名字必须要是 nixos。
所以我们实际上的操作如下

1
nix-channel --add https://nixos.org/channels/nixos-unstable nixos

接着使用 nix-channel --list 看一下有哪些源,

1
2
[root@nixos:/etc/nixos]# nix-channel  --list
nixos https://nixos.org/channels/nixos-unstable

然后使用 nix-channel --remove <name> 移除你不需要的源。

要启用 flake 支持,需要在 configuration.nix 里面添加 (实际上只要 flakes 那行,我当时把 experimental 写成了 experiment 导致疯狂报错)

1
2
3
{ pkgs, ... }: {
nix.settings.experimental-features = [ "nix-command" "flakes" ];
}

然后创建 /etc/nixos/flake.nix

附录

Nix 常用命令

  • nixos-rebuild switch: 修改完配置后,使配置生效

  • nixos-rebuild test: 修改完配置后,使配置生效,但是不将它设置为默认启动项

  • nixos-rebuild boot: 修改完配置后,将它设置为默认启动项,(但是要下次启动才生效,不立即生效)

  • nixos-rebuild switch -p test: 使配置立即生效并将修改完的配置加入到 grub 选项并命名为 test.

  • nixos-rebuild build: 测试配置能否通过构建(但是并不切换到该配置)

参考资料