Guix - hpaluch/hpaluch.github.io GitHub Wiki

Guix

Guix is special package manager and also OS based on that package manager. Unlike standard distributions every package has unique path based on its input, so it is naturally possible to have many versions of same packages.

To use packages one has to create profile - which is basically folder with set of links to active packages.

It has several advantages:

  • coexistence of any number and any versions of packages - there is never path conflict - providing many (not all!) benefits of Containers Without Containers
  • fully utilizing sharing files - shared libraries and even hard-linking duplicate files (because repository copy is always "read only"). Compare that with Ubuntu Snap that is unable to use shared libraries (Flatpack has partial support for "Runtimes").
  • "hermetic" builds: all package dependencies must be declared to ensure that nothing is missing
  • independent collections of packages ("profiles") - so you can have as many python versions as you want - not just single (pointing on ArchLinux and/or Fedora - these are seriously affected by this limitation)
  • real transactional updates - just symlink target changes when update or rollback is finished
  • easy rollback to previous state (just symlink changes)
  • concurrent work with package

But there are also serious challenges:

  • it is impossible to follow Linux filesystem standard that expects files in traditional locations
  • packages that depend on specific absolute paths (runtime loaded shared libraries, or expecting data in hardcoded location) need tweaks and fixes
  • this problem includes for example Icon path for Xfce launchers or for Audacious player (see below)

Homepage: https://guix.gnu.org/

It is similar to Nix (package manager) and NixOS (OS based on Nix packages and declarative configuration). However Guix uses Lisp dialect (Guile as Scheme interpreter)

To better understand main 2 components of Guix using Nix glossary:

To understand how Guix packages works I strongly suggest following Video: YT: Everyday Use of GNU Guix, Chris Marusich, SeaGL 2018 GNU archive unofficial 803 subscribers

Package Manager example

Scenario: openSUSE LEAP 16 removed Audio player audacious. We can install Guix package manager and install audacious as Guix package without conflict with existing SUSE packages.

Here is example how to install just Guix package manager:

Host OS: openSUSE LEAP 16.0

Following: https://guix.gnu.org/manual/1.5.0/en/html_node/Binary-Installation.html

# as normal user
cd
sudo zypper in curl wget
curl -fLO https://guix.gnu.org/guix-install.sh
chmod +x guix-install.sh
sudo ./guix-install.sh
# answer lot of questions
guix pull
# ooops: In procedure getaddrinfo: Servname not supported for ai_socktype

Cause: SUSE's version of /etc/services contains rubbish placeholder (instead of list of services).

Fix:

sudo zypper in netcfg # install /usr/etc/services
# make proper link replacing userless rubbish text placeholder
sudo ln -fs /usr/etc/services /etc/services

And run again:

guix pull

It should finish without error.

Now logout and login and verify that your PATH includes ~/.guix-profile/bin:

$ echo "$PATH" | grep -o .guix-profile/bin

.guix-profile/bin

If yes you can now install and use Guix packages, for example:

# run as regular user that will run Audio player:
guix install audacious
# list installed packages:
guix package -I

  audacious       4.4.2   out     /gnu/store/fs0c5wnxz5958w8pn1girr4dph4d2ci0-audacious-4.4.2

Fix to see audacious application in Xfce:

# Application Lanucher
ln -s ~/.guix-profile/share/applications/audacious.desktop ~/.local/share/applications/
# Application Icon
mkdir -p ~/.local/share/icons/hicolor/scalable/apps
ln -s ~/.guix-profile/share/icons/hicolor/scalable/apps/audacious.svg ~/.local/share/icons/hicolor/scalable/apps/

WARNING! To get button icons for Audacious are restorted to:

guix install gnome-themes-extra
mkdir -p ~/.local/share/icons/hicolor/256x256/actions
cp /gnu/store/6c9pdg4hn4h26rcw69nxksy1b21qjj4m-gnome-themes-extra-3.28/share/icons/HighContrast/256x256/actions/* \
   ~/.local/share/icons/hicolor/256x256/actions

Now moment of truth - simply try running audacious if it will work (requires GUI - X11).

One can solve similar LEAP 16 defect - missing 32-bit Wine (because SUSE totally removed all 32-bit runtime). Fix with single command:

guix install wine

WARNING! If running winecfg command will throw error:

bash: /home/ansible/.guix-profile/bin/winecfg: cannot execute binary file: Exec format error

You need to install grub add-on that will enable kernel 32-bit ABI:

sudo zypper in grub2-compat-ia32
sudo reboot
# after reboot verify that following kernel boot parameter is active:
fgrep -o ia32_emulation=1 /proc/cmdline

  ia32_emulation=1

Any Wine command (including winecfg) should now run fine...

Install notes

This applies only when installing Guix System (as operating system). Tested guix-system-install-1.5.0.x86_64-linux.iso:

It hangs on NVidia GT218 (just black screen with blinking cursor - forever) - following PCI ID:

VGA compatible controller [0300]: NVIDIA Corporation GT218 [GeForce 210] [10de:0a65] (rev a2)
  • I have to add nouveau to blacklist in GRUB menu to proceed.

Updating system

guix pull       # fetch all updates
guix package -u # update packages
sudo guix system reconfigure /etc/config.scm # update system
sudo reboot
guix gc # remove obsolete packages
# optional - get more info on your system:
guix system describe
guix system list-generations

Setting up and running VM

Used example from https://stumbles.id.au/getting-started-with-guix-deploy.html

In my example you should first generate ssh keypair as ~/.ssh/id_rsa_guix

;; Guix VM example. Modified version based on:
;; - Author: Ben Sturmfels
;; - Source: https://stumbles.id.au/getting-started-with-guix-deploy.html
;; Modification: enabled serial console
    (use-modules (gnu))
    (use-service-modules networking ssh)
    (use-package-modules bootloaders ssh)

    (operating-system
     (host-name "vm")
     (timezone "Etc/UTC")
     (bootloader (bootloader-configuration
                  (bootloader grub-bootloader)
                  (target "/dev/vda")
                  (terminal-outputs '(console))))
     (kernel-arguments (list "console=ttyS0,115200"))
     (file-systems (cons (file-system
                          (mount-point "/")
                          (device "/dev/vda1")
                          (type "ext4"))
                         %base-file-systems))
     (services
      (append (list (service dhcp-client-service-type)
                    (service openssh-service-type
                             (openssh-configuration
                              (openssh openssh-sans-x)
                              (permit-root-login #t)
                              (authorized-keys
                               ;; Authorise our SSH key.
                               `(("root" ,(local-file "../.ssh/id_rsa_guix.pub")))))))
              %base-services)))

Above SCM file ( with top-level operating-system ) can be used with one of:

  1. guix system image ... - will build just disk image - outputs its name
  2. guix system vm ... - will build both image and shell script to run vm - outputs its name

To build Image and VM script (script to run VM) you can use:

guix system vm --save-provenance --image-type=qcow2 --root=run-vm.sh --no-graphic gs-deploy.scm

Note: --root parameter will create symbolic link to command output:

  • for guix system image output is Disk image (so using --rooot=disk.qcow2 is sensible)
  • for guix system vm output is QEMU Wrapper script (so using --root=run-vm.sh is reasonable)

You can run VM with symlink shell wrapper ./run-vm.sh, but we will enable SSH port forwarding (Host port 2222, target vm port 22):

./run-vm.sh -nic user,hostfwd=tcp::2222-:22

Now you can login using any of:

  1. on console as root without password
  2. or using command like ssh -p 2222 -i ~/.ssh/id_rsa_guix [email protected]

Guix deploy example

Deploy expects SCM file in following format:

(list  (machine (operating-system %system) ... ) )

So there is no top-level (operating-system ...) but rather (list ...) of machines

TODO: ...

Playing with REPL

Sooner or later you will be hit with weird error. Here is how you can use REPL - interactive guile shell to find basic info:

$ guile

;; must use absolute pathname to *.scm
scheme@(guile-user)> ,load "/home/ansible/os-deploy/gs-deploy.scm"

/home/ansible/os-deploy/gs-deploy.scm:12:26: warning: the 'target' field is deprecated, please use 'targets' instead

scheme@(guile-user)> ,pretty-print %base-file-systems
$2 = (#<<file-system> device: "none" mount-point: "/dev/pts" type: "devpts" flags: () options: "gid=996,mode=620" mount?: #t mount-may-fail?: #f ne>
      #<<file-system> device: "none" mount-point: "/sys/kernel/debug" type: "debugfs" flags: () options: #f mount?: #t mount-may-fail?: #f needed-f>
      #<<file-system> device: "tmpfs" mount-point: "/dev/shm" type: "tmpfs" flags: (no-suid no-dev) options: "size=50%" mount?: #t mount-may-fail?:>
      #<<file-system> device: "efivarfs" mount-point: "/sys/firmware/efi/efivars" type: "efivarfs" flags: () options: #f mount?: #t mount-may-fail?>
      #<<file-system> device: "/gnu/store" mount-point: "/gnu/store" type: "none" flags: (read-only bind-mount no-atime) options: #f mount?: #t mou)

Ctrl-D to exit guile

Note: it is common habit to prefix global variables with (%) - so %base-file-systems should be global variable that we attempt to print.

To study:

Guile scheme reference

It is hard to found, finally got something:

Resources