Introducing Guix Pull Ready
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:
- Restricted Evaluation:
downloaded-channelsdoes not execute arbitrary Guile code. It parses the remote file inside a restricted sandbox that only accepts channel declarations. trusted-channels.scmVerification: 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 fromguix describe). If a remote response ever attempts to introduce an untrusted channel URL or omit a valid cryptographic channel introduction (make-channel-introduction),guix pullrefuses to proceed.- 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:
- Evaluations and Jobs: When commits are pushed to GNU Guix, the build farm (Cuirass) creates an evaluation with build jobs for all packages on each architecture (such as
x86_64-linux,aarch64-linux,powerpc64le-linux, andriscv64-linux). - Background Sync: The service polls Cuirass in the background and caches job statuses locally in an atomic database. This ensures instant HTTP responses without running into upstream CI timeouts.
- Ready Commit Lookup: Finds the newest commit whose evaluation has
0pending builds remaining and whoseguixjobset has succeeded. - Automatic Reconciliation: Occasionally, Cuirass’s denormalized jobs table can lag behind canonical build records when jobs finish, leaving a completed job marked as pending. The poller cross-checks stuck jobs against Cuirass’s canonical build records so completed evaluations cleanly transition to ready state.
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.