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 (not fully - you can search while installing, but not having concurrent guix install ... commands)

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)

And controversy:

  • there is no Firefox but rather IceCat browser (GNU Fork of Firefox). I have serious issues with installed plugin Privacy Redirect that intentionally redirects youtube.com to inv.nadeko.net. My opinion is that such redirects (even for sake of privacy) should never occur without clear user consent.

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 I resorted 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, but see below
# optional - get more info on your system:
guix system describe
guix system list-generations

WARNING! Commands below delete all previous generations (no rollback possible). See next paragraph for safer way how to delete only subset of generations.

# package cleanup: WARNING! Deletes all generations but latest
guix package --delete-generations # deletes just symlinks to generations
guix gc # really removes orphaned packages from store

# system cleanup:
sudo guix system delete-generations  # again just symlinks
guix gc # really removes orphaned packages from store

# same for pull
guix pull -l
guix pull -d # removes old generations!
guix gc

Note: to delete specific generations try:

$ guix package --list-generations

Generation 1    Apr 06 2026 12:48:48
  audacious     4.4.2   out     /gnu/store/y9fafk5msa4mbq9hqf3g38a8ly8qkzxb-audacious-4.4.2

Generation 2    Apr 06 2026 13:03:28
 + wine 10.0    out     /gnu/store/clax8pajhcs08735wva0mw9y1r5xxnac-wine-10.0

Generation 3    Apr 06 2026 13:06:41
 + keepass      2.57.1  out     /gnu/store/py6b1v1wvvh1gxv6axxz4mp9jc0cfli0-keepass-2.57.1

Generation 4    Apr 06 2026 13:55:42
 + adwaita-icon-theme   48.1    out     /gnu/store/24aiykiqlvk8njiqxd9wr5dq4pn4lyzv-adwaita-icon-theme-48.1
 + gnome-themes-extra   3.28    out     /gnu/store/6c9pdg4hn4h26rcw69nxksy1b21qjj4m-gnome-themes-extra-3.28

Generation 5    Apr 06 2026 13:55:53
 + adw-gtk3-theme       5.10    out     /gnu/store/gjh903p075rwj6r12nwm7pl9pwvisi5d-adw-gtk3-theme-5.10

Generation 6    Apr 06 2026 14:10:48

Generation 7    Apr 18 2026 12:53:27    (current)
 + gnome-themes-extra   3.28    out     /gnu/store/z0k8bl478sh7bk7kib7ydqc8c3c6ks8w-gnome-themes-extra-3.28
 + keepass              2.61    out     /gnu/store/qrbig2s73j08qb6y68ig5h3q3jsnlg2a-keepass-2.61
 + wine                 11.0    out     /gnu/store/igfi55f5rak4s47l8agr24cah4qd1hnf-wine-11.0
 + audacious            4.4.2   out     /gnu/store/mizy9ckcrhnav8k913py5rk0qnvm2hj6-audacious-4.4.2
 - gnome-themes-extra   3.28    out     /gnu/store/6c9pdg4hn4h26rcw69nxksy1b21qjj4m-gnome-themes-extra-3.28
 - keepass              2.57.1  out     /gnu/store/py6b1v1wvvh1gxv6axxz4mp9jc0cfli0-keepass-2.57.1
 - wine                 10.0    out     /gnu/store/clax8pajhcs08735wva0mw9y1r5xxnac-wine-10.0
 - audacious            4.4.2   out     /gnu/store/y9fafk5msa4mbq9hqf3g38a8ly8qkzxb-audacious-4.4.2

# keep 6 and 7
$ guix package --delete-generations=1..5

deleting /var/guix/profiles/per-user/hpaluch/guix-profile-1-link
deleting /var/guix/profiles/per-user/hpaluch/guix-profile-2-link
deleting /var/guix/profiles/per-user/hpaluch/guix-profile-3-link
deleting /var/guix/profiles/per-user/hpaluch/guix-profile-4-link
deleting /var/guix/profiles/per-user/hpaluch/guix-profile-5-link

$  guix package --list-generations

Generation 6    Apr 06 2026 14:10:48
  audacious             4.4.2   out     /gnu/store/y9fafk5msa4mbq9hqf3g38a8ly8qkzxb-audacious-4.4.2
  wine                  10.0    out     /gnu/store/clax8pajhcs08735wva0mw9y1r5xxnac-wine-10.0
  keepass               2.57.1  out     /gnu/store/py6b1v1wvvh1gxv6axxz4mp9jc0cfli0-keepass-2.57.1
  adwaita-icon-theme    48.1    out     /gnu/store/24aiykiqlvk8njiqxd9wr5dq4pn4lyzv-adwaita-icon-theme-48.1
  adw-gtk3-theme        5.10    out     /gnu/store/gjh903p075rwj6r12nwm7pl9pwvisi5d-adw-gtk3-theme-5.10
  gnome-themes-extra    3.28    out     /gnu/store/6c9pdg4hn4h26rcw69nxksy1b21qjj4m-gnome-themes-extra-3.28

Generation 7    Apr 18 2026 12:53:27    (current)
 + gnome-themes-extra   3.28    out     /gnu/store/z0k8bl478sh7bk7kib7ydqc8c3c6ks8w-gnome-themes-extra-3.28
 + keepass              2.61    out     /gnu/store/qrbig2s73j08qb6y68ig5h3q3jsnlg2a-keepass-2.61
 + wine                 11.0    out     /gnu/store/igfi55f5rak4s47l8agr24cah4qd1hnf-wine-11.0
 + audacious            4.4.2   out     /gnu/store/mizy9ckcrhnav8k913py5rk0qnvm2hj6-audacious-4.4.2
 - gnome-themes-extra   3.28    out     /gnu/store/6c9pdg4hn4h26rcw69nxksy1b21qjj4m-gnome-themes-extra-3.28
 - keepass              2.57.1  out     /gnu/store/py6b1v1wvvh1gxv6axxz4mp9jc0cfli0-keepass-2.57.1
 - wine                 10.0    out     /gnu/store/clax8pajhcs08735wva0mw9y1r5xxnac-wine-10.0
 - audacious            4.4.2   out     /gnu/store/y9fafk5msa4mbq9hqf3g38a8ly8qkzxb-audacious-4.4.2

# and finally release space
$ guix gc

note: currently hard linking saves    2.69 GiB
guix gc: freed 130 MiB

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:

My first Guix package

Create anywhere in your Home file pil-git-scripts.scm with contents:

;; Guix package fo Pickering Git Scripts (pil-git-scripts) project from GitHub
;; Create and install package with: guix package --install-from-file=pil-git-scripts.scm
(use-modules (guix packages)
	     (guix download)
	     (guix gexp)
	     (guix git-download)
	     (guix build-system copy)
	     (guix licenses))
  (package
    (name "pil-git-scripts")
    (version "0.99.0")
    (source
     (origin
       (method git-fetch)
       (uri (git-reference
         (url "https://github.com/hpaluch-pil/pil-git-scripts.git")
         (commit "5f264ed4c5abd9ebfea59ed2f00cba3f0b58555e" )))
       (file-name (git-file-name name version))
       (sha256 (base32 "0k3baflv7mkf3gjsphbx8h3if5raifwnvqgdkx75zhzkk09lmia7"))
       ))
    (build-system copy-build-system)
    (arguments
     (list #:install-plan #~'(("scripts/push_branch.sh" "bin/push_branch.sh"))))
    (home-page "https://github.com/hpaluch-pil/pil-git-scripts")
    (synopsis "My Git scripts")
    (description "Set of Git scripts I found useful 2004.")
    ;; I use "MIT" license, but it is missing in guix/licenses.scm
    (license bsd-0))
  • 1st hash (after commit) is simply git hash that I want to checkout: https://github.com/hpaluch-pil/pil-git-scripts/commit/5f264ed4c5abd9ebfea59ed2f00cba3f0b58555e
  • 2nd hash (with base32) can be computed with:
    mkdir ~/src
    cd ~/src
    git clone https://github.com/hpaluch-pil/pil-git-scripts.git
    cd pil-git-scripts
    git branch -v # ensure that you use same commit as 5f264ed4...
    
      * master 5f264ed Added graph_log_simplified.sh to changelog
    
    guix hash -rx .
    
      0k3baflv7mkf3gjsphbx8h3if5raifwnvqgdkx75zhzkk09lmia7
    
  • now build (and install!) this package with:
    guix package --install-from-file=pil-git-scripts.scm
    
  • you can see all installed packages with:
    $ guix package -I
    
    ...
    pil-git-scripts 0.99.0          out     /gnu/store/i0qfk36zsyrz936bh3wizdx2n8g9b6h5-pil-git-scripts-0.99.0
    
  • it will symlink following command (and even substitutes bash):
    ~/.guix-profile/bin/push_branch.sh
    

Note: there is some Guix discrepancy between:

  1. directly installing package with --install-from-file= - because it must evaluate to (package ...)
  2. with Channels - unfortunately in that case there must be (define-public PACKAGE-NAME ...) in package SCM file. (As trick in Cookbook you can call it on last line, but it is not common)

I plan to solve this by defining my own Channels repository.

Note: after guix pull package is gone - must be rebuild again (again Channels should solve that).

VM and GUI

To enable clipboard intergration you need spice service - apply following diff to your /etc/config.scm:

--- orig/config.scm	2026-04-25 20:11:37.411836126 +0200
+++ config.scm	2026-04-25 20:16:09.554978524 +0200
@@ -10,7 +10,7 @@
 ;; Indicate which modules to import to access the variables
 ;; used in this configuration.
 (use-modules (gnu))
-(use-service-modules cups desktop networking ssh xorg)
+(use-service-modules cups desktop networking spice ssh xorg)
 
 (operating-system
   (locale "en_US.utf8")
@@ -36,6 +36,7 @@
                  ;; record as a second argument to 'service' below.
                  (service openssh-service-type)
                  (service cups-service-type)
+                 (service spice-vdagent-service-type)
                  (set-xorg-configuration
                   (xorg-configuration (keyboard-layout keyboard-layout))))

Next run sudo guix system reconfigure /etc/config.scm and reboot.

From Guix source: guix/gnu/system/examples/vm-image.tmpl

GUI

I use Guix with XFCE. Here is list of important packages (for me):

  • audacious (mp3 player)
  • keepass (nice Windows version running on Mono .NET emulation)
  • mc
  • vim

Tricky situation: browser - no plain Firefox there, offered alternatives:

  • icecat - I don't like link redirecting (caused by plugin Privacy Redirect), for example https://youtube.com will redirect you to https://inv.nadeko.net - I never asked for that! BTW: even Nadeko now requires JavaScript (that FSF considers evil) to avoid AI-scrappers - so what is benefit of that redirect?
  • mullvadbrowser - I don't like that it uses its own DNS and VPN (how we can know what will happen to all our data there?)
  • nyxt - browser written in SBCL (common lisp dialect), not yet tested (requires build)
  • midori - ligth browser (I used it on RPi 1.B - only browser that was able to run on such underpowered machine)
  • dillo - not yet tested
  • ungoogled-chromium - not yet tested (looks promising)

Tips

Unsorted tips.

Listing installed services:

Resources