版本范围:下列示例保留 NixOS 24.05 的教程上下文;该版本已结束维护。实际项目应选择受支持的发行版、锁定 nixpkgs revision,并核对相应选项。
system.stateVersion表示兼容性基线,不应随升级机械改动。本文命令是教学示例,未在目标系统运行验证。
翻译自 nix.dev: Provisioning remote machines via SSH
通过 SSH 将 NixOS 部署到远程服务器,实现基础设施即代码。
前置要求#
- 已安装 NixOS 的目标服务器
- SSH 密钥访问权限
- 本地已安装 Nix
基本部署流程#
1. 准备目标服务器
确保远程服务器已启用 SSH:
# 在远程服务器上检查
systemctl status sshd2. 本地配置构建
创建部署配置 deployment.nix:
{ config, pkgs, ... }:
{
# 网络配置
networking.hostName = "remote-server";
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [ 22 80 443 ];
# SSH 配置
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
};
};
# 用户配置
users.users.deploy = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"<DEPLOY_SSH_PUBLIC_KEY>"
];
};
# Web 服务示例
services.nginx = {
enable = true;
virtualHosts."example.com" = {
root = "/var/www";
locations."/" = {
extraConfig = "index index.html;";
};
};
};
system.stateVersion = "24.05";
}3. 使用 nixos-rebuild 远程部署
目标必须已经安装 NixOS,部署配置还应导入该目标的 hardware-configuration.nix、文件系统与引导模块;这里的服务片段不是完整裸机配置。先保持一个可用 SSH 会话和控制台恢复路径,确认 deploy 用户能提升到 root。24.05 的 rebuild 使用 --use-remote-sudo;新版本 rebuild-ng 的对应参数可能为 --sudo,以目标工具的 --help 为准。
先构建,再测试;test 会修改正在运行的系统,只是不设为下次启动默认值。switch 同时激活并更新系统 generation/启动配置。
# 构建,不激活目标
nixos-rebuild build -I nixos-config=./deployment.nix
# 实际远程临时激活,先确认影响再执行
nixos-rebuild test --target-host deploy@remote-server --use-remote-sudo \
-I nixos-config=./deployment.nix# 远程部署并应用配置
nixos-rebuild switch \
--target-host deploy@remote-server \
--use-remote-sudo \
-I nixos-config=./deployment.nix参数说明:
--target-host: 目标服务器地址--build-host: 指定远程构建主机;不指定时通常在本地构建。不要把localhost特殊值当作跨版本保证。--use-remote-sudo:历史 rebuild 对非 root 目标用户启用远端 sudo。是否可交互输密码取决于工具版本与连接方式。
使用 Flakes 部署#
flake.nix
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
outputs = { self, nixpkgs }: {
nixosConfigurations.remote-server = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ ./configuration.nix ];
};
};
}部署命令
# 构建并部署
nixos-rebuild switch \
--flake .#remote-server \
--target-host deploy@remote-server --use-remote-sudo批量部署多台服务器#
以下脚本实际逐台激活服务器。每个 nixosConfigurations key 必须与数组中的名称完全对应;应先对单台节点完成 build/test 和 SSH 验证,再批准整个列表。失败会停止后续部署,已成功节点不会自动整体回滚。创建 deploy.sh:
#!/usr/bin/env bash
SERVERS=(
"server1.example.com"
"server2.example.com"
"server3.example.com"
)
for server in "${SERVERS[@]}"; do
echo "Deploying to $server..."
nixos-rebuild switch \
--flake ".#$server" \
--target-host "deploy@$server" --use-remote-sudo || exit 1
echo "✓ $server deployed"
done
echo "All servers deployed!"使用 deploy-rs 工具#
deploy-rs 是社区维护的部署工具,支持原子部署和回滚。
安装
# 在 shell.nix 或配置中添加
environment.systemPackages = with pkgs; [
deploy-rs
];配置 deploy.nix
下面的 attrset 应作为 flake 的 deploy 输出,由 self 和 deploy-rs inputs 提供作用域;仅保存成孤立文件并不会自动接入工具。建议同时暴露 deploy-rs.lib.<system>.deployChecks self.deploy 到 checks。原子 profile 切换、失败回滚及 magic rollback 都受配置和 SSH 恢复条件约束,不能代替数据备份。
{
nodes = {
web-server = {
hostname = "web.example.com";
profiles.system = {
user = "root";
sshUser = "deploy";
path = deploy-rs.lib.x86_64-linux.activate.nixos
self.nixosConfigurations.web-server;
};
};
db-server = {
hostname = "db.example.com";
profiles.system = {
user = "root";
sshUser = "deploy";
path = deploy-rs.lib.x86_64-linux.activate.nixos
self.nixosConfigurations.db-server;
};
};
};
}执行部署
# 部署所有节点
deploy
# 部署特定节点
deploy .#web-server
# 显示待激活变化:可能构建、上传并在远端 dry-activate,仍会使用远程连接
deploy --dry-activate
# 只做本地 flake 检查与系统构建,不触碰目标
nix flake check
nix build .#nixosConfigurations.web-server.config.system.build.toplevel密钥管理#
不要把明文密钥放入 Nix 字符串、store、镜像或 Terraform state。agenix 的密文可以随配置管理,私钥留在目标的受控路径;应用在运行时读取解密文件。
使用 age 加密密钥
services.myapp 是示意接口,必须由真实应用模块定义;owner/group 也须预先存在。agenix input 通过 specialArgs 等方式传入模块。
{ config, pkgs, agenix, ... }:
{
imports = [ agenix.nixosModules.default ];
age.secrets.api-key = {
file = ./secrets/api-key.age;
owner = "myapp";
group = "myapp";
};
services.myapp = {
enable = true;
apiKeyFile = config.age.secrets.api-key.path;
};
}部署检查与回滚#
# 先测试配置
nixos-rebuild test \
--flake .#remote-server \
--target-host deploy@remote-server --use-remote-sudo
# 如果出问题,远程回滚
ssh deploy@remote-server 'sudo nixos-rebuild switch --rollback'
# 查看远程系统版本
ssh deploy@remote-server 'sudo nix-env -p /nix/var/nix/profiles/system --list-generations'持续部署 CI/CD#
GitHub Actions 示例
这是实际部署 workflow,push 会触发远端变更。生产环境应配置受保护 deployment environment/审批与最小权限,第三方 actions 固定到核验过的 commit SHA。安装 Nix 不保证 runner 已有 nixos-rebuild,应通过锁定的工具环境提供对应版本。known_hosts 从独立可信渠道核验后预存;临时 ssh-keyscan 只能采集候选公钥,不能建立服务器身份信任。
name: Deploy NixOS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf '%s\n' "$DEPLOY_KNOWN_HOSTS" > ~/.ssh/known_hosts
chmod 600 ~/.ssh/known_hosts
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
DEPLOY_KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
- name: Deploy
run: |
nixos-rebuild switch \
--flake .#remote-server \
--target-host deploy@remote-server --use-remote-sudo参考与延伸
根据技术笔记重新整理,示例使用通用名称。