0%

如何在VPS上使用NixOS

NixOS 是一种基于声明式配置的操作系统, 只需通过一个配置文件即可完成整个系统的搭建, 非常适合用于 VPS 的环境配置. 我会在这里记录我安装 NixOS 并在上面搭起这个博客的全过程.

分区

按照惯例调整启动顺序,先进入 Live CD, 然后分区. UEFI启动方式和BIOS启动方式的分区方法略有不同, 因此您需要检查 UEFI 是否真正启用:

1
ls /sys/firmware/efi/efivars

alt text
文件或目录不存在说明这台机器是BIOS启动, 如果使用GPT需要包含一个BIOS Boot 分区(fdisk代号编码 EF02). 此分区至少需要1M空间, 只要建立并给出分区标识即可, 不需要多余操作:

分区号 挂载点 文件系统 代号编码 大小
1 - - EF02 1M
2 /boot fat32 EF00 256M
3 / btrfs 8300 剩余空间
4 SWAP - 8200 8G

使用任何一个分区工具创建即可, 根据ArchWiki这份分区表事实上可以在任意地方启动, 但是我没有试过.
接下来创建btrfs子卷并挂载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sudo -i

# 创建btrfs子卷
mount /dev/vda3 /mnt &&
btrfs subvolume create /mnt/root &&
btrfs subvolume create /mnt/home &&
btrfs subvolume create /mnt/nix &&
umount /mnt

# 挂载
mount -o compress=zstd,subvol=root /dev/vda3 /mnt &&
mkdir /mnt/{home,nix,boot} &&
mount -o compress=zstd,subvol=home /dev/vda3 /mnt/home &&
mount -o compress=zstd,noatime,subvol=nix /dev/vda3 /mnt/nix &&
mount /dev/vda2 /mnt/boot &&
swapon /dev/vda4

网络

VPS常常使用静态IP, 所以需要临时配置Live CD的IP地址才能联网:

1
2
3
4
5
# network connet
ip addr add xxx.xxx.xxx.xxx/24 dev ens3 && # 换成您的IP地址
ip route add default via xxx.xxx.xxx.1 && # 换成您的网关
ip addr del yyy.yyy.yyy.yyy/16 dev ens3 &&
echo "nameserver 8.8.8.8" | tee -a /etc/resolv.conf # 临时配置DNS

配置文件

以下指令会根据您当前的硬件配置自动生成 hardware-configuration.nix 和 configuration.nix

1
nixos-generate-config --root /mnt

首先看到 configuration.nix, 在您引入 Flakes 或者 Home Manager 之前大部分配置一个都在这个文件中, hardware-configuration.nix 也会引入到 configuration.nix 中, 但是 hardware-configuration.nix 一般而言只关于硬件,所以几乎不修改.
由于nixos-cn和其他安装Nixos的教程给出关于这两个文件的配置的介绍已经足够多了,我在这里直接贴出我的配置以供参考.

configuration.nix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{ config, pkgs, ... }:
{
imports =
[
./hardware-configuration.nix
./users.nix
./network.nix
./services.nix
];
boot.loader = {
grub = {
enable = true;
device = "/dev/vda";
useOSProber = false;
extraConfig = ''
set timeout=5
set timeout_style=menu
'';
};
};
services.xserver.enable = false;
boot.kernelPackages = pkgs.linuxPackages_zen;
time.timeZone = "Asia/Shanghai";
i18n.defaultLocale = "en_US.UTF-8";
system.stateVersion = "24.11";
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
}

hardware-configuration.nix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# Do not modify this file!  It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:

{
imports =
[
(modulesPath + "/profiles/qemu-guest.nix")
];

boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ];
boot.initrd.kernelModules = [ "virtio_net" "virtio_scsi" ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];

fileSystems."/" =
{
device = "/dev/disk/by-uuid/y";
fsType = "btrfs";
options = [ "subvol=root" "compress=zstd" ];
};

fileSystems."/home" =
{
device = "/dev/disk/by-uuid/y";
fsType = "btrfs";
options = [ "subvol=home" "compress=zstd" ];
};

fileSystems."/nix" =
{
device = "/dev/disk/by-uuid/y";
fsType = "btrfs";
options = [ "subvol=nix" "compress=zstd" "noatime" ];
};

fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/z";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};

swapDevices =
[{ device = "/dev/disk/by-uuid/x"; }];

# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
# networking.useDHCP = lib.mkDefault true;
# networking.interfaces.ens3.useDHCP = lib.mkDefault true;

nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

users.nix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{ config, pkgs, ... }:
{
imports = [ ];
users.defaultUserShell = pkgs.zsh;
users.users = {
beis = {
isNormalUser = true;
home = "/home/beis";
extraGroups = [ "wheel" "networkmanager" "nix" ];
openssh.authorizedKeys.keys = [ "ssh-rsa x" ];
};
};
}

network.nix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{ config, pkgs, ... }:
{
networking = {
networkmanager.enable = true;
interfaces.ens3 = {
ipv4.addresses = [
{
address = "xxx.xxx.xxx.xxx";
prefixLength = 24;
}
];
ipv6.addresses = [{
address = "x";
prefixLength = 48;
}];
};
defaultGateway = {
address = "xxx.xxx.xxx.1";
interface = "ens3";
};
defaultGateway6 = {
address = "x";
interface = "ens3";
};
nameservers = [ "8.8.8.8" "8.8.4.4" ];
hostName = "nixos";
};
networking.firewall = {
enable = true;
allowedTCPPorts = [ 80 443 ];
};
}

services.nix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
vim
curl
wget
aria2
python39
zsh
git
neofetch
(pkgs.rsync.overrideAttrs (old: {
version = "3.4.1";
src = pkgs.fetchurl {
url = "https://download.samba.org/pub/rsync/rsync-3.4.1.tar.gz";
sha256 = "0llcv1gxcl4qyry689sh24mj02pyy2wl1xq1q4gmb2zdl6rvq919";
};
dontPatch = true;
}))
];

services.openssh = {
enable = true;
ports = [ x ]; # 换成无符号整数的端口号
settings = {
PasswordAuthentication = false;
PermitRootLogin = "prohibit-password";
};
};
programs.zsh = {
enable = true;
};
imports = [
(fetchTarball "https://github.com/nix-community/nixos-vscode-server/tarball/master")
];
services.vscode-server.enable = true;
services.nginx = {
enable = true; # 启用 Nginx 服务
virtualHosts."blog.mofish.cafe" = {
enableACME = true;
forceSSL = true;
root = "/hexo"; # 通过rsync和scp同步blog内容

};
};
security.acme.acceptTerms = true;
security.acme.certs = {
"blog.mofish.cafe".email = "[email protected]";
};
}

配置文件写好后即可运行nixos-install以安装系统.
请注意, 如果您的VPS内存较少, 请务必挂上swap分区再运行此命令, 否则容易卡死.
运行完成后可以运行nixos-enter进入您的系统shell, 也可以直接重启检查安装是否成功.

参考