从 channel 到 Flakes:在 NixOS 上声明式安装 Pi Agent

从 channel 到 Flakes:在 NixOS 上声明式安装 Pi Agent
Xiaozhi_z写这篇文章纯粹是我有一个很老的旗舰办公本一直在家里吃灰(我记得好像是3代I7),正好最近加了学校的一个实验室可以有地方放这台笔记本让它再发挥一下余光(用这个笔记本去跑一些不复杂的agent完全没问题 也想着顺便体验体验可能更适合Agent的Linux系统 最终找到了NixOS
NixOS 是一个完全采用声明式管理的 Linux 发行版,构建在 Nix 包管理器之上。整个系统——内核、应用、系统软件包、配置文件——都由 Nix 表达式统一描述,再由 Nix 构建并放入 store。它和传统发行版最大的不同在于:软件包不会被装进 /bin、/usr 这些目录,而是彼此隔离地存放在 /nix/store 里,每个版本一个独立路径。/bin、/usr/bin 当然还是有的,但里面基本只是指向 store 中某个具体版本的符号链接,真正的实体都在 store。靠这套机制,NixOS 实现了系统状态的原子化更新和秒级回滚,也顺带消除了环境漂移问题。

为什么选这个系统?
一开始我的选择其实是Omarchy,一个据说内置了一堆agent cli环境的系统,但是可惜底层是Arch不太适合7x24小时开机当一个小服务器。然后我就找到了NixOS,一个既不属于Debian、Redhat、Arch系家族的系统。
可能一开始会用一些上手难度,我一上来就输了 nix install openssh 以为这样就能安装上sshd服务却没有想到这个系统居然是声明式的,是要写配置文件configuration.nix然后进行nixos-rebuild switch进行包管理的,可能一开始会有一些适应的空间。
但是优势非常明显,基本就是两点:一是系统整个都是声明式的,可以随便回滚;二是可以随时独立开一个全新的环境。 我之前跑agent就直接用的Rocky因为用红帽用习惯了,经常 agent 跑着跑着就整出来各种各样的软件包、环境变量、pip 包、npm 包,把系统环境污染得乱七八糟,跑到最后各种冲突。这个系统可以直接开一次性环境,关闭shell就清空。而且可以随便回滚,agent把系统弄崩了可以直接回滚之前的状态。
用声明式方法安装ssh服务端
在 Debian / Ubuntu / Arch 这些系统里,我们习惯的是
1 | sudo apt install openssh-server |
也就是安装一个包,再手动启用一个服务。
但是在这个系统里面是修改/etc/nixos/configuration.nix这个配置文件,启用sshd这个服务。
因为这个系统不自带vi、vim(我又不习惯nano,就一开始先启动了一个带有vim的虚拟环境
1 | nix-shell -p vim |
1 | services.openssh.enable = true |
根据新配置构建系统
1 | nixos-rebuild switch |
安装Pi Agent
Pi 官方推荐的是 profile 安装,但为了狠狠学习一下声明式,我决定走 Flakes 路线。Pi 官方仓库提供了 Flake,暴露了 packages 输出,所以可以直接把它作为 input 引入我的 NixOS 配置,在 configuration.nix 里引用它的包,实现声明式安装。

为什么不用profile安装是因为nixos不推荐使用profile来影响环境 这里如果声明式安装又引入了一个叫Flakes的概念感觉好玩准备试试
Flakes 是什么
上面提到了 Flakes,这里补一下。Flakes 就是 Nix 项目的一种标准结构,把依赖和产出都写在一个 flake.nix 里。核心是 inputs 和 outputs:inputs 声明依赖谁,outputs 返回这个 Flakes 对外提供什么。
但真正有用的是锁文件。你在 inputs 里写一个 GitHub 地址,Nix 会生成 flake.lock,把依赖锁到具体 commit。只要 lock 不变,谁、什么时候构建,拿到的版本都一样。传统配置靠 channel 定位 nixpkgs,channel 是滚动的,今天和一个月后构建可能完全不同,复现性就差在这。
为什么装 Pi 非要用 Flakes
回到装 Pi 这件事上,官方推荐profile安装,但是profile的本质是往系统上手动塞东西,NixOS 并不推荐用它来影响环境,如果想走声明式目前我能查到的就是Flakes路线。
官方的 Pi Agent的版本停留在0.75.4

但是 Pi 的官方上游已经到1.3.0版本了 版本差的蛮大的 有一些特性和功能都没有

把系统配置切换成 Flakes 管理
NixOS系统默认不是Flakes管理 而是直接使用channel + configuration.nix 驱动 要先把系统配置移交给Flakes管理进行下一步操作
启用 Flakes 实验特性 将下方配置写入configuration.nix
Flakes 通过 git 命令拉取其依赖项
1 | nix.settings.experimental-features = [ "nix-command" "flakes" ]; |
先正常重建一次让这个设置生效
1 | nixos-rebuild switch |

创建flakes的初始化模版文件
这里对网络环境有一定的要求
1 | cd /etc/nixos |
编写flake.nix的配置文件 这里简单来讲就是设置了一个入口 然后把原本的configuration.nix作为一个modules也就是一个子配置文件写入到flakes配置
这里的nixosConfigurations.nixos中的nixos要和自己的主机名对应 不知道主机名可以输入hostname查看
源地址我用的南大的镜像地址 如果网络直连Github没问题用官方源也可以
1 | { |
应用配置 切换到 Nix Flakes 这里用了个加速源
1 | nixos-rebuild switch --option substituters "https://mirrors.cernet.edu.cn/nix-channels/store" |

用 Flake 安装 Pi Agent
修改 flake.nix 增加 pi 这个 input 然后把 pi 这个 flake 的包集传递下去,方便 configuration.nix 使用
1 | { |
然后修改 configuration.nix
1 | { config, pkgs, pi, ... }: |
重新构建 安装Pi Agent
这里有两个截屏是因为一开始忘记加镜像源了(
1 | nixos-rebuild switch --option substituters "https://mirrors.cernet.edu.cn/nix-channels/store" |


然后查看一下pi的版本 版本1.3.0与上游最新版一致
1 | pi --version |

为什么大费周章的做这么多声明式安装其实只是为了假如agent真的把系统玩坏了或者崩了,nixos-rebuild switch --rollback 秒回上一版,最坏也就是回滚一次,不用重装。而且写好的声明式文件可以直接丢到一台新机器上再次rebuild就可以获得一模一样的环境!
