feat: remote deployment

This commit is contained in:
Ryan Yin 2023-08-15 11:08:20 +08:00
parent b800157301
commit 35274826e4
6 changed files with 210 additions and 67 deletions

View File

@ -1,56 +1,130 @@
# Remote Deployment
Deploying NixOS configuration to remote hosts can be accomplished using tools like [NixOps](https://github.com/NixOS/nixops), [deploy-rs](https://github.com/serokell/deploy-rs), and [colmena](https://github.com/zhaofengli/colmena). However, if you prefer a simpler approach, you can use the built-in remote deployment capability of `nixos-rebuild` with SSH protocol.
Nix's inherent design is well-suited for remote deployment, and the Nix community offers several tools tailored for this purpose, such as [NixOps](https://github.com/NixOS/nixops) and [colmena](https://github.com/zhaofengli/colmena). Additionally, the official tool we've used extensively, `nixos-rebuild`, possesses some remote deployment capabilities too.
Before using `nixos-rebuild` for remote deployment, there are a few prerequisites:
Let me briefly guide you through using colmena or `nixos-rebuild` for remote deployment.
1. Configure SSH public key authentication for the remote hosts.
2. To prevent sudo password verification failures, either deploy as the `root` user or grant the user sudo permission without password verification.
- Related issue: <https://github.com/NixOS/nixpkgs/issues/118655>
## Prerequisites
Once the above configurations are in place, you can deploy the configuration to the server using the following command:
Before embarking on remote deployment, a few preparatory steps are necessary:
```bash
# 1. Add the SSH key to ssh-agent first
ssh-add ~/.ssh/ai-idols
1. To prevent sudo password verification failures, either deploy as the `root` user or grant the user sudo permission without password verification.
2. Configure SSH public key authentication for the remote hosts.
# 2. Deploy the configuration to the remote host, using the SSH key added in step 1.
# The username defaults to `$USER`, in my case, it's `ryan`.
nixos-rebuild --flake .#aquamarine --target-host 192.168.4.1 --build-host 192.168.4.1 switch --use-remote-sudo --verbose
It's advisable to use the `root` user for deployment as it's more convenient and avoids the complexities of sudo permissions.
Assuming we intend to deploy remotely using the root user, the initial step involves configuring SSH public key authentication for the root user on the remote host.
To accomplish this, simply add the following content to any NixOS Module in the remote host's Nix configuration (e.g., `configuration.nix`), then rebuild the system:
```nix
# configuration.nix
{
# ...
users.users.root.openssh.authorizedKeys.keys = [
# TODO Replace with your own SSH public key.
"ssh-ed25519 AAAAC3Nxxxxx ryan@xxx"
];
# ...
}
```
The command above will build and deploy the configuration to the `aquamarine` server, and the build process will also execute on `aquamarine`. The `--use-remote-sudo` option indicates that sudo permission is required on the remote server for deploying the configuration.
Furthermore, you'll need to add the SSH private key to the SSH agent on your local machine for authentication during remote deployment:
If you prefer to build the configuration locally and deploy it to the remote server, replace `--build-host aquamarine` with `--build-host localhost`. Additionally, instead of using the IP address directly, you can define host aliases in `~/.ssh/config` or `/etc/ssh/ssh_config`. For example:
```bash
ssh-add ~/.ssh/your-private-key
```
> The SSH config can be generated entirely through Nix configuration, and this task is left to you.
## Deploy through `colmena`
`colmena` doesn't directly use the familiar `nixosConfigurations.xxx` for remote deployment. Instead, it customizes a flake outputs named `colmena`. Although its structure is similar to `nixosConfigurations.xxx`, it's not identical.
In your system's `flake.nix`, add a new outputs named `colmena`. A simple example is shown below:
```nix
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.05";
# ...
};
outputs = { self, nixpkgs }: {
# ...
# Add this output, colmena will read its contents for remote deployment
colmena = {
meta = {
nixpkgs = import nixpkgs { system = "x86_64-linux"; };
# This parameter functions similarly to `sepcialArgs` in `nixosConfigurations.xxx`,
# used for passing custom arguments to all submodules.
specialArgs = {
inherit nixpkgs;
};
};
# Host name = "nixos-test"
"nixos-test" = { name, nodes, ... }: {
# Parameters related to remote deployment
deployment.targetHost = "192.168.5.42"; # Remote host's IP address
deployment.targetUser = "root"; # Remote host's username
# This parameter functions similarly to `modules` in `nixosConfigurations.xxx`,
# used for importing all submodules.
imports = [
./configuration.nix
];
};
};
};
}
```
Now you can deploy your configuration to the device:
```bash
nix run nixpkgs#colmena apply
```
For more advanced usage, refer to colmena's official documentation at <https://colmena.cli.rs/unstable/introduction.html>
## Deploy through `nixos-rebuild`
Using `nixos-rebuild` for remote deployment has the advantage of being similar to deploying to a local host. It only requires a few additional parameters to specify the remote host's IP address, username, and other details.
For instance, to deploy the configuration defined in the `nixosConfigurations.nixos-test` of your flake to a remote host, use the following command:
```bash
nixos-rebuild switch --flake .#nixos-text \
--target-host root@192.168.4.1 --build-host localhost --verbose
```
The above command will build and deploy the configuration of `nixos-test` to a server with IP `192.168.4.1`. The system build process will occur locally.
If you prefer to build the configuration on the remote host, replace `--build-host localhost` with `--build-host root@192.168.4.1`.
To avoid repeatedly using IP addresses, you can define host aliases in your local machine's `~/.ssh/config` or `/etc/ssh/ssh_config`. For example:
> Generating the SSH configuration entirely through Nix configuration is possible, and this task is left to you.
```bash
cat ~/.ssh/config
# ......
Host ai
HostName 192.168.5.100
Port 22
Host aquamarine
HostName 192.168.5.101
HostName 192.168.4.1
Port 22
Host ruby
HostName 192.168.5.102
Port 22
Host kana
HostName 192.168.5.103
Port 22
# ......
```
You can then use the host aliases to deploy the configuration:
With this setup, you can use host aliases for deployment:
```bash
nixos-rebuild --flake .#aquamarine --target-host aquamarine --build-host aquamarine switch --use-remote-sudo --verbose
nixos-rebuild switch --flake .#nixos-test --target-host root@aquamarine --build-host root@aquamarine --verbose
```
This allows for more convenient deployment using the defined host aliases.
This offers a more convenient way to deploy using the defined host aliases.

View File

@ -12,7 +12,7 @@ However, this doesn't mean that NixOS eliminates the need for system snapshots.
## How does Nix compare to traditional system management tools like Ansible?
Nix is not only used for managing desktop environments but is also widely employed for batch management of cloud servers. The official NixOps from the NixOS community and deploy-rs developed by the community are tools specifically designed for this use case.
Nix is not only used for managing desktop environments but is also widely employed for batch management of cloud servers. The official [NixOps](https://github.com/NixOS/nixops) from the NixOS community and [colmena](https://github.com/zhaofengli/colmena) developed by the community are tools specifically designed for this use case.
When compared to widely used traditional tools like Ansible, Nix has the following main advantages:

View File

@ -14,7 +14,7 @@ Dynamic data mentioned above, along with the contents in the user's home directo
Although we cannot achieve complete system reproducibility, the `/home` directory, being an important user directory, contains many necessary configuration files. A significant community project called [home-manager](https://github.com/nix-community/home-manager) is designed to manage user-level packages and configuration files within the user's home directory.
Due to Nix's features, such as being declarative and reproducible, Nix is not limited to managing desktop environments but is also extensively used for managing development environments, compilation environments, cloud virtual machines, and container image construction. [NixOps](https://github.com/NixOS/nixops) from the official Nix project and [deploy-rs](https://github.com/serokell/deploy-rs) from the community are both operational tools based on Nix.
Due to Nix's features, such as being declarative and reproducible, Nix is not limited to managing desktop environments but is also extensively used for managing development environments, compilation environments, cloud virtual machines, and container image construction. [NixOps](https://github.com/NixOS/nixops) from the official Nix project and [colmena](https://github.com/zhaofengli/colmena) from the community are both operational tools based on Nix.
## Why NixOS?

View File

@ -1,61 +1,130 @@
# 远程部署
社区的一些工具,比如 [NixOps](https://github.com/NixOS/nixops), [deploy-rs](https://github.com/serokell/deploy-rs), 跟 [colmena](https://github.com/zhaofengli/colmena),都可以用来部署 NixOS 配置到远程主机,但是都太复杂了,所以先全部跳过
Nix 本身的设计就很适合远程部署Nix 社区也有许多专门用于远程部署的工具,比如 [NixOps](https://github.com/NixOS/nixops) 与 [colmena](https://github.com/zhaofengli/colmena)。另外我们前面已经用了很多次的官方工具 `nixos-rebuild`,它拥有一定的远程部署能力
实际上我们前面使用了多次的 NixOS 本机部署命令 `nixos-rebuild`,这个工具也支持通过 ssh 协议进行远程部署,非常方便
这里我简单介绍下如何使用 colmena 与 `nixos-rebuild` 进行远程部署
美中不足的是,`nixos-rebuild` 不支持使用密码认证进行部署,所以要想使用它进行远程部署,我们需要:
## 准备工作
1. 为远程主机配置 ssh 公钥认证。
2. 为了避免 sudo 密码认证失败,需要使用 `root` 用户进行部署,或者给用户授予 sudo 权限不需要密码认证。
1. 相关 issue: <https://github.com/NixOS/nixpkgs/issues/118655>
在进行远程部署之前,需要做一些准备工作:
在搞定上面两点后,我们就可以使用 `nixos-rebuild` 进行远程部署了:
1. 为了防止 sudo 密码验证失败,要么以 `root` 用户身份部署,要么为用户授予免密码验证的 sudo 权限。
2. 为远程主机配置 SSH 公钥身份验证。
```bash
# 1. 首先将本地的 ssh 私钥加载到 ssh-agent 中,以便后续使用
ssh-add ~/.ssh/ai-idols
建议使用 `root` 用户进行部署,因为这更方便且不需要额外的配置,没有令人头疼的 sudo 权限问题。
# 2. 将 NixOS 配置部署到远程主机,使用第一步添加的 ssh key 进行认证,用户名默认为 `$USER`
nixos-rebuild --flake .#aquamarine --target-host 192.168.4.1 --build-host 192.168.4.1 switch --use-remote-sudo --verbose
假设我们现在要通过 root 用户进行远程部署,首先需要在远程主机上为该用户配置 SSH 公钥身份验证。
直接在远程主机的 Nix 配置的任一 NixOS Module 中(比如 `configuration.nix`)添加如下内容,然后重新构建系统即可:
```nix
# configuration.nix
{
# ...
users.users.root.openssh.authorizedKeys.keys = [
# TODO 替换为您自己的 SSH 公钥。
"ssh-ed25519 AAAAC3Nxxxxx ryan@xxx"
];
# ...
}
```
上面的命令会将 NixOS 配置部署到 `aquamarine` 这台主机上,参数解释如下:
然后还需要提前在本机上将用于登录的 SSH 私钥添加到 SSH agent以便在部署配置时进行身份验证
1. `--target-host`: 设置远程主机的 ip 地址
2. `--build-host` 指定了构建 NixOS 配置的主机,这里设置为跟 `--target-host` 相同,表示在远程主机上构建配置。
3. `--use-remote-sudo` 表示部署需要用到远程主机的 sudo 权限,如果不设置这个参数,部署会失败。
```bash
ssh-add ~/.ssh/your-private-key
```
如果你希望在本地构建配置,然后再部署到远程主机,可以命令中的 `--build-host aquamarinr` 替换为 `--build-host localhost`
## 通过 `colmena` 进行部署
另外如果你不想直接使用 ip 地址,可以在 `~/.ssh/config` 或者 `/etc/ssh/ssh_config` 中定义一些主机别名,比如:
`colmena` 不能直接使用我们已经熟悉的 `nixosConfigurations.xxx` 进行远程部署,它自定义了一个名为 `colmena` 的 flake outputs 来进行远程部署,
其内容结构与 `nixosConfigurations.xxx` 类似但不完全相同。
> 当然如下这份配置也完全可以通过 Nix 来管理,这个就留给读者自己去实现了。
在你系统的 `flake.nix` 中添加一个新的名为 `colmena` 的 outputs一个简单的例子如下
```nix
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-23.05";
# ...
};
outputs = { self, nixpkgs }: {
# ...
# 新增这个 outputscolmena 会读取这个 outputs 中的内容进行远程部署
colmena = {
meta = {
nixpkgs = import nixpkgs { system = "x86_64-linux"; };
# 这个参数的功能与 `nixosConfigurations.xxx` 中的 `sepcialArgs` 一致,
# 都是用于传递自定义参数到所有子模块。
specialArgs = {
inherit nixpkgs;
};
};
# 主机名 = "nixos-test"
"nixos-test" = { name, nodes, ... }: {
# 与远程部署相关的参数
deployment.targetHost = "192.168.5.42"; # 远程主机的 IP 地址
deployment.targetUser = "root"; # 远程主机的用户名
# 此参数的功能与 `nixosConfigurations.xxx` 中的 `modules` 一致
# 都是用于导入所有子模块。
imports = [
./configuration.nix
];
};
};
};
}
```
现在,您可以将配置部署到设备上:
```bash
nix run nixpkgs#colmena apply
```
更复杂的用法,请参阅 colmena 的官方文档 <https://colmena.cli.rs/unstable/introduction.html>
## 通过 `nixos-rebuild` 进行部署
`nixos-rebuild` 进行远程部署的好处在于,它的工作方式与部署到本地主机完全相同,只需要多传几个参数,指定下远程主机的 IP 地址、用户名等信息即可。
例如,使用以下命令将 flake 中的 `nixosConfigurations.nixos-test` 这份配置部署到远程主机:
```bash
nixos-rebuild switch --flake .#nixos-text \
--target-host root@192.168.4.1 --build-host localhost --verbose
```
上述命令将会构建并部署 nixos-test 的配置到 IP 为 `192.168.4.1` 的服务器,系统构建过程将在本机执行。
如果你希望在远程主机上构建系统,只需要将 `--build-host localhost` 替换为 `--build-host root@192.168.4.1`
如果你觉得到处写 IP 地址不太合适,也可以在本地主机的 `~/.ssh/config``/etc/ssh/ssh_config` 中定义主机别名。例如:
> SSH 配置可以完全通过 Nix 配置生成,这个任务就留给读者自己完成了。
```bash
cat ~/.ssh/config
# ......
Host ai
HostName 192.168.5.100
Port 22
Host aquamarine
HostName 192.168.5.101
HostName 192.168.4.1
Port 22
Host ruby
HostName 192.168.5.102
Port 22
Host kana
HostName 192.168.5.103
Port 22
# ......
```
这样我们就可以使用主机别名进行部署了:
然后就可以直接使用主机别名进行部署了:
```bash
nixos-rebuild --flake .#aquamarine --target-host aquamarine --build-host aquamarine switch --use-remote-sudo --verbose
nixos-rebuild switch --flake .#nixos-test --target-host root@aquamarine --build-host root@aquamarine --verbose
```

View File

@ -16,7 +16,7 @@ NixOS 的配置文件就像是程序的**源代码**,只要源代码没丢,
## Nix 与 Ansible 等传统的系统运维工具相比有何优劣?
Nix 不仅可用于管理桌面电脑的环境也有很多人用它批量管理云服务器Nix 官方的 [NixOps](https://github.com/NixOS/nixops) 与社区的 [deploy-rs](https://github.com/serokell/deploy-rs) 都是专为这个场景开发的工具。
Nix 不仅可用于管理桌面电脑的环境也有很多人用它批量管理云服务器Nix 官方的 [NixOps](https://github.com/NixOS/nixops) 与社区的 [colmena](https://github.com/zhaofengli/colmena) 都是专为这个场景开发的工具。
Nix 与 Ansible 这类被广泛应用的传统工具比,主要优势就在:

View File

@ -16,7 +16,7 @@ Nix 是一个声明式的软件包管理器,用户需要通过某些配置声
但是用户的 Home 目录中实际包含了许多重要的配置文件,用户当然会希望能使用 Nix 将它们给管理起来。
另一个重要的社区项目 [home-manager](https://github.com/nix-community/home-manager) 就填补了这块缺失,它被设计用于管理用户 Home 目录中的配置文件以及用户级别的软件包。
因为 Nix 声明式、可复现的特性Nix 不仅可用于管理桌面电脑的环境也有很多人用它管理开发编译环境、云上虚拟机、容器镜像构建等等Nix 官方的 [NixOps](https://github.com/NixOS/nixops) 与社区的 [deploy-rs](https://github.com/serokell/deploy-rs) 都是基于 Nix 实现的运维工具。
因为 Nix 声明式、可复现的特性Nix 不仅可用于管理桌面电脑的环境也有很多人用它管理开发编译环境、云上虚拟机、容器镜像构建等等Nix 官方的 [NixOps](https://github.com/NixOS/nixops) 与社区的 [colmena](https://github.com/zhaofengli/colmena) 都是基于 Nix 实现的运维工具。
## 为什么选择 NixOS