NixOS 快速使用
本文面向一定命令行基础的人食用。
NixOS & Nix
NixOS 作为不变性系统,设计宗旨是为了保证软件包构建结果统一,为了做到这一点,每个软件包的构建过程都被认为是一个纯函数,该软件包构建过程的所有依赖为函数输入,Nix通过对这些输入计算哈希,通过哈希区分不同版本依赖软件包。
这也奠定了其 /nix/store 下放置所有文件,其他文件均以链接方式存在的基础,并且提供了难以想象的自由度。
系统安装
下载 https://nixos.org/ ,引导后连接网络。
更换 channel
sudo -i
nix-channel --add https://mirrors.ustc.edu.cn/nix-channels/nixpkgs-unstable nixpkgs # 订阅镜像仓库频道
nix-channel --add https://mirrors.ustc.edu.cn/nix-channels/nixos-24.05 nixos # 请注意系统版本
nix-channel --list # 列出频道
nix-channel --update # 更新并解包频道
nixos-rebuild --option substituters "https://mirror.ustc.edu.cn/nix-channels/store" switch --upgrade # 临时切换二进制缓存源,并更新生成
建议均使用 unstable 。
分区
/boot 和 根目录必须有,其他任意。
然后挂载到 /mnt 相应位置
生成配置并部署
nixos-generate-config --root /mnt
系统内 nixos-help 可查阅文档。
然后我们修改一下配置,使用你常用的编辑器打开 /mnt/etc/nixos/configuration.nix
根据文档把 grub 和 NetWorkManager 先打开。
添加一个非 root 用户。
改完后
sudo nixos-install --option substituters "https://mirror.ustc.edu.cn/nix-channels/store"
最后会提醒你改 root 密码。
可以通过 nixos-enter
进入 chroot 环境更改非 root 用户密码。
然后重启,祈祷开机。
软件安装
你应该已经发现了,向 environment.systemPackages
内加入软件包名字即可安装软件。
然而如何应用更改呢?
在系统内可以用 nixos-rebuild switch
来更改。
接下来我们尝试安装桌面,以 Gnome 为例。
参照 NixOS Manual :
services.xserver.desktopManager.gnome.enable = true;
services.xserver.displayManager.gdm.enable = true;
意味着启动这两个服务,相应软件会自动安装。
rebuild 后就可以看到桌面了。
接下来就可以乱装软件了,可以参照 NixOS wiki , NixOS Manual 进行折腾。
别急,Nix 的功力初见端倪,接下来我们引入两个实验特性 Flakes & Nix Commands
Flakes & Nix Commands
即使此二者仍为实验性质,其已被广泛应用。
Flakes 是取代 channel 的功能,它旨在统一软件包尤其是 nixpkgs
的版本。
这里提到 nixpkgs
是 https://github.com/NixOS/nixpkgs
是 NixOS 及所有软件包的集合,NixOS 的开发都在这里进行。
Flakes 引入了一个 flakes.nix 用于管理所有输入,flakes.lock 以 git commits 和文件 hash 的方式固定版本。
这个特性的引入不仅提高了可复现性,并且可以同时引入多个对象。
我们可以引入 nixpkgs
的不同版本,使得系统中某个软件包停留在这个版本,可以引入其他作者的仓库提供更多软件,并且更新更及时(nixpkgs 审核要时间)。
Flakes 还可以提供不同的配置文件,使不同环境不会互相干扰,并且不用考虑容器化带来的效率问题,因为 Flakes 只需要简单的切换环境变量达到目的。
向 configuration.nix
中加入:
nix.settings.experimental-features = [ "nix-command" "flakes" ];
启用该特性。
为了在系统层面使用 Flakes, 我们引入 flake.nix
文件:
{
description = "Main config";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
};
outputs = { self, nixpkgs, ... }@inputs: {
nixosConfigurations.hostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
];
};
};
}
该文件inputs 中定义了 nixpkgs 的输入来源,一般为 git 仓库,对于 github, gitlab 上的仓库,Nix 使用 HTTP API 进行访问,其余 git 仓库采用 git 进行访问,可引入私有仓库存储敏感信息。
outputs 中则引入了 configuration.nix
作为模块,实际上将该文件放在 /etc/nixos
中,即可实现原来的所有功能,Nix 会自动创建 flake.lock
文件,标识 git 仓库目前所在的 commit
信息,以及文件的哈希以保证可复现性。
nix-command
是采用类似 flakes
all in git 的思想的一套全新命令行工具。
Home Manager
一般来说 /etc/nixos 仅应该存在系统配置,对于用户配置,比如 git 身份,ssh 等应由单独的软件来管理,我们可以采用 nix-community/home-manager
来管理。
我们修改 flake.nix 为如下配置:
{
description = "Main config";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, nixpkgs, ... }@inputs: {
nixosConfigurations.hostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.wxt = import ./home-wxt.nix;
# Optionally, use home-manager.extraSpecialArgs to pass
# arguments to home.nix
}
];
};
};
}
该文件定义了 home-manager 的来源,修改 home-manager 中的输入源和系统相同,若未指定,使用 nix-community/home-manager/flake.lock 中指定的 nixpkgs 版本,可能与系统不用。然后引入 home-manager
作为 NixOS Module 。
接下来我们建立 home-wxt.nix
文件:
{ config, pkgs, neovim-n, ... }:
{
imports = [
];
nixpkgs.config.allowUnfree = true;
home.username = "wxt";
home.homeDirectory = "/home/wxt";
home.packages = with pkgs;[]
# add package here
home.stateVersion = "24.11";
programs.git = {
enable = true;
userName = "wxt";
extraConfig = {
commit = { gpgsign = true; };
};
};
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting.enable = true;
zplug = {
enable = true;
plugins = [
{ name = "sobolevn/wakatime-zsh-plugin"; }
];
};
oh-my-zsh = {
enable = true;
plugins = [ "git" ];
theme = "bira";
};
shellAliases = {
l = "ls -l";
};
history.size = 10000;
history.path = "${config.xdg.dataHome}/zsh/history";
};
programs.home-manager.enable = true;
}
更多用法参见 home-manager 文档:https://nix-community.github.io/home-manager/
(Flakes 其实不止管理系统配置,更可以管理娱乐、工作甚至不同 IDE 的配置,并且不影响全局环境,推荐阅读https://nixos-and-flakes.thiscute.world/zh/nixos-with-flakes/nixos-with-flakes-enabled)
奇技淫巧
非 NixOS 二进制软件
为了保证多版本软件共存,NixOS 不遵守 FHS 规范,导致大部分未经修改的软件无法直接运行,一般情况我们可以启用 nix-ld
提供一部分库链接,很多软件也可以从 nixpkgs
里找到,Nix 在构建时提供了一个 ‘AutopatchelfHook’ 可以在打包软件后自动解决动态库依赖问题。我们也可以优先考虑 flatpak 和 appimage ,其中 appimage 可以使用 appimage-run
运行, 安装 ‘nix-ld’ 后大部分静态编译的程序也可运行。
也可以使用 bwrap
之类的轻量化容器。
以上方法成功率较大并且不复杂。