强曰为道

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

第五章 通道与版本管理

第五章:通道与版本管理

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-driverNVIDIA 显卡驱动
steamSteam 游戏平台
chromiumChromium 浏览器
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说明
nonguixhttps://gitlab.com/nonguix/nonguix非自由软件
guix-sciencehttps://gitlab.com/guix-science/guix-science科学计算包
guix-science-nonfreehttps://gitlab.com/guix-science/guix-science-nonfree非自由科学计算包
guix-pasthttps://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 的声明式系统配置。


扩展阅读