Wai Hon's Blog

Introducing Guix Pull Ready

2026-11-07 #linux #guix

Contents

Problem: Potential Local Source Build

In my previous post on switching to GNU Guix, I shared my experience migrating my home server from Arch Linux to Guix System. One of the main challenges I highlighted was dealing with unexpected local compilations from source after running guix pull.

Unlike traditional binary distributions, GNU Guix is fundamentally a source-based distribution backed by substitute binary caches. When running guix pull, Guix updates channel definitions according to ~/.config/guix/channels.scm (which by default tracks the tip of the official repository’s master branch unless pinned to a specific commit). If the commit being pulled is recent, the official build farm (ci.guix.gnu.org) may still be evaluating package definitions or compiling binaries.

When prebuilt substitutes are not yet available for that commit, Guix falls back to its core design: building packages locally from source. On a modest home server or laptop, updating can unexpectedly trigger hours of local compilation for large software like Rust, WebKit, or compiler toolchains, pegging CPU cores and driving up temperatures.

In that previous article, my temporary workaround was manual and imprecise: pinning guix pull in ~/.config/guix/channels.scm to a commit from a day or two earlier, hoping that build servers had finished their work by then. While that reduced surprise builds, it remained an educated guess. I wanted a reliable, automated way to pull a commit whose CI evaluation has already completed.

Solution: Guix Pull Ready

To solve this problem, I built guix-pull-ready and set up a public instance running at guix-pull-ready.whhone.com.

The service continuously tracks evaluations on Cuirass, Guix’s continuous integration system, and determines the latest master commit whose substitutes have completed building. With this service, you no longer need to guess which commit is safe to pull.

Quick Start Commands

The primary API provided by the service is /channels.scm. You can pull the newest ready commit on-demand without modifying your permanent channel configuration:

guix pull -C <(curl -fsSL "https://guix-pull-ready.whhone.com/channels.scm")

Even better, GNU Guix provides a built-in downloaded-channels procedure. You can configure ~/.config/guix/channels.scm to automatically query the service on every guix pull:

(downloaded-channels
  "https://guix-pull-ready.whhone.com/channels.scm")

If you also maintain your own custom or local channels, downloaded-channels supports an #:append keyword argument so you can combine the ready upstream commit with your extra channels:

(downloaded-channels
  "https://guix-pull-ready.whhone.com/channels.scm"
  #:append (list (channel
                   (name 'my-channel)
                   (url "https://example.org/my-channel.git"))))

With this setup, running a routine guix pull always fetches a commit whose CI evaluation has finished building.

Coordinated Nonguix Support

Many users rely on the third-party Nonguix channel for non-free firmware or kernels. Updating multiple channels independently often results in substitute misses if the channels were evaluated against mismatched commits.

guix-pull-ready coordinates both channels by matching evaluations on cuirass.nonguix.org with the exact Guix commit they were built against:

(downloaded-channels
  "https://guix-pull-ready.whhone.com/channels.scm?additional_channels=nonguix")

This ensures substitutes are ready across both Guix and Nonguix simultaneously.

Security of downloaded-channels and trusted-channels.scm

A natural question when pointing ~/.config/guix/channels.scm to an external URL is security: what prevents a remote server from returning a malicious channel repository?

Modern GNU Guix addresses this directly through its channel trust mechanism:

  1. Restricted Evaluation: downloaded-channels does not execute arbitrary Guile code. It parses the remote file inside a restricted sandbox that only accepts channel declarations.
  2. trusted-channels.scm Verification: Before pulling, Guix verifies that every channel returned by the remote URL is explicitly trusted. It checks ~/.config/guix/trusted-channels.scm (or, if that file is absent, falls back to trusting only your currently active channels from guix describe). If a remote response ever attempts to introduce an untrusted channel URL or omit a valid cryptographic channel introduction (make-channel-introduction), guix pull refuses to proceed.
  3. End-to-End Commit Authentication: Once the channel is matched against your trusted list, Guix fetches directly from the official Git repository and verifies the commit’s OpenPGP signature against the channel’s authorized keyring.

In short, guix-pull-ready cannot alter where code comes from or bypass signature verification. Its only role is advising guix pull which already-authenticated commit hash to check out. (Note: when adopting a new channel like Nonguix via downloaded-channels for the first time, make sure Nonguix and its channel introduction are either already active in guix describe or listed in ~/.config/guix/trusted-channels.scm.)

How It Works Under the Hood

The service is designed around how GNU Guix continuous integration processes updates:

The server is implemented as a lightweight, zero-dependency daemon written in Go (standard library only) that compiles down to a single static binary. All user queries are served directly from an in-memory snapshot, keeping response times sub-millisecond and acting as a shared cache that avoids placing repeated read load on ci.guix.gnu.org.

Upstream Context and Project Status

There are two important aspects regarding how this project relates to the broader GNU Guix community.

Official Upstream Efforts

While chatting in the #guix IRC channel on Libera.Chat, I learned that maintainers and contributors are actively working on official support for “perfect evaluation”.

Having native support inside Guix itself (allowing guix pull to automatically negotiate ready substitute sets without external helpers) would be the ideal long-term solution. I hope that work lands upstream in the official Guix distribution soon. Until then, guix-pull-ready serves as a practical, lightweight community stopgap.

Project Status and LLM Assistance

The GNU Guix project maintains a strict policy against accepting LLM-generated contributions. I understand and completely respect this decision. Preserving copyright clarity and code comprehension is essential for a foundational operating system.

guix-pull-ready is an LLM-assisted project. It will remain a community effort hosted in its own repository rather than being proposed as an upstream patch.

If you prefer not to use LLM-assisted tools, that is completely understandable, and you do not have to use it. For those who find the substitute wait frustrating, however, this tool is available to make your update experience smoother.

Conclusion

GNU Guix offers strong control, reproducibility, and peace of mind for managing system infrastructure. Having updates occasionally trigger unintended multi-hour source builds was one of the few practical frictions in my daily workflow.

I have been using guix-pull-ready for the past few weeks, and that friction is now largely gone. Updating Guix now feels much closer to the predictable binary updates of Arch Linux or Debian.

If you are running GNU Guix and want predictable updates, feel free to try the public instance at guix-pull-ready.whhone.com or check out the source on GitHub.