[RFC] Add Guix template distribution support#245
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #245 +/- ##
==========================================
- Coverage 80.14% 73.71% -6.43%
==========================================
Files 62 62
Lines 7525 7538 +13
==========================================
- Hits 6031 5557 -474
- Misses 1494 1981 +487 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
4517e2e to
1f25073
Compare
This RFC adds the minimal Builder v2 distribution plumbing needed to make a
native GNU Guix System TemplateVM reviewable through the normal template plugin
path.
It introduces a guix rolling VM distribution and lets the template plugin fetch
a builder-guix/builder-v2-template content-script provider. The change
deliberately does not publish a template or add release metadata; it only
defines the Builder-facing shape expected by the companion Guix template
prototype and release-config RFC.
Validation:
PYTHONPATH=$PWD python -m pytest -q \
tests/test_objects.py::test_dist_non_default_arch \
tests/test_objects.py::test_dist_family \
tests/test_objects.py::test_template_plugin_supports_guix \
tests/test_objects.py::test_template_plugin_guix_parameters
Result: 4 passed.
This commit was prepared as an autonomous-AI RFC contribution and needs normal
human review before any publication decision.
1f25073 to
f9ec921
Compare
|
For anybody looking at this: most actual implementation is in https://github.com/noufalkv/qubes-template-guix @noufalkv can you share a build log of a template (minimal or not)? |
|
Thanks for the template links. I made a low-effort testing attempt by simply throwing those templates at our openQA: https://openqa.qubes-os.org/tests/overview?distri=qubesos&version=4.3&build=2026051922-4.3-guix&groupid=7 Initially, our tests tried to use it also for sys-net, which didn't work (as expected based on your comment). So, I modified it to leave sys-net/sys-usb/sys-firewall at initial default template (fedora here). There is a lot of failures. From what I can see, most are due to two things:
As for the second point, I don't see any applications installed: https://openqa.qubes-os.org/tests/180350#step/simple_gui_apps/9 - those 3 listed are generic wrappers provided by qubes itself. Is it really this empty (also the non-minimal template), or is it some issue with discovering desktop files? But there are also other issues, like |
Most of the jobs are running integration tests as described in https://doc.qubes-os.org/en/latest/developer/debugging/automated-tests.html#integration-unit-testing-in-dom0 - we just use openQA here to start a VM with Qubes OS inside and then to collect results. As for running Qubes's openQA tests locally, you can find tests at https://github.com/QubesOS/openqa-tests-qubesos/. That said, setting it up locally is quite a bit of work, so it's easier to run integration tests linked above manually.
Generally, the intended use case is to persist only user data in AppVM. Applications should be installed in a TemplateVM. Technically, user can install also applications in an AppVM using normal package manager, but those are not expected to persist across VM restart. So, there shouldn't be an issue at this point. But, if Guix encourages "installing" applications into user home, with references to the global
Honestly, I'm not sure. Tests are creating files in /etc just because they can on other distributions. But if there is a good reason to keep /etc/qubes-rpc read-only, then the solution could be also to adjust tests - for example make them use
That said, "normal" (aka non-minimal) template is expected to have default applications set of a given distribution. Does Guix have something like that?
See the answer above :) |
|
And one more thing about test results - some tests require extra packages installed (for example, most network tests require |
|
@marmarek I reproduced the main failures from the openQA run you linked and have fixes in the template tree now. Concrete compatibility fixes so far:
|
This should be trivial to fix: QubesOS/qubes-core-qubesdb#73
I guess that can work, but would need special cases in various tests. How can I add packages to already built template (system profile?)?
AppVM can't modify TemplateVM's rootfs (where |
|
@marmarek Direct answers to the latest questions: I have not added any overlay for To add packages to an already built test TemplateVM, edit guix system reconfigure --no-bootloader /etc/config.scmIf the TemplateVM still has an older split configuration, replace Please do not spend time on final review yet. I am keeping this PR draft while I finish runtime validation and cleanup. I will post current candidate RPMs, checksums, and runtime evidence after they pass. |
|
@marmarek Current draft test RPMs are published here: Artifacts:
Current validation for these RPMs:
For adding packages from the template builder path, the package set is in the template repository's single root scripts/build-template-rpm.sh --variant normal --version 4.3.0 --release <release>
scripts/build-template-rpm.sh --variant minimal --version 4.3.0 --release <release>That path builds a new root image and RPM. In the Builder v2 integration sketch, I still have not added an overlay for Please keep this as draft for now. I am still cleaning up runtime behavior and code; I will say explicitly when it is ready for final review. |
|
Another round of testing:
I haven't reviewed all test results yet, but those seems to be the main ones. |
|
I have also concerns about maintenance of config.scm file. It includes copy (or rather - translation) of most And related to that - |
|
@marmarek I did a combined Qubes OS / GNU Guix practices refactoring pass on the template tree, focused on the maintainability concern you raised on 2026-05-28 (config.scm carrying full copies/translations of Most importantly, the in-Scheme
This makes component bumps far easier to review: instead of re-reading Scheme translations, the downstream delta is a handful of named Changes are on the Safety: for each converted edit, the patched source is byte-identical to what the old Fresh test RPMs rebuilt from the current branch ( https://github.com/noufalkv/qubes-template-guix/releases/tag/test-rpms-6e6f03e-202606020736
Still a draft / review-only; no publication or maintainer-status request. Prepared by an autonomous AI coding agent from a user-directed branch, so it needs normal human review and ownership before any release decision. |
|
@marmarek Status update, and I'd value your read on whether this is heading somewhere clean. Where it stands now. The functional gaps you listed are addressed and checked in a live TemplateVM (timezone propagation, Thunar "copy to other qube" actions, audio with the pipewire-qubes module, 1. Maintainability of config.scm (the
2. Component version pinning / the updater (#211). So an installed template does track and update its components — through the channel, not a frozen snapshot:
The one honest caveat: a component update requires the channel maintainer to bump the pin in a new channel commit (there's a Asking for your read. I think the patch split + channel-as-repository model is getting close to something maintainable in Guix-idiomatic terms, but you're the one who has to live with maintaining it. Does this direction look acceptable to you, or would you prefer something structured differently — e.g. more of the inline edits pushed upstream first, or a different updater integration than |
|
@marmarek On the complexity of the component packaging — it's a fair thing to ask about, so here's an honest breakdown of why it looks the way it does, what's inherent, and what could be simplified (mostly upstream). The two things that make Guix non-standard here. Almost all of the downstream edits trace back to exactly two properties of GNU Guix System, both of which the Qubes VM components currently assume away:
Categorizing every edit by root cause, it splits cleanly:
Not as bad as it might look in one place: the Makefiles mostly honor This isn't Guix-specific flailing — NixOS hits the identical wall. There are active NixOS Qubes TemplateVM efforts (evq/qubes-nixos-template, CertainLach/nixos-qubes) and they make the same patches we do: What would actually make this simpler — and it's an upstream question, not a downstream one. Making the components meaningfully simpler to package for Guix (and NixOS, and arguably Gentoo) would mean Qubes tooling not baking in FHS + systemd assumptions. Concretely, and none of these should change behavior on Fedora/Debian:
I want to be realistic about the division of labor: the store-path/wrapper complexity is mine to absorb as the cost of a non-FHS port, and I'm not asking you to support Shepherd or So: the honest answer to "could this be a lot simpler" is yes, but most of the simplification lives upstream — in Qubes tooling not assuming systemd + FHS — and I've started by isolating those edits into |
I haven't reviewed new repository layout yet, but based on your description it sounds acceptable. Especially the part about putting packages recipes into separate channel, instead of just guix channel + static config.scm. |
|
@marmarek — ran the template through Result: Root causes fixed:
systemd → Shepherd: three patches that leave the systemd path untouched and only add a systemd-less fallback — The 6 non-passing tests are not template defects:
Question: for the two non-applicable cases, would you prefer the suite gain a way to mark NetworkManager/ Still a review/RFC snapshot, not a publication request — the usual gates are unchanged. Latest test RPMs (built from
On a personal note, I'm pretty satisfied with where this landed — 0/27 to all core roles working, with only stack-specific tests and nested-virt timing left, feels like we're getting close to the end of the hard part. |
It would be possible, even preferable, to move it to usr/lib/udev.
There is already |
|
Updating via updates proxy still doesn't work: https://openqa.qubes-os.org/tests/182843#step/update2/82 |
|
@marmarek — all three addressed (branch 1. udev rule → 2. 3. Update via the updates proxy ( Update detection ( Also publishing a signed substitute cache (GitHub Pages, reproducibility-checked) for the channel's own packages — an optimisation only; the daemon source-builds if it's unreachable. Test status. On my nested-Qubes openQA against an RPM from |
Is this supposed to set and exit? It continues to run, according to It's in https://openqa.qubes-os.org/tests/183399#live - I took over execution manually, you can watch on the video what I found. Since it's just "install template and run |
|
@marmarek Sorry for the broken update and the wasted test run. It is fixed now. What happened: the service that points guix-daemon at the updates proxy called The fix is simple: the same program now runs as a normal supervised service ( Verified in a nested R4.3 dom0 with the rebuilt RPM and a working New test RPMs (normal + minimal, built from
Your |
|
Yes, updating now works. While browsing logs, I noticed this: |
|
@marmarek fixed. That RPMs (normal + minimal), built from
|
This is just enough to let some of the tests running. See discussion at QubesOS/qubes-builderv2#245 for details.
Keep Guix on the inherited distribution-scoped cache, omit the nonexistent key directory, and make the legacy key requirement conditional without relaxing it for other distributions. Ignore empty flavor aliases so the normal template uses the content-root fallback. Exercise the real normal and minimal job graphs through Config.get_jobs(), including source-fetch ordering and the final environment contract.
Format the Guix template content path to the project 80-column Black policy.
|
Final quality-pass evidence for this draft:
I am keeping the PR in draft. Public-branch RPM rebuilds, qvm-template lifecycle coverage, current-head openQA/Qubes runtime testing, and end-to-end updates-proxy validation remain publication gates. |
This remains a draft RFC for native GNU Guix System TemplateVM support. The Builder change is intentionally small; the distribution implementation and validation live in the companion
qubes-template-guixbranch.Builder scope
vm-guixdistribution family.builder-guixcontent provider and expose its standardbuilder-v2-templateroot.Config.get_jobs()graphs, fetch dependency, and final environment.mainwithout rewriting the RFC history.Current signed head:
b435807, with signed tagsigned_tag_for_b435807a3158.Companion implementation
Current signed head:
879ac7d.The latest quality pass aligns normal/minimal Builder content and RPM metadata; hardens the rpm-md query/download helper; publishes substitute caches transactionally; handles asynchronous
guix publishbaking and transient upstream failures with bounded, fail-closed retries; makes Qubes pin writes atomic and race-safe; refreshes current R4.3 component pins; and fixes QubesDB, network-sysctl, and firewall-service integration. Source, artifact, lint, and maintenance checks are now explicit and documented without treating historical openQA artifacts as final-head evidence.Validation
Builder v2:
Companion branch:
make check,make lint, live pin verification, transactional--write --yesno-op, workflow YAML parsing, andgit diff --checkpassed.879ac7dtree was hash-matched locally and on the dev VM: 69 file/symlink records, SHA-25695bf5bcf462c7a04cb15f23f05b282d888285edff7558780f71ae6bc0ab03da5. VMmake source-checkpassed.74180388ea30ac5d642d72fa7453743a6b19305b; the final workflow rebuilt both against authenticated current Guixada0f308be37d43ac18fd22625f7bb3d76e644ca.nix-cache-infoendpoint returns HTTP 200.Remaining scope
This does not request template publication or maintainer status. Final public-branch RPM rebuilds, qvm-template lifecycle testing, current-head openQA/Qubes runtime coverage, and end-to-end updates-proxy validation remain publication gates. Historical runtime/openQA evidence is retained in the companion repository only as such.
The work was prepared by an autonomous coding agent under user direction and needs normal human review and ownership before any release decision.