Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions guix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# SourceOS on Guix — migration spike

Status: **spike** (additive; does not touch the Nix build). Decision recorded:
migrate the SourceOS substrate from Nix → Guix, driven by Nix-project governance
instability. `nonguix` gives us the same nonfree posture we already run under
nixpkgs `allowUnfree` — the freedom stance is unchanged; we are **not** chasing
the FSF/FSDG zero-blob badge.

## What's here
- `channels.scm` — upstream Guix + `nonguix` (the `allowUnfree` analog), with
nonguix's published signing introduction. **Pin the commits** via
`guix pull && guix describe` on the first runner (offline hashes can't be real).
- `system/workstation.scm` — the first parity target: a plain x86_64 workstation
using the real Linux kernel + firmware + CPU microcode from nonguix.

## Build (on a Linux runner — NOT macOS)
Requires the `guix-daemon` on Linux; it cannot run from a macOS session.

```bash
guix time-machine -C guix/channels.scm -- system build guix/system/workstation.scm
guix time-machine -C guix/channels.scm -- system vm guix/system/workstation.scm # boot-test
```

## Why the spike is scoped this way
The philosophy is settled; the only real risk is **nonguix hardware-enablement
maturity** for our two hardest targets. The spike proves them in order:

1. **x86_64 workstation** (`system/workstation.scm`) — baseline parity.
2. **Apple Silicon / Asahi on Guix** — exists but far less trodden than Asahi-on-Nix.
3. **CUDA / GPU model-serving node** — packaged via nonguix; smaller/less
battle-tested than nixpkgs.

If 2 and 3 build and boot with working hardware, the migration path is real. If
one hits a wall, we've learned it cheaply — before touching the estate.

## Phased plan (prove-then-cut, same discipline as the board parity)
1. **Spike** — this directory: prove the three targets build/boot.
2. **Parity** — re-express `modules/nixos/*` as Guix services/system config, the
base-OS profiles first (SourceOS territory).
3. **Cutover** — a Guix image-build workflow alongside `nix-build-images`; run
both; flip the default once parity holds. Nix stays until then.

## Honest limits
- These files are authored and reviewed but **not build-validated** here (no guix
on macOS). First `guix system build` on a Linux runner is the real gate.
- Reproducibility is not achieved until `channels.scm` commits are pinned.
- Lix (drop-in Nix fork) remains the cheaper stability-only hedge if the Guix
spike's hardware targets prove too immature; keep it in reserve.
30 changes: 30 additions & 0 deletions guix/channels.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
;;; SourceOS Guix channels — the Nix -> Guix migration spike.
;;;
;;; Two channels: upstream Guix, plus `nonguix` — Guix's analog of nixpkgs'
;;; `allowUnfree`. nonguix provides the real Linux kernel + firmware + CPU
;;; microcode + proprietary drivers/CUDA the estate's hardware needs. This is the
;;; SAME nonfree posture the estate already runs under nixpkgs + allowUnfree; the
;;; freedom stance is unchanged (we are NOT chasing the FSF/FSDG zero-blob badge).
;;;
;;; Reproducibility: PIN `commit` on both channels via `guix pull && guix describe`
;;; on the first Linux build runner, then commit the pinned result here. Real
;;; commit hashes cannot be fabricated offline — the branch pins below are only
;;; the spike starting point, not a reproducible pin.
;;;
;;; The nonguix `introduction` below is its PUBLISHED security bootstrap (the
;;; signing anchor). VERIFY it against the current nonguix README before the first
;;; pull — a wrong commit/fingerprint fails channel authentication by design.

(list (channel
(name 'guix)
(url "https://git.savannah.gnu.org/git/guix.git")
(branch "master"))
(channel
(name 'nonguix)
(url "https://gitlab.com/nonguix/nonguix")
(branch "master")
(introduction
(make-channel-introduction
"897c1a470da759236cc11798f4e0a5f7d4d59fbc"
(openpgp-fingerprint
"2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5")))))
67 changes: 67 additions & 0 deletions guix/system/workstation.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
;;; SourceOS Guix workstation profile (x86_64) — Nix -> Guix migration spike.
;;;
;;; Demonstrates the nonfree posture: the real Linux kernel + `linux-firmware`
;;; + CPU `microcode-initrd` from nonguix (the `allowUnfree` equivalent), not
;;; `linux-libre`. This is the first parity target — a plain workstation image —
;;; before the two hard ones (Asahi/Apple-Silicon, CUDA model-serving node).
;;;
;;; Build on a LINUX runner with the channels in ../channels.scm applied:
;;; guix time-machine -C guix/channels.scm -- \
;;; system build guix/system/workstation.scm # realize the closure
;;; guix time-machine -C guix/channels.scm -- \
;;; system vm guix/system/workstation.scm # boot-test in a VM
;;; NOT buildable from macOS (needs the guix-daemon on Linux).

(use-modules (gnu)
(nongnu packages linux)
(nongnu system linux-initrd))
(use-service-modules desktop ssh)
(use-package-modules certs ssh version-control)

;; Define the layout once so the OS and the bootloader share the same object.
(define %keyboard-layout (keyboard-layout "us"))

(operating-system
(host-name "sourceos-workstation")
(timezone "UTC")
(locale "en_US.utf8")
(keyboard-layout %keyboard-layout)

;; nonguix: real Linux + firmware + CPU microcode (the allowUnfree equivalent).
(kernel linux)
(firmware (list linux-firmware))
(initrd microcode-initrd)

(bootloader (bootloader-configuration
(bootloader grub-efi-bootloader)
(targets '("/boot/efi"))
(keyboard-layout %keyboard-layout)))

(file-systems (append
(list (file-system
(mount-point "/")
(device (file-system-label "SOURCEOS_ROOT"))
(type "ext4"))
(file-system
(mount-point "/boot/efi")
(device (file-system-label "SOURCEOS_EFI"))
(type "vfat")))
%base-file-systems))

(users (cons (user-account
(name "sourceos")
(comment "SourceOS operator")
(group "users")
(supplementary-groups '("wheel" "netdev" "audio" "video")))
%base-user-accounts))

(packages (append (list nss-certs git)
%base-packages))

;; openssh (keys only) prepended to the desktop stack (which already provides
;; NetworkManager / wpa-supplicant — do not re-declare them here).
(services (cons* (service openssh-service-type
(openssh-configuration
(openssh openssh-sans-x)
(password-authentication? #f)))
%desktop-services)))