NixOS 的核心思想
NixOS 是将 Nix 哲学应用到整个操作系统的结果。传统 Linux 配置散落在 /etc 的数百个文件中,系统状态是通过执行一系列命令逐步累积形成的——难以复现,难以追踪。
NixOS 将系统配置集中到 /etc/nixos/configuration.nix 一个文件中(可以模块化拆分)。nixos-rebuild switch 原子化地将系统切换到配置所描述的精确状态,任何失败都可以立即回滚。
NixOS 工作原理
────────────────────────────────────────────────────
/etc/nixos/configuration.nix
│ nixos-rebuild switch
▼
Nix 评估配置 → 构建所有需要的包 → 生成新 generation
│
▼
原子切换(符号链接更新)
├── /run/current-system → /nix/store/new-generation/
├── /etc/ 配置文件更新
└── systemd 服务状态同步
│
▼ (如果出错)
nixos-rebuild switch --rollback
└── 回到上一 generation(几秒内完成)
NixOS 安装概览
# 1. 从 nixos.org 下载 ISO 镜像,制作启动盘后引导
# 2. 分区(UEFI 示例)
parted /dev/sda -- mklabel gpt
parted /dev/sda -- mkpart ESP fat32 1MB 512MB
parted /dev/sda -- set 1 esp on
parted /dev/sda -- mkpart primary ext4 512MB 100%
# 3. 格式化
mkfs.fat -F 32 -n boot /dev/sda1
mkfs.ext4 -L nixos /dev/sda2
# 4. 挂载
mount /dev/disk/by-label/nixos /mnt
mkdir -p /mnt/boot
mount /dev/disk/by-label/boot /mnt/boot
# 5. 生成初始配置
nixos-generate-config --root /mnt
# 生成 /mnt/etc/nixos/configuration.nix 和 hardware-configuration.nix
# 6. 编辑配置(见下文),然后安装
nixos-install
# 7. 设置 root 密码,重启
reboot
configuration.nix 结构详解
# /etc/nixos/configuration.nix
# 这是一个接受 { config, pkgs, ... } 参数的函数
{ config, pkgs, ... }:
{
# ── 基础设置 ──────────────────────────────
system.stateVersion = "24.05"; # 不要随意修改!
# 主机名
networking.hostName = "my-nixos";
# 时区
time.timeZone = "Asia/Shanghai";
# 语言
i18n.defaultLocale = "zh_CN.UTF-8";
# ── 引导器 ────────────────────────────────
# systemd-boot(UEFI,推荐)
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# 或者使用 GRUB(传统 BIOS)
# boot.loader.grub.enable = true;
# boot.loader.grub.device = "/dev/sda";
# ── 网络 ──────────────────────────────────
networking.networkmanager.enable = true; # 桌面推荐
# 或:networking.useDHCP = true; # 服务器推荐
# ── 系统全局软件包 ────────────────────────
environment.systemPackages = with pkgs; [
vim
git
curl
wget
htop
tmux
ripgrep
fd
];
# ── 用户配置 ──────────────────────────────
users.users.alice = {
isNormalUser = true;
description = "Alice";
extraGroups = [ "wheel" "networkmanager" "docker" ];
shell = pkgs.zsh;
# 初始密码(用 mkpasswd 生成哈希)
hashedPassword = "$6$...";
# 或:直接使用明文(不安全,仅用于初始设置)
# initialPassword = "changeme";
};
# 允许 wheel 组 sudo
security.sudo.enable = true;
# ── 常用服务 ──────────────────────────────
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false; # 只允许密钥认证
};
};
# ── Nix 设置 ──────────────────────────────
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# ── 防火墙 ────────────────────────────────
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [ 22 80 443 ];
}
应用配置:nixos-rebuild
# 切换到新配置(立即生效,更新引导项)
sudo nixos-rebuild switch
# 切换但不更新引导默认项(仍可从引导菜单选择旧版本)
sudo nixos-rebuild test
# 只构建,不切换(验证配置语法和依赖)
sudo nixos-rebuild build
# 构建并在 VM 中测试(不影响真实系统)
sudo nixos-rebuild build-vm
./result/bin/run-*-vm # 启动测试 VM
# 回滚到上一个 generation
sudo nixos-rebuild switch --rollback
# 查看所有 generation
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
# 输出示例:
# 1 2024-01-01 12:00:00
# 2 2024-01-15 09:30:00
# 3 2024-02-01 14:22:00 (current)
# 切换到特定 generation
sudo nix-env --switch-generation 2 --profile /nix/var/nix/profiles/system
sudo /nix/var/nix/profiles/system-2-link/bin/switch-to-configuration switch
从零配置一台开发机
以下是一个完整的开发机 configuration.nix 示例:
{ config, pkgs, ... }:
{
system.stateVersion = "24.05";
networking.hostName = "dev-machine";
time.timeZone = "Asia/Shanghai";
# UEFI 引导
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# 网络
networking.networkmanager.enable = true;
# 开发工具
environment.systemPackages = with pkgs; [
# 终端工具
vim neovim git curl wget htop tmux zsh fzf
ripgrep fd bat eza delta
# 开发语言
python311 nodejs_20 go rustup
# 容器
docker docker-compose
# 实用工具
jq yq httpie direnv nix-direnv
];
# 服务
services.openssh.enable = true;
virtualisation.docker.enable = true;
# Zsh 为系统默认 Shell
programs.zsh.enable = true;
# 用户
users.users.dev = {
isNormalUser = true;
extraGroups = [ "wheel" "docker" "networkmanager" ];
shell = pkgs.zsh;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3... user@host"
];
};
# Nix 配置
nix = {
settings.experimental-features = [ "nix-command" "flakes" ];
gc.automatic = true;
gc.dates = "weekly";
gc.options = "--delete-older-than 14d";
};
# 防火墙
networking.firewall.allowedTCPPorts = [ 22 ];
}
将配置纳入 Git 版本控制
强烈建议将 /etc/nixos/ 目录(或其中的配置文件)纳入 Git 仓库:
cd /etc/nixos && git init && git add . && git commit -m "Initial NixOS config"
这样每次配置变更都有记录,可以随时查看差异(git diff)、回溯历史配置(git log),甚至在多台机器间同步配置。
stateVersion 不要随意修改
system.stateVersion 不是 NixOS 的版本,而是"系统状态初始化时的版本"。修改它可能导致某些服务配置升级脚本被跳过或重复执行。安装时生成什么值就保持什么值,即使升级 NixOS 版本也不需要修改。
本章小结
NixOS 的革命性在于将系统管理从"执行命令积累状态"变成"声明目标状态"。configuration.nix 是系统的唯一事实来源,nixos-rebuild switch 原子化实现目标状态,任何时候都可以回滚。下一章深入 NixOS 模块系统,学习如何配置更复杂的服务。