Hello Guix-devel,

I wanted to run Guix System in a VM, but didn’t find any guides on
doing this in my hypervisor of choice, Cloud Hypervisor[0]. I figured
I'd write it up for others.

Broadly speaking, Cloud Hypervisor can either:

* Boot your kernel/initrd directly, though this prevents selecting a generation.
* Boot a light firmware (hypervisor-fw), which scans your ESP for the
Boot Loader Specification[1] file. This isn't currently supported on
Guix.
* Boot a UEFI environment via edk2[2]. This can boot GRUB2 EFI, so I
picked this.

To boot via UEFI, I generated a raw GPT image with ESP and rootfs
using: `guix system image -t efi-raw my-system.scm`. (Note: Guix 1.4
used MBR for this, so you'll need a more recent Guix.)

This VM will be administered over SSH, with a local terminal as a
fallback. Cloud Hypervisor can provide serial and/or console (in the
form of virtio-console). GRUB2 doesn’t support virtio-console, so I
chose serial.

Here’s a minimal system config:

```
(use-modules (gnu))

(operating-system
  (host-name "cloud-hypervisor-guest")
  (bootloader (bootloader-configuration
        (bootloader grub-efi-bootloader)))
  (kernel-arguments (list "console=ttyS0"))
  (file-systems (cons (file-system
                        ; The label that 'efi-raw' generates.
                        (device (file-system-label "Guix_image"))
                        (mount-point "/")
                        (type "ext4"))
                      %base-file-systems)))
```

Now that we have an image, we can execute it with the edk2 firmware[3]:

```
$ cloud-hypervisor –firmware ./CLOUDHV.fd --disk path=my-image.raw
--memory size=4G --serial tty --console off
[...]
This is the GNU system.  Welcome.
cloud-hypervisor-guest login:
```

Success!

Other findings:

* systemd-boot support in Guix[4] will allow us to use the lighter
hypervisor-fw firmware to boot the guest. This should allow using the
console rather than serial too.
* When I deploy this on my VM host, I run the same cloud-hypervisor
command in my init, but use `--serial pty` to allow me to access the
local terminal via `screen /dev/pts/2`.
* I briefly experimented with getting output over console working.
"console=hvc0 agetty.tty=hvc0" on your kernel command line will allow
kernel/agetty i/o to work on the console.
* Some stale docs on virtio support in initrd.[5]
* cloud-hypervisor is not packaged for Guix. Maybe one day I will,
if/when Guix is my host.

Regards,
Tom

0. https://github.com/cloud-hypervisor/cloud-hypervisor
1. https://uapi-group.org/specifications/specs/boot_loader_specification/
2. https://github.com/cloud-hypervisor/edk2
3. https://github.com/cloud-hypervisor/edk2/releases
4. https://lists.gnu.org/archive/html/guix-devel/2025-08/msg00024.html
5. https://codeberg.org/guix/guix/pulls/2720

Reply via email to