强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

GNU Guix 函数式包管理教程 / 第五章 通道与版本管理

第五章:通道与版本管理

5.1 通道概述

通道(Channel)是 Guix 获取包定义和系统模块的来源。每个通道本质上是一个 Git 仓库,包含 Scheme 模块(包定义、服务定义等)。

通道(Channel)→ Git 仓库 → Scheme 模块 → 包定义 / 服务定义

通道的核心作用

作用 说明
包分发 提供包的定义(recipe),而非二进制文件
版本管理 每个通道 commit 对应一组确定的包版本
可重现性 锁定通道版本即可重现整个环境
可扩展性 第三方通道扩展官方包集合

5.2 官方通道

5.2.1 guix 通道

默认通道,包含 Guix 核心代码和所有官方包定义:

(channel
  (name 'guix)
  (url "https://git.savannah.gnu.org/git/guix.git")
  (branch "master")
  (introduction
    (make-channel-introduction
      "9edb3f66fd807b096b48283debdcddccfea34bad"
      (openpgp-fingerprint
        "BBB0 2DFC 2F96 32BA 8D95  4B6C 9218 5D7B E7AA 3A24"))))

官方通道的签名验证:Guix 使用 OpenPGP 签名验证通道的完整性。首次 guix pull 时会验证 introduction commit 的签名,后续所有 commit 必须形成从 introduction 到 HEAD 的签名链。

5.2.2 查看通道信息

# 查看当前使用的通道
guix describe

# 输出示例:
# Generation 15  May 10 2026 12:00:00    (current)
#   guix 1.4.0-12.abc1234
#     repository URL: https://git.savannah.gnu.org/git/guix.git
#     branch: master
#     commit: abc1234def5678...
#     channel news:
#       - Added 5 new packages
#       - Updated vim to 9.1.0

5.3 第三方通道

5.3.1 Nonguix 通道

最常用的第三方通道,提供非自由软件和官方通道无法包含的包:

包名 说明
linux 完整 Linux 内核(非 Linux-libre)
nvidia-driver NVIDIA 显卡驱动
steam Steam 游戏平台
chromium Chromium 浏览器
firmware 非自由固件
;; ~/.config/guix/channels.scm
(list
  (channel
    (name 'guix)
    (url "https://git.savannah.gnu.org/git/guix.git")
    (introduction
      (make-channel-introduction
        "9edb3f66fd807b096b48283debdcddccfea34bad"
        (openpgp-fingerprint
          "BBB0 2DFC 2F96 32BA 8D95  4B6C 9218 5D7B E7AA 3A24"))))

  (channel
    (name 'nonguix)
    (url "https://gitlab.com/nonguix/nonguix")
    (introduction
      (make-channel-introduction
        "897c1a470da759236cc11798f4e0a5f7d4d59fbc"
        (openpgp-fingerprint
          "2A39 3FFF 68F4 EF7A 3D29  12AF 6F51 20A0 22FB B2D5")))))

⚠️ 注意:Nonguix 通道包含非自由软件,仅在确实需要时使用。

5.3.2 常见第三方通道

通道 URL 说明
nonguix https://gitlab.com/nonguix/nonguix 非自由软件
guix-science https://gitlab.com/guix-science/guix-science 科学计算包
guix-science-nonfree https://gitlab.com/guix-science/guix-science-nonfree 非自由科学计算包
guix-past https://gitlab.com/guix-past/guix-past 历史版本包

5.3.3 查找更多通道

# 在 GitLab/GitHub 上搜索 guix channel
# 常见命名模式:
# guix-<topic>
# guix-packages

# 社区维护的通道列表
# https://awesome-guix.com/

5.4 自定义通道

5.4.1 通道仓库结构

创建自定义通道需要遵循特定的目录结构:

my-guix-channel/
├── .git/
├── .guix-channel          # 通道元数据(可选)
├── README.md
└── mychannel/
    ├── packages/
    │   ├── vim.scm
    │   ├── python.scm
    │   └── web.scm
    └── services/
        └── myapp.scm

5.4.2 通道元数据文件

;; .guix-channel(可选)
(channel
  (version 0)
  (news-file "news.scm"))

5.4.3 包定义模块示例

;; mychannel/packages/vim.scm
(define-module (mychannel packages vim)
  #:use-module (guix packages)
  #:use-module (guix build-system gnu)
  #:use-module (guix gexp)
  #:use-module (guix licenses)
  #:use-module (guix download)
  #:use-module (gnu packages vim)
  #:use-module (gnu packages ncurses))

(define-public my-vim
  (package
    (inherit vim)
    (name "my-vim")
    (version "9.1.0-custom")
    (source (origin
              (method url-fetch)
              (uri (string-append "https://github.com/my/vim/archive/"
                                  version ".tar.gz"))
              (sha256 (base32 "0abc..."))))
    (arguments
      (substitute-keyword-arguments (package-arguments vim)
        ((#:configure-flags flags)
         #~(append #$flags
                   (list "--enable-feature-x")))))))

5.4.4 注册自定义通道

;; ~/.config/guix/channels.scm
(list
  ;; 官方通道
  (channel
    (name 'guix)
    (url "https://git.savannah.gnu.org/git/guix.git")
    (introduction
      (make-channel-introduction
        "9edb3f66fd807b096b48283debdcddccfea34bad"
        (openpgp-fingerprint
          "BBB0 2DFC 2F96 32BA 8D95  4B6C 9218 5D7B E7AA 3A24"))))

  ;; 自定义通道
  (channel
    (name 'mychannel)
    (url "https://github.com/username/my-guix-channel")
    (branch "main")))
# 拉取更新
guix pull

# 验证通道已加载
guix describe

5.5 通道的分支与版本

5.5.1 使用特定分支

(channel
  (name 'mychannel)
  (url "https://github.com/username/my-guix-channel")
  (branch "stable"))   ; 使用 stable 分支而非 main

5.5.2 锁定到特定 Commit

(channel
  (name 'guix)
  (url "https://git.savannah.gnu.org/git/guix.git")
  (commit "abc1234def56789012345678901234567890abcd")
  (introduction
    (make-channel-introduction
      "9edb3f66fd807b096b48283debdcddccfea34bad"
      (openpgp-fingerprint
        "BBB0 2DFC 2F96 32BA 8D95  4B6C 9218 5D7B E7AA 3A24"))))

5.6 版本锁定与可重现

5.6.1 生成锁定文件

# 导出当前通道状态为锁定文件
guix describe --format=channels > channels-lock.scm

# 查看内容
cat channels-lock.scm

导出的文件包含所有通道的精确 commit hash:

(list (channel
        (name 'guix)
        (url "https://git.savannah.gnu.org/git/guix.git")
        (commit "abc1234...")
        (introduction
          (make-channel-introduction
            "9edb3f66fd807b096b48283debdcddccfea34bad"
            (openpgp-fingerprint
              "BBB0 2DFC 2F96 32BA 8D95  4B6C 9218 5D7B E7AA 3A24")))))

5.6.2 使用锁定文件

# 在另一台机器上使用相同的通道版本
guix pull --channels=channels-lock.scm

# 使用 time-machine 运行特定版本的 Guix
guix time-machine --channels=channels-lock.scm -- \
  install vim

# 使用特定版本创建 shell 环境
guix time-machine --channels=channels-lock.scm -- \
  shell python python-numpy

5.6.3 团队协作场景

场景:确保团队成员使用相同版本

# 项目根目录
project/
├── channels.scm        # 锁定的通道版本
├── manifest.scm        # 项目依赖
└── README.md

# 团队成员执行:
guix pull --channels=./channels.scm
guix time-machine --channels=./channels.scm -- \
  shell --manifest=manifest.scm

5.6.4 Guix System 的版本锁定

# 备份系统配置对应的通道版本
guix describe --format=channels > /etc/guix/channels-lock.scm

# 系统升级时先锁定,测试通过后再切换
sudo guix time-machine --channels=/etc/guix/channels-lock.scm -- \
  system reconfigure /etc/config.scm

5.7 通道的高级用法

5.7.1 通道的优先级

当多个通道定义了同名包时,Guix 按照 channels.scm 中的顺序确定优先级——后面的通道优先级更高

(list
  ;; 官方通道(基础)
  (channel (name 'guix) ...)

  ;; 第三方通道(扩展)
  (channel (name 'nonguix) ...)

  ;; 自定义通道(最高优先级,可以覆盖前面的包)
  (channel (name 'mychannel) ...))

5.7.2 覆盖官方包

;; mychannel/packages/vim.scm
(define-module (mychannel packages vim)
  #:use-module (guix packages)
  #:use-module (gnu packages vim))

;; 覆盖官方的 vim,添加自定义补丁
(define-public vim
  (package
    (inherit (@ (gnu packages vim) vim))
    (source (origin
              (inherit (package-source (@ (gnu packages vim) vim)))
              (patches
                (append
                  (origin-patches
                    (package-source (@ (gnu packages vim) vim)))
                  (list (local-file "my-vim-patch.patch"))))))))

5.7.3 通道的 News 机制

;; news.scm — 通道更新日志
(channel-news
  (version 0)
  (entry (commit "abc1234...")
         (title (en "Added my-vim 9.1.0-custom")
                (zh "添加了 my-vim 9.1.0-custom"))
         (body (en "A custom build of Vim with feature X enabled.")
               (zh "启用了 X 功能的自定义 Vim 构建。"))))
# 查看通道更新新闻
guix pull --news

5.8 使用 guix time-machine

guix time-machine 是版本管理的终极工具——在不切换通道的情况下使用特定版本的 Guix 执行命令。

5.8.1 基本用法

# 使用 2025 年 1 月 1 日的 Guix 版本安装包
guix time-machine --commit=abc1234 -- install vim

# 使用特定 channels 文件
guix time-machine --channels=channels-old.scm -- install vim

5.8.2 创建完全可重现的环境

# 1. 锁定通道版本
guix describe --format=channels > channels.scm

# 2. 创建环境清单
cat > manifest.scm << 'EOF'
(specifications->manifest
  '("python"
    "python-numpy"
    "gcc-toolchain"))
EOF

# 3. 重现环境(任何机器都可以)
guix time-machine --channels=channels.scm -- \
  shell --manifest=manifest.scm

5.8.3 time-machine 的实际场景

场景一:CI/CD 管道

# .gitlab-ci.yml
build:
  script:
    - guix time-machine --channels=channels.scm -- \
        shell --manifest=manifest.scm -- \
        make && make test

场景二:生产环境部署

# 部署脚本
#!/bin/bash
guix time-machine --channels=channels-2026-01.scm -- \
  system reconfigure /etc/config.scm

5.9 通道维护最佳实践

5.9.1 通道仓库管理

实践 说明
频繁测试 每次提交前运行 guix buildguix lint
使用 CI 设置 CI 自动构建所有包
版本标签 使用 Git tag 标记稳定版本
CHANGELOG 维护更新日志
提交规范 使用一致的 commit message 格式

5.9.2 通道的安全考虑

# 验证通道签名
guix pull --verify

# 查看通道的签名信息
git -C ~/.config/guix/current log --show-signature

# 只信任有签名的 commit
guix pull --disable-authentication  # ⚠️ 不推荐

⚠️ 注意:永远不要使用 --disable-authentication 在生产环境中拉取通道。签名验证是防止供应链攻击的关键安全机制。

5.9.3 通道的 Git 钩子

#!/bin/bash
# .git/hooks/pre-push — 推送前自动检查

# 检查所有包定义是否可构建
guix build -L . my-package || {
  echo "Build failed, push aborted."
  exit 1
}

# 运行 lint 检查
guix lint -L . my-package || {
  echo "Lint warnings found."
  exit 1
}

5.10 通道故障排除

问题 原因 解决方案
guix pull 极慢 Git 仓库较大 使用 --depth=1 或镜像
签名验证失败 通道被篡改或密钥变更 检查通道 URL 和 introduction
包定义冲突 多通道定义同名包 调整通道顺序
guix pull 后找不到包 通道未正确加载 检查模块路径和 guix describe
时间机器失败 旧 commit 无法构建 检查是否有过期的源码 URL
# 诊断通道问题
guix describe --verbose
guix pull --verbose

# 清理通道缓存
rm -rf ~/.cache/guix/channels
guix pull

5.11 通道操作速查表

操作 命令
查看通道 guix describe
更新通道 guix pull
锁定通道 guix describe --format=channels > channels.scm
使用特定通道 guix pull --channels=channels.scm
时间机器 guix time-machine --channels=... -- <cmd>
查看新闻 guix pull --news
验证签名 guix pull --verify
清理缓存 rm -rf ~/.cache/guix/channels

5.12 总结

本章深入讲解了 Guix 通道机制:

  1. 通道概念——Git 仓库形式的包定义来源
  2. 官方通道——默认的 guix 通道
  3. 第三方通道——Nonguix、guix-science 等扩展
  4. 自定义通道——创建和维护自己的通道
  5. 版本锁定——通过 channels.scm 实现可重现
  6. 时间机器——guix time-machine 的强大功能
  7. 安全与维护——签名验证和最佳实践

下一章我们将学习 Guix System 的声明式系统配置。


扩展阅读