Oh! Guix! 传说中 GNU/Linux 发行版的终极答案——原子、声明式、完全自由。我用上了,大概两个月。下面这些算不上评测,更像一份折腾笔记。
一、坑多
最大的感受就一个字:坑。比如 Guix 的 search path 机制会把 login bash 的 PATH 重置掉,导致 codex 的 exec_command 找不到它刚注入的 apply_patch;又比如一堆指向 /gnu/store 的环境变量漏进 flatpak 沙盒,让沙盒里的应用直接没网。
Guix 的文档质量其实相当高,但社区人少,很多问题根本搜不到答案。说实话,如果没有 LLM agent,这里面很多坑我是解决不了的。
具体的现象、原因和解决办法我都记在了《Guix 踩坑记录以及解决办法》里,那篇会持续更新。
二、非 FHS
非 FHS 这一点我早有准备,毕竟之前用过 NixOS。而且现在能给 FHS 环境的东西太多了:flatpak、docker/podman、distrobox,Guix 自己的 guix shell 也有 -C、-F 选项可以起一个 FHS 容器环境。所以在开发上其实没什么问题。
但是——AppImage 不能正常用,这就相当难受了。
在 NixOS 上,有这些东西:
programs.appimage.enable = true;
programs.appimage.binfmt = true;
还有 appimage-run。而在 Guix 上这些统统没有,官方和社区给出的答案是 guix shell -C -F,再把 dbus、Wayland 之类挂进去,大概长这样:
guix shell \
--container --network --emulate-fhs \
--development ungoogled-chromium gcc:lib \
--preserve='^WAYLAND_DISPLAY$|^XDG_' --expose=$XDG_RUNTIME_DIR \
--preserve='^DBUS_' --expose=/var/run/dbus \
-- ./xyz.AppImage
实际使用体验相当糟糕,每次都要手写一长串参数。
顺带一提,guix pack -f appimage 本身也能打包 AppImage,加上 -RR 之后得到的是完整闭包——所有依赖都塞进去,只要目标机器有 FUSE 和 user namespace,不管跑的是 Guix 还是别的发行版都能直接用。我试着打包了 NetEase_Cloud_Music_Gtk4,结果产物接近 1G 🤣,所有编解码器都被打进去了。
三、开发体验:
guix shell 是个很不错的开发工具。配合 direnv,cd 进工作区就能自动把开发工具和依赖注入 PATH。比如我写 Rust 的时候:
❯ cd Projects/gh2tg
direnv: loading ~/Projects/gh2tg/.envrc
direnv: using guix --manifest=manifest.scm
direnv: export +CARGO_HTTP_CAINFO +CPLUS_INCLUDE_PATH +C_INCLUDE_PATH +GUIX_ENVIRONMENT +LIBRARY_PATH +OBJCPLUS_INCLUDE_PATH +OBJC_INCLUDE_PATH +PKG_CONFIG_PATH +RUST_SRC_PATH ~GUIX_LOCPATH ~PATH ~SSL_CERT_DIR ~SSL_CERT_FILE
;; manifest.scm — Rust 开发环境
;;
;; 用法:
;; guix shell -m manifest.scm
;; 或者把该文件放到项目根目录后直接运行:
;; guix shell
(specifications->manifest
(list
;; Rust 工具链
"rust" ; out 输出:rustc 编译器
"rust:cargo" ; Cargo 包管理器
"rust:tools" ; rustfmt 等附加开发工具
"rust:rust-src" ; 标准库源码(rust-analyzer / IDE 跳转需要)
;; 编译链接所需系统工具:提供 cc、ld 等
"gcc-toolchain"
;; 常用开发依赖
"pkg-config" ; 供 -sys 类 crate 查找系统库
"openssl" ; 很多 crate(如 reqwest、git2)会用到
"nss-certs" ; CA 证书,让 cargo 能通过 HTTPS 拉取 crates
;; 调试器
"gdb"))
体验类似于 Nix 的 nix-shell + flakes。另外 guix shell 还能用 -D 指定一个派生,拿到构建这个派生所需的环境,但不安装它本身,调试构建时很好用。
四、GNU 原教旨主义:
Guix 官方 channel 会拒绝打包不是完全自由的软件。比如 PrismLauncher:启动器本身开源,但它的功能只服务于 Minecraft 这个闭源游戏,这种就进不了官方频道。
而且大多数人手里的硬件本来就不完全自由,网卡尤其如此。官方安装镜像只有 Linux-Libre 和 GNU/Hurd 两种内核:Hurd 就不说了,Linux-Libre 根本驱动不了我笔记本的网卡——如果只用官方镜像,我连安装都完不成。
所以我用的是「Guix·萌」镜像,它内置了 nonguix 频道和 Linux 内核。
五、channel 生态:
同样是人少的问题。官方频道打包数量极其有限,而且部分包缺少维护、很久不同步更新。用 Guix 的话,维护一个个人 channel 几乎是必选项——我的频道在 sorubedo/guix-channel。
但代价是要添加很多 channel,滚动体验就很差了:各个 channel 之间不会同步,GNU 频道一旦有破坏性更新,大概率会连累其他 channel 的可用性,导致 guix pull 拉不下来或者 guix system reconfigure 直接报错。
而且 Guix 真的很慢,并没有比 Nix 好多少。
还有一个具体的痛点:Flutter 目前相当难用 Guix 打包。它没有对应的 build system,pub.dev 又很难做到不联网(Guix 要求构建阶段离线),我就没找到任何一个 channel 包含任何 Flutter 软件。想自己打包,结果用 AI 也没打出来。
六、桌面体验:
我用的 niri 在官方 channel 有打包,noctalia 也自带 Guix 频道,所以桌面体验这块我感觉和其他发行版大差不差。区别在于,很多组件要去各个 channel 里找,或者自己打包。

我的日常桌面:niri + Noctalia。左边终端是 fastfetch,底下那条命令是 sudo herd status——Guix 的服务管理器是 GNU Shepherd,herd 就是它的控制命令。
过程中也踩了一些坑,比如 (plasma-desktop-service-type) 配出来的 DM 居然是 GDM?不太理解。所以最后我没用桌面服务模块,而是自己组装——这一点和很多元发行版的体验是一致的。组装下来,我对一个日用桌面/WM 到底需要什么,已经相当门清了(
桌面相关的坑我都记在了踩坑记录里:niri 服务与 xdg-desktop-portal、Xwayland、Qt 图标、文件管理器,还有 home 侧的 N 卡驱动。
七、情绪价值:
Guix 虽然 GNU 血统最纯正,但称得上是一个相当冷门特殊的发行版,甚至被认为属于「灵车」。了解 Guix 的人发现我在用它,大概率会感叹一声「你居然用 Guix」;我也曾因此被误以为是运维大神(。遇到不了解 Guix 的人,我也能好好跟他说道说道声明式 OS 的好处。
但说到底,对于喜欢折腾的人,尝试和折腾各种发行版本来就是一件开心的事。
现代热门发行版已经被 systemd 占领,在 init 和 services 管理这一块几乎没有什么新鲜感。systemd 做得相当好,我也爱用,但不能因此忽视别的 init 的特色。在 non-systemd 发行版里,我用过的还有 Gentoo(OpenRC)、Void(runit)、Alpine 和 postmarketOS。
最令我爽的一次是 Gentoo:通宵等着它编译,从下载镜像到登录 Plasma 花了 9 个小时。再让我来一次我会嫌麻烦,但那种快感很难用语言描述。Guix也是,在装到物理机前,我在虚拟机改了很久配置,装上后的一周又在不断改配置。
结语
Guix 不是给所有人的答案,但它把「声明式」和「完全自由」这两件事推到了极致。这两个月里,我一边被坑得怀疑人生,一边又确实舍不得换掉它。
目前正在考虑回到 Debian Testing,反正 Guix 只要配置声明还在,就能随时复现。
如果你也在用 Guix,欢迎看看我的踩坑记录——那里持续更新我在上面遇到的各种问题和解决办法。
guix system shepherd-graph
