1. NixOS 的设计哲学
NixOS 与其他 Linux
发行版最根本的区别在于它是完全声明式的。传统的 Linux 系统是通过一系列命令和文件编辑逐步构建的,系统状态是命令序列的累积结果。而 NixOS 将系统的所有配置集中在 configuration.nix 中——这个文件描述了整个系统的"目标状态",NixOS 通过评估这个文件并将系统推进到该状态来工作。
这种设计带来了几个革命性的优势:
- 版本控制:整个系统配置是单个文件(或多个导入的文件),可以使用 Git 管理
- 原子升级:系统升级要么全部成功,要么回滚到之前的状态,永远不会处于半升级状态
- 可复现:从
configuration.nix+hardware-configuration.nix可以在任何兼容硬件上重建完全相同的系统 - 多配置并存:可以在引导菜单中选择不同的系统配置(称为 generation)
- 回滚安全:如果新配置导致系统无法启动,可以在启动时选择旧配置
2. configuration.nix 结构
2.1 基础配置框架
# /etc/nixos/configuration.nix
{ config, pkgs, lib, ... }:
{
# 引入硬件配置(由 nixos-generate-config 生成)
imports = [
./hardware-configuration.nix
./network-configuration.nix
./services-configuration.nix
];
# 引导配置
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# 内核
boot.kernelPackages = pkgs.linuxPackages_latest;
# 主机名
networking.hostName = "my-nixos-server";
# 时区
time.timeZone = "Asia/Shanghai";
# 国际化
i18n.defaultLocale = "zh_CN.UTF-8";
# 用户配置
users.users.alice = {
isNormalUser = true;
home = "/home/alice";
description = "Alice";
extraGroups = [ "wheel" "networkmanager" "docker" ];
shell = pkgs.zsh;
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3... alice@example.com"
];
};
# root 密码(建议使用 hashedPasswordFile 更安全)
users.users.root.hashedPassword = "$6$rounds=500000$...";
# 系统级包
environment.systemPackages = with pkgs; [
vim
git
htop
curl
wget
];
# 启用 Nix Flakes
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# 系统状态版本(不要修改!用于向后兼容)
system.stateVersion = "24.05";
}
2.2 硬件配置
hardware-configuration.nix 由安装程序自动生成,包含设备特定的配置:
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
# 文件系统挂载
fileSystems."/" = {
device = "/dev/disk/by-uuid/abc123-456";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/DEF-456";
fsType = "vfat";
options = [ "fmask=0022" "dmask=0022" ];
};
# 交换分区
swapDevices = [
{ device = "/dev/disk/by-uuid/swap-uuid"; }
];
# 内核模块
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" ];
boot.kernelModules = [ "kvm-intel" "v4l2loopback" ];
boot.extraModulePackages = [ ];
}
3. 网络配置
3.1 基础网络
{
# DHCP 自动获取
networking.useDHCP = true;
# 或者静态 IP
networking.interfaces.eth0 = {
useDHCP = false;
ipv4.addresses = [{
address = "192.168.1.100";
prefixLength = 24;
}];
};
networking.defaultGateway = "192.168.1.1";
networking.nameservers = [ "8.8.8.8" "8.8.4.4" ];
# 防火墙
networking.firewall = {
enable = true;
allowedTCPPorts = [ 22 80 443 ];
allowedUDPPorts = [ 53 ];
# 允许从特定来源访问
extraCommands = ''
iptables -A INPUT -s 10.0.0.0/8 -p tcp --dport 5432 -j ACCEPT
'';
};
}
3.2 高级网络
{
# 网桥配置
networking.bridges.br0.interfaces = [ "eth0" "eth1" ];
networking.interfaces.br0 = {
ipv4.addresses = [{
address = "10.0.0.1";
prefixLength = 24;
}];
};
# VLAN
networking.vlans.vlan10 = {
id = 10;
interface = "eth0";
};
# WireGuard VPN
networking.wireguard.interfaces.wg0 = {
ips = [ "10.100.0.2/24" ];
listenPort = 51820;
privateKeyFile = "/etc/wireguard/private-key";
peers = [{
publicKey = "abc123...";
allowedIPs = [ "10.100.0.0/24" ];
endpoint = "vpn.example.com:51820";
persistentKeepalive = 25;
}];
};
# 网络管理器(桌面系统用)
networking.networkmanager.enable = true;
}
4. 服务管理
4.1 SSH 服务
{
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
PubkeyAuthentication = true;
};
ports = [ 22 ];
};
}
4.2 Web 服务器(Nginx)
{ config, pkgs, ... }:
{
services.nginx = {
enable = true;
# 全局配置
recommendedGzipSettings = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
# 虚拟主机
virtualHosts = {
"example.com" = {
enableACME = true; # 自动 Let's Encrypt 证书
forceSSL = true; # 强制 HTTPS
locations."/" = {
proxyPass = "http://localhost:8080";
proxyWebsockets = true;
};
};
"static.example.com" = {
root = "/var/www/static";
locations."/" = {
extraConfig = ''
add_header Cache-Control "public, max-age=31536000";
'';
};
};
};
};
# ACME(证书自动管理)
security.acme = {
acceptTerms = true;
defaults.email = "admin@example.com";
};
}
4.3 数据库
{
# PostgreSQL
services.postgresql = {
enable = true;
package = pkgs.postgresql_15;
dataDir = "/var/lib/postgresql/15";
ensureDatabases = [ "myapp" ];
ensureUsers = [{
name = "myuser";
ensureDBOwnership = true;
}];
settings = {
max_connections = 200;
shared_buffers = "2GB";
};
};
# Redis
services.redis.servers.default = {
enable = true;
bind = "127.0.0.1";
port = 6379;
};
# MySQL/MariaDB
services.mysql = {
enable = true;
package = pkgs.mariadb;
ensureDatabases = [ "myapp" ];
ensureUsers = [{
name = "myuser";
ensurePermissions = {
"myapp.*" = "ALL PRIVILEGES";
};
}];
};
}
4.4 容器(Docker/Podman)
{
# Docker
virtualisation.docker = {
enable = true;
autoPrune = {
enable = true;
dates = "weekly";
};
};
# Podman(无守护进程,更安全)
virtualisation.podman = {
enable = true;
dockerCompat = true; # 提供 docker 命令兼容
};
# 用户组
users.extraGroups.docker.members = [ "alice" ];
}
4.5 定时任务
{
# systemd timer(替代 cron)
systemd.services.backup-mysql = {
description = "Backup MySQL databases";
serviceConfig = {
Type = "oneshot";
User = "root";
ExecStart = pkgs.writeShellScript "backup-mysql" ''
${pkgs.mariadb}/bin/mysqldump --all-databases > /backup/mysql-$(date +%Y%m%d).sql
'';
};
};
systemd.timers.backup-mysql = {
description = "Run MySQL backup daily";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
};
};
}
5. 系统重建
5.1 重建命令
# 测试配置是否正确(不实际应用)
sudo nixos-rebuild test
# 应用配置并使其持久化(推荐)
sudo nixos-rebuild switch
# 构建但不激活(用于检查)
sudo nixos-rebuild build
# 从 Flake 构建
sudo nixos-rebuild switch --flake /etc/nixos#my-host
# 回滚到上一个 generation
sudo nixos-rebuild switch --rollback
# 列出所有 generation
sudo nixos-rebuild list-generations
# 从特定 generation 启动(需要重启)
sudo nixos-rebuild boot --flake /etc/nixos#my-host
5.2 Generation 管理
每次 nixos-rebuild switch 都会创建一个新的 generation:
# 查看所有 generation
nixos-rebuild list-generations
# 删除旧 generation(保留最近 10 个)
nix-collect-garbage --delete-older-than 30d
# 保留特定的 generation
sudo nix-env --profile /nix/var/nix/profiles/system --delete-generations +10
# 启动时按 e 编辑引导条目
# 选择不同的 generation 启动
6. 模块化配置
6.1 拆分配置文件
大型系统的 configuration.nix 会变得非常长。使用模块系统拆分:
/etc/nixos/
├── configuration.nix # 主配置,导入其他模块
├── hardware-configuration.nix # 硬件配置(自动生成)
├── modules/
│ ├── networking.nix # 网络配置模块
│ ├── services/
│ │ ├── web.nix # Web 服务器
│ │ ├── database.nix # 数据库服务
│ │ └── monitoring.nix # 监控服务
│ ├── users.nix # 用户配置
│ └── security.nix # 安全设置
└── flake.nix # Flake 配置(如果使用)
# /etc/nixos/configuration.nix
{ config, pkgs, lib, ... }:
{
imports = [
./hardware-configuration.nix
./modules/networking.nix
./modules/users.nix
./modules/security.nix
./modules/services/web.nix
./modules/services/database.nix
];
# 全局配置...
system.stateVersion = "24.05";
}
6.2 条件模块
# modules/services/monitoring.nix
{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.my.monitoring;
in
{
options.my.monitoring = {
enable = mkEnableOption "monitoring stack";
prometheus.enable = mkOption {
type = types.bool;
default = true;
};
grafana.enable = mkOption {
type = types.bool;
default = true;
};
};
config = mkIf cfg.enable {
services.prometheus = mkIf cfg.prometheus.enable {
enable = true;
scrapeConfigs = [{
job_name = "node";
static_configs = [{
targets = [ "localhost:9100" ];
}];
}];
};
services.grafana = mkIf cfg.grafana.enable {
enable = true;
settings.server.http_port = 3000;
};
};
}
6.3 使用条件模块
# /etc/nixos/configuration.nix
{
imports = [ ./modules/monitoring.nix ];
my.monitoring = {
enable = true;
prometheus.enable = true;
grafana.enable = true;
};
}
7. 系统级包与配置
7.1 环境配置
{
# 系统 PATH 中的包
environment.systemPackages = with pkgs; [
vim
git
htop
tcpdump
iotop
];
# 环境变量
environment.variables = {
EDITOR = "vim";
PAGER = "less";
MY_APP_CONFIG = "/etc/myapp/config.json";
};
# /etc 中的文件
environment.etc."myapp/config.json".text = ''
{
"database": {
"host": "localhost",
"port": 5432
}
}
'';
# 或者从文件读取
environment.etc."nginx/nginx.conf".source = ./nginx/nginx.conf;
}
7.2 字体与桌面
{
# 字体配置
fonts.packages = with pkgs; [
noto-fonts
noto-fonts-cjk # 中日韩文字
noto-fonts-emoji # emoji
fira-code # 编程字体
];
# 桌面环境
services.xserver = {
enable = true;
displayManager.gdm.enable = true;
desktopManager.gnome.enable = true;
};
# 或者 KDE Plasma
services.displayManager.sddm.enable = true;
services.desktopManager.plasma6.enable = true;
}
8. 总结
NixOS 的声明式配置管理重新定义了系统管理的方式:
| 操作 | 传统 Linux | NixOS |
|---|---|---|
| 安装软件 | apt install | 在 configuration.nix 中添加 |
| 配置服务 | systemctl enable + 编辑配置文件 | 在 configuration.nix 中声明 |
| 系统升级 | apt upgrade(可能中途失败) | nixos-rebuild switch(原子操作) |
| 回滚 | 手动恢复备份或重新安装 | 启动时选择旧 generation |
| 复制系统 | 手动复刻所有步骤 | 复制 configuration.nix + rebuild |
| 版本控制 | 不直接支持 | 完整的 Git 版本控制 |
对于运维工程师和系统管理员,NixOS 提供了一种全新的工作方式:将系统视为代码,用版本控制管理变更,享受可复现性和原子升级带来的安全感。
NixOS 系统代际与回滚
NixOS 的每次 nixos-rebuild switch 都创建一个新的系统代际(generation):
# 查看所有代际
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
# 输出示例:
# 1 2024-01-01 ...
# 2 2024-02-15 ... ← 当前
# 3 2024-03-01 ...
# 回滚到第 1 代
sudo nix-env --switch-generation 1 --profile /nix/var/nix/profiles/system
# 启动时按空格进入 GRUB 菜单,选择任意历史代际
原子升级保证:如果
nixos-rebuild switch中途失败(如电源中断),系统仍保持原代际可用。这不是「回滚」,而是「从未切换到新版本」。
命令式修改的陷阱:NixOS 鼓励纯声明式管理,但手动修改 /etc 文件或运行 nix-env -iA 安装包会破坏声明式一致性。建议:
- 禁止在
/etc直接修改(除 NixOS 生成的链接外) - 禁止
nix-env命令安装包(应写入configuration.nix) - 使用
nixos-rebuild switch作为唯一变更入口
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。