Chapter 10

多机器管理与高级实践

用一个 Git 仓库管理所有机器的 NixOS 配置——从单台服务器到整个集群

多机器配置的组织结构

管理多台 NixOS 机器时,最佳实践是用一个 Git 仓库存放所有配置,每台机器是 nixosConfigurations 中的一个条目:

nixos-config 仓库结构 ────────────────────────────────────────────────── flake.nix ← 入口,定义所有机器 flake.lock ├── hosts/ │ ├── webserver/ │ │ ├── default.nix ← webserver 专用配置 │ │ └── hardware-configuration.nix │ ├── dev-machine/ │ │ └── default.nix │ └── builder/ │ └── default.nix ├── modules/ │ ├── common.nix ← 所有机器共享配置 │ ├── server.nix ← 服务器通用配置 │ └── desktop.nix ← 桌面通用配置 ├── home/ │ ├── alice.nix ← alice 的 Home Manager 配置 │ └── bob.nix └── secrets/ ← sops-nix 加密文件 └── secrets.yaml
# flake.nix — 多机器配置
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
    home-manager = {
      url = "github:nix-community/home-manager/release-24.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    sops-nix = {
      url = "github:Mic92/sops-nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, home-manager, sops-nix, ... }: {
    nixosConfigurations = {
      # Web 服务器
      webserver = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ./modules/common.nix
          ./modules/server.nix
          ./hosts/webserver
          sops-nix.nixosModules.sops
        ];
      };

      # 开发机
      dev-machine = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ./modules/common.nix
          ./modules/desktop.nix
          ./hosts/dev-machine
          home-manager.nixosModules.home-manager
          { home-manager.users.alice = import ./home/alice.nix; }
        ];
      };
    };
  };
}

deploy-rs — 远程部署 NixOS

deploy-rs 是一个 Rust 编写的 NixOS 远程部署工具,可以将本地构建的系统配置部署到远程机器:

# flake.nix — 添加 deploy-rs
{
  inputs.deploy-rs.url = "github:serokell/deploy-rs";

  outputs = { self, nixpkgs, deploy-rs, ... }: {
    # ... nixosConfigurations ...

    # deploy-rs 部署节点配置
    deploy.nodes = {
      webserver = {
        hostname = "192.168.1.100";   # 或域名
        profiles.system = {
          sshUser = "root";
          path = deploy-rs.lib.x86_64-linux.activate.nixos
            self.nixosConfigurations.webserver;
        };
      };
    };

    # 让 nix flake check 也验证 deploy 配置
    checks = builtins.mapAttrs
      (system: deployLib: deployLib.deployChecks self.deploy)
      deploy-rs.lib;
  };
}
# 部署到所有节点
nix run github:serokell/deploy-rs -- .

# 部署到指定节点
nix run github:serokell/deploy-rs -- .#webserver

# 部署前先 dry-run(不实际切换,只构建)
nix run github:serokell/deploy-rs -- --dry-activate .#webserver

nixos-anywhere — 远程全新安装

nixos-anywhere 可以通过 SSH 连接到一台目标机器,自动分区、格式化并安装 NixOS——无需手动操作目标机器:

# 前提:目标机器已在任意 Linux 系统下运行(live CD 或现有系统)
# 需要 root SSH 访问

# 安装到目标机器
nix run github:nix-community/nixos-anywhere -- \
  --flake .#webserver \
  root@192.168.1.100

# 使用自定义磁盘配置(disko)
nix run github:nix-community/nixos-anywhere -- \
  --flake .#webserver \
  --disk-encryption-keys /tmp/luks.key \
  root@target-machine

colmena — 多机器管理

colmena 是专为大规模 NixOS 集群设计的部署工具,支持标签过滤、并行部署:

# colmena.nix(或 flake.nix 中的 colmena 输出)
{
  meta = {
    nixpkgs = import <nixpkgs> {};
  };

  # 所有机器共享的配置
  defaults = { pkgs, ... }: {
    environment.systemPackages = [ pkgs.vim pkgs.git ];
  };

  webserver-01 = { name, nodes, ... }: {
    deployment.targetHost = "10.0.0.1";
    deployment.tags = [ "web" "production" ];
    services.nginx.enable = true;
  };

  webserver-02 = { ... }: {
    deployment.targetHost = "10.0.0.2";
    deployment.tags = [ "web" "production" ];
    services.nginx.enable = true;
  };

  database = { ... }: {
    deployment.targetHost = "10.0.0.3";
    deployment.tags = [ "db" "production" ];
    services.postgresql.enable = true;
  };
}
# 部署所有机器
colmena apply

# 只部署 web 标签的机器
colmena apply --on '@web'

# 并行部署,最多 3 台同时
colmena apply --parallel 3

# 构建但不部署(检查配置)
colmena build

sops-nix — 加密管理 Secrets

数据库密码、API Key 等敏感信息不能明文写入 Nix 配置(会进入 /nix/store,可被任何用户读取)。sops-nix 使用 age 或 GPG 加密管理这些 secrets:

# 安装 sops 和 age
nix profile install nixpkgs#sops nixpkgs#age

# 生成 age 密钥对
age-keygen -o ~/.config/sops/age/keys.txt
# 输出:Public key: age1xxxxxx...

# 获取主机 SSH 公钥(NixOS 会用此密钥解密)
ssh-keyscan my-server | ssh-to-age
# 输出:age1xxxxxx...
# .sops.yaml — 配置哪些密钥可以解密哪些文件
creation_rules:
  - path_regex: secrets/.*\.yaml$
    age: |
      age1xxxxxx...   # 你的管理员密钥
      age1yyyyyy...   # 服务器的 age 密钥(从 SSH 公钥转换)
# 创建加密 secrets 文件
sops secrets/secrets.yaml
# 打开编辑器,输入内容(YAML 格式):
# database_password: my-secret-password
# api_key: sk-xxxx...
# 保存后自动加密

# 查看/编辑 secrets
sops secrets/secrets.yaml
# NixOS configuration — 使用 sops-nix
{ config, ... }:

{
  imports = [ <sops-nix/modules/sops> ];

  sops = {
    # age 密钥文件(在机器上)
    age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
    age.keyFile = "/var/lib/sops-nix/key.txt";

    # 声明要使用的 secrets
    secrets."database_password" = {
      sopsFile = ./secrets/secrets.yaml;
      owner = "myapp";    # 文件所有者
      mode = "0400";      # 只有所有者可读
    };
  };

  # 在服务配置中使用(路径会在运行时被解密内容填充)
  systemd.services.myapp.environment.DATABASE_PASSWORD_FILE =
    config.sops.secrets."database_password".path;
    # 值为 /run/secrets/database_password(启动时由 sops 解密填充)
}

系统回滚

# 查看系统 generations
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system

# 从命令行回滚(立即切换)
sudo nixos-rebuild switch --rollback

# 从引导菜单回滚(无需 SSH,适合系统无法启动的情况)
# 重启时在 GRUB/systemd-boot 菜单选择旧的 generation

# 手动切换到特定 generation
sudo nix-env --switch-generation 5 --profile /nix/var/nix/profiles/system
sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch

学习路径规划

Nix 的学习曲线较陡,以下是推荐的渐进式路径:

第1步

nix-shell / nix develop(1-2周)

从开发环境开始——为现有项目写一个 shell.nix 或 flake.nix devShell,体验隔离依赖的价值。配合 direnv,实现进目录自动激活。

第2步

Flakes(1-2周)

将开发环境迁移到 Flakes,理解 inputs/outputs/flake.lock。开始为项目构建产物和 Docker 镜像。

第3步

Home Manager(1-2周)

在 macOS 或 Linux 上用 Home Manager 管理 dotfiles。不需要 NixOS 就能体验声明式用户环境的好处。

第4步

NixOS(长期)

在虚拟机中安装 NixOS,从零配置一台开发机。理解模块系统,逐步将配置模块化,加入 secrets 管理。

第5步

多机器管理(进阶)

用单个 flake.nix 管理多台 NixOS 机器,引入 deploy-rs 或 colmena 自动化部署,用 sops-nix 管理 secrets。

社区资源

nix.dev
Nix 官方推荐的学习网站,包含教程、指南和最佳实践。Zero to Nix 是入门的绝佳起点。
NixOS Wiki
wiki.nixos.org — 社区维护的 NixOS 配置参考,几乎所有你想配置的服务都能找到示例。
search.nixos.org
在线搜索 Nixpkgs 包和 NixOS 选项,可以按稳定版/unstable 切换,是日常使用的必备书签。
NixOS Discourse
discourse.nixos.org — 官方论坛,遇到问题可以在这里提问,社区响应很积极。
nix-community GitHub
github.com/nix-community — Home Manager、fenix(Rust)、nix-direnv 等大量高质量社区工具的集合地。
Nixpkgs 源码
github.com/NixOS/nixpkgs — 直接阅读 Nixpkgs 中的包定义和 NixOS 模块源码,是理解高级用法的最佳教材。
全教程总结

Nix 的本质是一个一致性保证系统:从开发环境(nix shell)到应用包(derivation)到整个操作系统(NixOS),再到 CI/CD 构建(nix build)和 Docker 镜像(dockerTools),Nix 在每一个层面都提供"相同输入永远产生相同输出"的保证。这不只是工具的选择,更是思维方式的转变——从命令式的"执行这些步骤"到声明式的"我想要这个状态"。学习 Nix 有一定成本,但一旦掌握,你的开发和运维效率将得到质的提升。