Next: , Previous: , Up: System Configuration   [Contents][Index]

3.3 Guix System Image API

Historically, Guix System is centered around an operating-system structure. This structure contains various fields ranging from the bootloader and kernel declaration to the services to install.

Depending on the target machine, that can go from a standard x86_64 machine to a small ARM single board computer such as the Pine64, the image constraints can vary a lot. The hardware manufacturers will impose different image formats with various partition sizes and offsets.

To create images suitable for all those machines, a new abstraction is necessary: that’s the goal of the image record. This record contains all the required information to be transformed into a standalone image, that can be directly booted on any target machine.

(define-record-type* <image>
  image make-image
  (name               image-name ;symbol
                      (default #f))
  (format             image-format) ;symbol
  (target             image-target
                      (default #f))
  (size               image-size  ;size in bytes as integer
                      (default 'guess))
  (operating-system   image-operating-system  ;<operating-system>
                      (default #f))
  (partitions         image-partitions ;list of <partition>
                      (default '()))
  (compression?       image-compression? ;boolean
                      (default #t))
  (volatile-root?     image-volatile-root? ;boolean
                      (default #t))
  (substitutable?     image-substitutable? ;boolean
                      (default #t)))

This record contains the operating-system to instantiate. The format field defines the image type and can be efi-raw, qcow2 or iso9660 for instance. In the future, it could be extended to docker or other image types.

A new directory in the Guix sources is dedicated to images definition. For now there are four files:

Let’s have a look to pine64.scm. It contains the pine64-barebones-os variable which is a minimal definition of an operating-system dedicated to the Pine A64 LTS board.

(define pine64-barebones-os
   (host-name "vignemale")
   (timezone "Europe/Paris")
   (locale "en_US.utf8")
   (bootloader (bootloader-configuration
                (bootloader u-boot-pine64-lts-bootloader)
                (targets '("/dev/vda"))))
   (initrd-modules '())
   (kernel linux-libre-arm64-generic)
   (file-systems (cons (file-system
                        (device (file-system-label "my-root"))
                        (mount-point "/")
                        (type "ext4"))
   (services (cons (service agetty-service-type
                             (extra-options '("-L")) ; no carrier detect
                             (baud-rate "115200")
                             (term "vt100")
                             (tty "ttyS0")))

The kernel and bootloader fields are pointing to packages dedicated to this board.

Right below, the pine64-image-type variable is also defined.

(define pine64-image-type
   (name 'pine64-raw)
   (constructor (cut image-with-os arm64-disk-image <>))))

It’s using a record we haven’t talked about yet, the image-type record, defined this way:

(define-record-type* <image-type>
  image-type make-image-type
  (name           image-type-name) ;symbol
  (constructor    image-type-constructor)) ;<operating-system> -> <image>

The main purpose of this record is to associate a name to a procedure transforming an operating-system to an image. To understand why it is necessary, let’s have a look to the command producing an image from an operating-system configuration file:

guix system image my-os.scm

This command expects an operating-system configuration but how should we indicate that we want an image targeting a Pine64 board? We need to provide an extra information, the image-type, by passing the --image-type or -t flag, this way:

guix system image --image-type=pine64-raw my-os.scm

This image-type parameter points to the pine64-image-type defined above. Hence, the operating-system declared in my-os.scm will be applied the (cut image-with-os arm64-disk-image <>) procedure to turn it into an image.

The resulting image looks like:

 (format 'disk-image)
 (target "aarch64-linux-gnu")
 (operating-system my-os)
  (list (partition
         (inherit root-partition)
         (offset root-offset)))))

which is the aggregation of the operating-system defined in my-os.scm to the arm64-disk-image record.

But enough Scheme madness. What does this image API bring to the Guix user?

One can run:

mathieu@cervin:~$ guix system --list-image-types
The available image types are:

   - unmatched-raw
   - rock64-raw
   - pinebook-pro-raw
   - pine64-raw
   - novena-raw
   - hurd-raw
   - hurd-qcow2
   - qcow2
   - iso9660
   - uncompressed-iso9660
   - tarball
   - efi-raw
   - mbr-raw
   - docker
   - wsl2
   - raw-with-offset
   - efi32-raw

and by writing an operating-system file based on pine64-barebones-os, you can customize your image to your preferences in a file (my-pine-os.scm) like this:

(use-modules (gnu services linux)
             (gnu system images pine64))

(let ((base-os pine64-barebones-os))
    (inherit base-os)
    (timezone "America/Indiana/Indianapolis")
      (service earlyoom-service-type
                (prefer-regexp "icecat|chromium")))
      (operating-system-user-services base-os)))))


guix system image --image-type=pine64-raw my-pine-os.scm


guix system image --image-type=hurd-raw my-hurd-os.scm

to get an image that can be written directly to a hard drive and booted from.

Without changing anything to my-hurd-os.scm, calling:

guix system image --image-type=hurd-qcow2 my-hurd-os.scm

will instead produce a Hurd QEMU image.

Next: Using security keys, Previous: Customizing the Kernel, Up: System Configuration   [Contents][Index]