1. 为什么需要专门的部署工具?
NixOS 的系统重建命令 nixos-rebuild switch 设计初衷是在本地运行。但在以下场景中,需要在远程机器上执行配置更新:
- 服务器集群管理:几十台生产服务器需要统一更新 Nginx 配置或安全补丁
- 边缘节点部署:树莓派集群、IoT 设备需要在不物理接触的情况下更新
- CI/CD 集成:Git 提交后自动部署到测试环境和生产环境
- ** secrets 管理**:配置中包含 API 密钥、证书等敏感数据,需要安全地传递到目标主机
手动 SSH 到每台服务器运行 nixos-rebuild switch 显然不可扩展。Nix 社区开发了多种专用工具来解决这些需求。
2. deploy-rs
deploy-rs 是目前社区最活跃的 NixOS 远程部署工具。它使用 Flakes 管理配置,支持并行部署和自动回滚。
2.1 基本架构
deploy node SSH/activaion target node
(flakes config) ------------------> (remote NixOS)
2.2 flake.nix 配置
# flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
deploy-rs = {
url = "github:serokell/deploy-rs";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, deploy-rs }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
# 通用 NixOS 模块
commonModule = { config, pkgs, ... }: {
nix.settings.experimental-features = [ "nix-command" "flakes" ];
services.openssh.enable = true;
};
in
{
# NixOS 配置
nixosConfigurations = {
web-server = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
commonModule
./hosts/web-server.nix
];
};
database = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
commonModule
./hosts/database.nix
];
};
cache-server = nixpkgs.lib.nixosSystem {
inherit system;
modules = [
commonModule
./hosts/cache-server.nix
];
};
};
# 部署配置
deploy = {
# SSH 连接配置(可选,默认使用 ~/.ssh/config)
sshOpts = [ "-o" "StrictHostKeyChecking=no" ];
nodes = {
web-server = {
hostname = "web1.example.com";
profiles.system = {
user = "root";
path = deploy-rs.lib.${system}.activate.nixos
self.nixosConfigurations.web-server;
};
};
database = {
hostname = "db1.internal";
sshUser = "deploy"; # SSH 登录用户
profiles.system = {
user = "root";
path = deploy-rs.lib.${system}.activate.nixos
self.nixosConfigurations.database;
};
};
cache-server = {
hostname = "192.168.1.50";
profiles.system = {
user = "root";
path = deploy-rs.lib.${system}.activate.nixos
self.nixosConfigurations.cache-server;
};
};
};
};
# deploy-rs 检查
checks = builtins.mapAttrs (system: deploy-rs.lib.${system}.deployChecks) self.deploy;
};
}
2.3 部署命令
# 部署到所有节点
deploy . -- -s
# 部署到特定节点
deploy .#web-server
# 只构建不激活(检查配置是否正确)
deploy . --build-only
# 使用 dry-activate 进行测试
deploy . --dry-activate
# 指定 SSH 密钥
deploy . --ssh-opts "-i /path/to/key"
2.4 自动回滚机制
deploy-rs 的关键特性是激活失败时自动回滚。部署流程如下:
- 构建目标系统配置
- 通过 SSH 将配置传输到目标主机
- 在目标主机上激活新配置(类似
nixos-rebuild switch) - 如果激活失败或健康检查未通过,自动回滚到之前的配置
# 自定义激活检查(可选)
# 在目标主机上执行的脚本,验证服务是否正常运行
profiles.system = {
user = "root";
path = deploy-rs.lib.${system}.activate.nixos self.nixosConfigurations.web-server;
# 激活后检查 Nginx 是否响应
activationScript = ''
#!/usr/bin/env bash
for i in {1..10}; do
if curl -sf http://localhost/health > /dev/null; then
echo "Health check passed"
exit 0
fi
sleep 1
done
echo "Health check failed, rolling back..."
exit 1
'';
};
3. Colmena
Colmena 是另一个流行的部署工具,它更像一个"分布式的 nixos-rebuild"。它使用本地评估并在目标主机上激活。
3.1 hive.nix 配置
Colmena 的核心配置文件是 hive.nix:
# hive.nix
{
meta = {
nixpkgs = import <nixpkgs> { system = "x86_64-linux"; };
nodeNixpkgs = {
# 为特定节点使用不同的 nixpkgs
arm-node = import <nixpkgs> { system = "aarch64-linux"; };
};
nodeSpecialArgs = {
# 传递给每个节点的额外参数
all = { inherit (import ./secrets.nix) apiKey; };
};
};
# 默认配置(应用到所有节点)
defaults = { config, pkgs, ... }: {
# 所有节点的基础配置
nix.settings.experimental-features = [ "nix-command" "flakes" ];
deployment = {
targetHost = null; # 由下面覆盖
targetPort = 22;
targetUser = "root";
buildOnTarget = false; # 在本地构建,然后上传
};
};
# 节点定义
web-server = { config, pkgs, ... }: {
deployment.targetHost = "web1.example.com";
imports = [ ./hosts/web-server.nix ];
services.nginx = {
enable = true;
virtualHosts."example.com" = {
locations."/" = {
proxyPass = "http://localhost:8080";
};
};
};
};
database = { config, pkgs, ... }: {
deployment = {
targetHost = "db1.internal";
targetUser = "admin"; # 使用非 root 用户(需要 sudo)
tags = [ "database" "production" ];
};
imports = [ ./hosts/database.nix ];
services.postgresql = {
enable = true;
package = pkgs.postgresql_15;
ensureDatabases = [ "myapp" ];
};
};
cache-server = { config, pkgs, ... }: {
deployment = {
targetHost = "192.168.1.50";
tags = [ "cache" "internal" ];
};
imports = [ ./hosts/cache-server.nix ];
services.nix-serve = {
enable = true;
secretKeyFile = "/var/cache-priv-key.pem";
};
};
# 树莓派节点(ARM 架构)
arm-node = { config, pkgs, ... }: {
deployment = {
targetHost = "pi-node.local";
targetPort = 2222;
};
# ARM 特定配置
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
};
}
3.2 Colmena 部署命令
# 部署所有节点
colmena apply
# 只部署特定节点
colmena apply --on web-server
colmena apply --on database
# 按标签部署
colmena apply --tag production
colmena apply --tag cache
# 并行部署
colmena apply --parallel 4
# 构建但不激活
colmena apply --build-only
# 评估配置(检查是否有错误)
colmena eval
# 在节点上执行命令
colmena exec --on web-server -- systemctl status nginx
colmena exec --tag database -- psql -l
# 上传文件到节点
colmena upload --on web-server ./local-file /remote/path
# SSH 到节点
colmena ssh web-server
3.3 密钥管理
Colmena 支持在部署时安全地传递 secrets:
# secrets.nix(加密文件,使用 agenix 或 sops-nix)
{
database.password = "secret-password";
api.key = "api-key-value";
}
# hive.nix
{ config, pkgs, secrets, ... }: {
# 使用 secrets 配置服务
services.postgresql.initialScript = pkgs.writeText "init.sql" ''
CREATE USER myuser WITH PASSWORD '${secrets.database.password}';
'';
}
4. NixOps
NixOps 是官方历史最久的部署工具,但目前维护不太活跃。它支持云资源创建(EC2、GCE、Azure 等)和配置管理一体化。
4.1 基本用法
# network.nix
{
network = {
description = "Web application cluster";
enableRollback = true;
};
# 默认配置
defaults = { config, pkgs, ... }: {
services.openssh.enable = true;
networking.firewall.enable = true;
};
web-server = { config, pkgs, nodes, ... }: {
deployment.targetHost = "web1.example.com";
services.nginx.enable = true;
services.nginx.virtualHosts."app.com" = {
locations."/".proxyPass = "http://localhost:3000";
};
};
database = { config, pkgs, nodes, ... }: {
deployment.targetHost = "db1.internal";
services.postgresql.enable = true;
services.postgresql.ensureDatabases = [ "app" ];
};
}
# 创建部署
nixops create network.nix -d production
# 部署
nixops deploy -d production
# 查看状态
nixops info -d production
nixops check -d production
# 回滚
nixops rollback -d production
# 销毁资源
nixops destroy -d production
5. 选择指南
| 工具 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| deploy-rs | 活跃维护,Flakes 原生,自动回滚,并行部署 | 仅支持 NixOS,非官方 | 小型到中型集群,追求简单易用 |
| Colmena | 强大的标签系统,远程命令执行,灵活 | 学习曲线稍高 | 大型集群,需要精细控制 |
| NixOps | 官方工具,支持云资源自动创建 | 维护不活跃,Flakes 支持弱 | 需要自动创建云资源的场景 |
6. Secrets 管理
部署中的一个关键挑战是如何安全地传递密码、API 密钥和证书。
6.1 agenix
agenix 使用 age 加密文件,在部署时由目标主机解密:
# flake.nix
{
inputs = {
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, agenix }:
{
nixosConfigurations.web-server = nixpkgs.lib.nixosSystem {
modules = [
agenix.nixosModules.default
{
age.secrets.database-password = {
file = ./secrets/database-password.age;
owner = "postgres";
group = "postgres";
};
services.postgresql.initialScript = ''
CREATE USER app WITH PASSWORD '$(cat ${config.age.secrets.database-password.path})';
'';
}
];
};
};
}
6.2 sops-nix
sops-nix 使用 Mozilla SOPS 管理 YAML/JSON 加密文件:
# .sops.yaml
keys:
- &admin age1xxx...
creation_rules:
- path_regex: secrets/.*\.yaml$
key_groups:
- age:
- *admin
# flake.nix
{
inputs.sops-nix.url = "github:Mic92/sops-nix";
outputs = { self, nixpkgs, sops-nix }:
{
nixosConfigurations.web-server = nixpkgs.lib.nixosSystem {
modules = [
sops-nix.nixosModules.sops
{
sops.defaultSopsFile = ./secrets/secrets.yaml;
sops.secrets.api_key = {
owner = "myapp";
};
systemd.services.myapp.serviceConfig = {
LoadCredential = "api_key:${config.sops.secrets.api_key.path}";
};
}
];
};
};
}
7. CI/CD 集成
7.1 GitHub Actions + deploy-rs
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v24
with:
extra_nix_config: |
experimental-features = nix-command flakes
- name: Add SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
- name: Build and Deploy
run: |
nix run github:serokell/deploy-rs -- . -- -s
8. 总结
NixOS 远程部署工具生态正在快速发展。deploy-rs 凭借其简洁和可靠性成为当前的主流推荐,Colmena 适合需要高级编排功能的大型集群:
| 能力 | deploy-rs | Colmena | NixOps |
|---|---|---|---|
| Flakes 支持 | ✅ 原生 | ✅ 支持 | ⚠️ 实验性 |
| 并行部署 | ✅ | ✅ | ✅ |
| 自动回滚 | ✅ | ❌ | ✅ |
| 多架构 | ✅ | ✅ | ✅ |
| 标签系统 | ❌ | ✅ | ❌ |
| 云资源创建 | ❌ | ❌ | ✅ |
| 活跃度 | 高 | 高 | 低 |
对于新用户,推荐从 deploy-rs 开始。它结合了 Flakes 的现代工作流和可靠的部署机制,是学习 NixOS 远程部署的最佳起点。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。