Guix Introduction Part 4: Try Guix
Contents
This is the fourth part of a brief introduction to the Guix functional package manager, and how it could be used to manage dependencies of projects, much like virtual environments for Python, but with much larger scope.
This time we look at how to install Guix, either in a physical or virtual machine, either as a complete GNU/Linux distribution, or just as a package manager on top of another Linux distribution. We also list some commonly used Guix commands
Get Guix
Refer to System Installation for details on getting Guix running (either the Guix system, or just the Guix package manager), we briefly summarize the main ways below. At the time of writing, the Guix version is 1.2.0.
Run Guix system in qemu virtual machine with pre-made image
Running Guix in a virtual machine is probably the easiest way to try it out. Qemu is a generic and open source emulator and virtualizer that can be used to run a pre-made image.
Refer to Running Guix in a Virtual Machine for more details. At the time of writing, the Guix version of the image is 1.2.0 for x86_64 architecture. We summarize the steps below:
-
install qemu following the instructions at https://www.qemu.org/download/
-
download the guix-system-vm-image-1.2.0.x86_64-linux.xz compressed image
-
decompress to get
guix-system-vm-image-1.2.0.x86_64-linux
1
xz -d guix-system-vm-image-1.2.0.x86_64-linux.xz
-
invoke qemu on the image with
1 2 3 4 5
qemu-system-x86_64 \ -nic user,model=virtio-net-pci \ -enable-kvm -m 1024 \ -device virtio-blk,drive=myhd \ -drive if=none,file=./guix-system-vm-image-1.2.0.x86_64-linux,id=myhd
-
you can change arguments such as
-m
as appropriate to set the amount of memory desired. Note that you may need to tweak the arguments of invoking qemu a bit, depending on your host system. E.g. in MacOS Mojave 10.14.6, I need to use the following:1 2 3 4 5 6
qemu-system-x86_64 \ -nic user,model=virtio-net-pci \ -m 1024 \ -device virtio-blk,drive=myhd \ -drive if=none,file=./guix-system-vm-image-1.2.0.x86_64-linux,id=myhd \ -accel hvf
-
wait for a while, then you will be in the default xfce desktop of a Guix system, i.e. a GNU/Linux distribution built around Guix. But note that by default, not many packages are installed, e.g. even a web browser is not installed by default. You may install them as needed, e.g. you may install
icecat
(the GNU version of Firefox browser) by:1
guix package -i icecat
-
optional: since the command for invoking qemu can be very long, you may put it into a shell script to more conveniently invoke the VM
-
optional: you may use other front-ends (some are GUI) to more conveniently manage qemu VM, see https://wiki.archlinux.org/index.php/Libvirt#Client
Install the Guix system, the GNU/Linux distribution built on the Guix package manager
You can also install a Guix system in either a virtual or physical machine.
-
Get the Guix system install ISO image
Refer to USB Stick and DVD Installation
-
download the compressed 64-bit ISO from https://ftp.gnu.org/gnu/guix/guix-system-install-1.2.0.x86%5F64-linux.iso.xz
- you may instead get the compressed 32-bit ISO from https://ftp.gnu.org/gnu/guix/guix-system-install-1.2.0.i686-linux.iso.xz
-
optionally verify the authenticity of the image:
-
get the sig file for 64-bit ISO and verify (change
x86_64-linux
toi686-linux
if you download the 32-bit ISO)1 2
wget https://ftp.gnu.org/gnu/guix/guix-system-install-1.2.0.x86_64-linux.iso.xz.sig gpg --verify guix-system-install-1.2.0.x86_64-linux.iso.xz.sig
-
if then above command fails, then import the gpg public key first and then re-run the above verification:
1 2
wget https://sv.gnu.org/people/viewgpg.php?user_id=15145 \ -qO - | gpg --import -
-
-
decompress the image with
xz -d
command to getguix-system-install-1.2.0.x86_64-linux.iso
1
xz -d guix-system-install-1.2.0.x86_64-linux.iso.xz
-
-
Install in a fresh qemu virtual machine
Refer to Installing Guix in a Virtual Machine
-
install qemu following the instructions at https://www.qemu.org/download/
-
create a fresh disk image in qcow2 format, where you can choose an appropriate size, e.g. 50G (the created image file will initially be much smaller, but will grow in size when it is filled up)
1
qemu-img create -f qcow2 guix-system.img 50G
-
boot the installation ISO image in the VM:
1 2 3 4
qemu-system-x86_64 -m 1024 -smp 1 -enable-kvm \ -nic user,model=virtio-net-pci -boot menu=on,order=d \ -drive file=guix-system.img \ -drive media=cdrom,file=guix-system-install-1.2.0.system.iso
-
note that you may need to tweak the arguments to
qemu-system-x86_64
depending on your host system, e.g. you may need to replace-enable-kvm
with-accel hvf
in MacOS. The-enable-kvm
is optional anyway, but will significantly improve performance. -
note the few things mentioned in https://guix.gnu.org/manual/en/guix.html#Preparing-for-Installation
- The graphical installer is available on TTY1.
- You can obtain root shells on TTYs 3 to 6 by hitting ctrl-alt-f3, ctrl-alt-f4, etc.
- TTY2 shows the documentation and you can reach it with ctrl-alt-f2.
- Documentation is browsable using the Info reader commands (see Stand-alone GNU Info).
- The installation system runs the GPM mouse daemon, which allows you to select text with the left mouse button and to paste it with the middle button.
-
for simplicity, choose Guided Graphical Installation to finish the installation
-
after the installation, you can get into guix with the default xfce desktop whenever you invoke the VM
-
optional: since the command for invoking qemu can be very long, you may put it into a shell script to more conveniently invoke the VM
-
optional: you may use other front-ends (some are GUI) to more conveniently manage qemu VM, see https://wiki.archlinux.org/index.php/Libvirt#Client
-
-
Install in other virtual machine
You can also install Guix system using the ISO in other types of virtual machines such as:
- VirtualBox (free)
- Parallels (proprietary)
- VmWare (proprietary)
- and many others, see https://en.wikipedia.org/wiki/Comparison%5Fof%5Fplatform%5Fvirtualization%5Fsoftware
Similar to installing in qemu VM:
- note the few things mentioned in https://guix.gnu.org/manual/en/guix.html#Preparing-for-Installation
- The graphical installer is available on TTY1.
- You can obtain root shells on TTYs 3 to 6 by hitting ctrl-alt-f3, ctrl-alt-f4, etc.
- TTY2 shows the documentation and you can reach it with ctrl-alt-f2.
- Documentation is browsable using the Info reader commands (see Stand-alone GNU Info).
- The installation system runs the GPM mouse daemon, which allows you to select text with the left mouse button and to paste it with the middle button.
- for simplicity, choose Guided Graphical Installation to finish the installation
- after the installation, you can get into guix with the default xfce desktop whenever you invoke the VM
-
Install on physical machine
Installing Guix system on physical machine is similar to installing in virtual machine, except that you need to transfer the ISO image to either a USB stick or a DVD. It is recommended that you try to install in a virtual machine first to get familiar with the process, see the preceding subsection.
Refer to https://guix.gnu.org/manual/en/guix.html#USB-Stick-and-DVD-Installation
-
Copying to a USB Stick
- Insert a USB stick of 1 GiB or more into your machine
- if on a Linux machine,
-
determine its device name, e.g.
/dev/sdb
or/dev/sdc
. Note that it is VERY important to determine the correct device name, otherwise you may mistakenly wipe out another device. -
assuming that the USB stick is known as
/dev/sdX
, copy the image with:1 2 3 4
# access to /dev/sdX usually requires root privilege # also, /dev/sdX should NOT be mount sudo dd if=guix-system-install-1.2.0.x86_64-linux.iso of=/dev/sdX status=progress sudo sync
-
- if on a different OS or you prefer to use a GUI, you can try these programs:
-
alternative: Burning on a DVD
- Insert a blank DVD into your machine
- if on a Linux machine,
-
determine its device name. Note that it is VERY important to determine the correct device name, otherwise you may mistakenly wipe out another device.
-
assuming that the DVD drive is known as
/dev/srX
, copy the image with:1 2
# access to /dev/srX usually requires root privilege growisofs -dvd-compat -Z /dev/srX=guix-system-install-1.2.0.x86_64-linux.iso
-
- if on a different OS or you prefer to use a GUI, you can try these programs:
-
Installation
Similar to installing in qemu VM:
- note the few things mentioned in https://guix.gnu.org/manual/en/guix.html#Preparing-for-Installation
- The graphical installer is available on TTY1.
- You can obtain root shells on TTYs 3 to 6 by hitting ctrl-alt-f3, ctrl-alt-f4, etc.
- TTY2 shows the documentation and you can reach it with ctrl-alt-f2.
- Documentation is browsable using the Info reader commands (see Stand-alone GNU Info).
- The installation system runs the GPM mouse daemon, which allows you to select text with the left mouse button and to paste it with the middle button.
- for simplicity, choose Guided Graphical Installation to finish the installation
- after the installation, you can get into guix with the default xfce desktop
- note the few things mentioned in https://guix.gnu.org/manual/en/guix.html#Preparing-for-Installation
-
Install the guix package manager in existing GNU/Linux distribution (possibly in a VM)
Instead of installing a Guix system, you may choose to only install guix package manager on top of a GNU/Linux distribution (named “foreign distro in Guix documentation”, which does not need to be a Guix system, e.g. Debian, Ubuntu, Fedora, ArchLinux, etc).
Refer to Binary Installation
- the easiest way is to use the shell installer script:
-
download and execute the shell installer script as root
1 2 3 4
cd /tmp wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh chmod +x guix-install.sh ./guix-install.sh
- you may be asked to import gpg key, if so, just follow the instructions, then re-run the installer script
-
after that, check Application Setup for extra configuration you might need
-
- alternatively, you may choose to install the guix package from the package manager of your distribution, if there is one, e.g.:
Brief summary of commonly used commands in Guix
Here we list some common commands and usage of Guix, see Getting Started of the Guix manual for more details.
Basic usage of Guix
-
Help on Guix commands
-
Help on the main usage, to see the available commands
1
guix --help
-
Help on each command, e.g. the
guix package
command1
guix package --help
-
-
Search packages
1 2
guix search keywords-here # guix package -s keywords-here
-
Show information of package(s)
1
guix show package1 package2
-
Update channel(s)
To update the channels so that all the package definitions are updated, but the packages themselves are not automatically updated.
1
guix pull
-
Install package(s)
-
You can install one or more packages in one transaction
1
guix install package1 package2
-
An alternative way
1 2
guix package -i package1 package2 # guix package --install package1 package2
-
-
Remove package(s)
-
guix remove
1
guix remove package1 package2
-
An alternative way
1 2
guix package -r package1 package2 # guix package --remove package1 package2
-
-
Upgrade package(s)
-
guix upgrade
1
guix upgrade package1 package2
-
An alternative way
1 2
guix package -u package1 package2 # guix package --upgrade package1 package2
-
-
Install/Remove/Upgrade package(s) in one transaction
You can also install/remove/upgrade package(s) in a single transaction, simply list the package(s) with suitable options of
guix package
,-i
for installing,-r
for removing,-u
for upgrading:1
guix package -i package1 -r package2 -u package3
-
List installed packages
1 2
guix package -I # guix package --list-installed
-
Rollback to the previous generation
1
guix package --roll-back
-
List generations
1 2
guix package -l # guix package --list-generations
-
Switch generations
PATTERN
can be a generation number or+n
to go forward n generations; or-n
to go backward n generations.
1 2
guix package -S PATTERN # guix package --switch-generation=PATTERN
- E.g. to go forward one generation
1 2
guix package -S +1 # guix package --switch-generation=+1
- E.g. to go backward one generation, similar to
--roll-back
, but if the specified generation does not exist, the current generation will not change
1 2
guix package -S -1 # guix package --switch-generation=-1
Using manifest file to specify a list of package(s)
-
A manifest file is a Scheme file that evaluates to a list of guix packages (as Scheme object).
-
A convenient way is to use the
specifications->manifest
function which takes a list of package names as strings and returns a list of the corresponding package objects. -
It can be used in a few contexts such as
guix package
to install packages, orguix environment
to spawn a shell with specified packages (see below), through the-m
or--manifest
option. -
The advantage of a manifest file is that the list of packages can be easily version controlled (e.g. with
git
). -
An example of manifest file (let’s say
pkgs.scm
) is:
|
|
-
Install the list of package(s) in a manifest file
Note that the
-m
can be repeated multiple times with different manifest files, and the lists will be concatenated and all will be installed.1
guix package -m pkgs.scm
Note that a manifest file by itself only specifies the list of packages by name, but not the exact versions. In order to reproduce the exact versions of the list of packages, a manifest file can be combined with
guix time-machine
as described below.
Using Guix profiles
Default guix actions (install/upgrade/remove) operate on the
default profile of each user (it is a symbolic link, default
location is at $HOME/.guix-profile
), but each user can create
multiple profiles, activate the profiles as needed in similar ways
to Python virtual environments, and specify the profile to
operate on with each action through the -p
(or --profile
)
option (see Invoking guix package):
-
Create profile
The profile name is basically symbolic link(s) to the real contents of the profile, and we can put it basically anywhere, e.g.
~/my-ds-profile
. So it is up to you to organize the profiles in a sensible way. It is also up to you to assign the roles of different profiles, e.g. one profile for each project; or different profiles for different domains of packages (e.g. one profile for data analysis, one profile for entertainment, one profile for graphics editing, etc).A profile will be created when you perform guix package actions specifying a profile, e.g. install
r
andr-xgboost
in the profile~/my-ds-profile
, which need not exist before this action:1
guix package -i r r-xgboost -p ~/my-ds-profile
Note that the created profile is not automatically activated, so you retain the maximum flexibility to activate as needed, or arrange to activate chosen profiles in each shell, see below.
-
Install or upgrade or remove packages in a profile
- Any usual
guix package
actions can be performed on a chosen profile by using the-p
(or--profile
) option, e.g. to install another packager-yaml
to the profile~/my-ds-profile
just created:
1
guix package -i r-yaml -p ~/my-ds-profile
- E.g. install packages using a manifest file in a profile:
1
guix package -m the_manifest_file -p path_to_profile
- Any usual
-
List profiles
1
guix package --list-profiles
-
Activate a profile
Activating a profile amounts to modifying and exporting some environment variables (e.g.
PATH
) in the current shell, which is conveniently done by sourcing theetc/profile
file under the profile. The recommended way to activate a profile, e.g.~/my-ds-profile
, is to:1
GUIX_PROFILE="~/my-ds-profile" ; . "$GUIX_PROFILE"/etc/profile
Note that you can activate multiple profiles in the same shell as appropriate. But there is no effective way to deactivate a profile in the same shell, other than exiting the shell. The upside is that the global environment is not “polluted”, and you can start a new shell to activate a profile, then exit the shell afterwards.
Also, you can automatically activate any profile in each spawn shell by adding the activation to your shell initialization, e.g.
.bash_profile
or.bashrc
. -
Delete a profile
Somehow Guix does not provide a convenient command to delete a profile. Deleting a profile involves removing the profile symbolic link and its siblings that point to specific generations. E.g. to delete the
~/my-ds-profile
profile created above:1
rm ~/my-profile ~/my-profile-*-link
-
Export current or chosen profile as a manifest file
You can export the list of packages of a profile (if not specified, will use the default profile) to a manifest file. E.g. to export the default profile:
1
guix package --export-manifest > pkgs1.scm
E.g. to export the above
~/my-ds-profile
profile:1
guix package --export-manifest -p ~/my-ds-profile > pkgs2.scm
Using Guix environment
The guix environment
command allows you to spawn a new shell with
certain packages (or their dependencies) accessible (by modifying some
environment variables, e.g. PATH
), without changing your other
profiles; and you can optionally either just spawn such a shell, or
execute a command inside this shell. Essentially a temporary profile
is created (for the set of packages wanted), so that you do not
“pollute” your other environment. The needed packages will be
automatically built if they are not yet in the cached store. So guix environment
is a very convenient way to reproduce a set of packages
in a clean way. For example, this can be used to manage per-project
dependencies, as we will see in a future demo post of this series.
Note that when in a shell spawn by guix environment
, the environment
variable GUIX_ENVIRONMENT
will have the value of the path to the
temporary profile for the environment, and you can detect it to change
the shell prompt, e.g. add this to your .bashrc:
|
|
-
Spawn a shell with dependencies of some packages E.g. to get the dependencies of
emacs
andvim
:1 2
# guix environment pkg1 pkg2 ... guix environment emacs vim
Can also use
-m
(possibly multiple times) to specify manifest file(s):1 2
# guix environment pkg1 pkg2 ... -m pkgs1.scm -m pkgs2.scm ... guix environment kmahjongg -m pkgs.scm
Also check out the
--load
option for loading a file for package. -
Spawn a shell with some packages themselves
Use the
--ad-hoc
option to get the packages themselves. E.g. to get the gamekmahjongg
itself:1 2
# guix environment --ad-hoc pkg1 pkg2 ... guix environment --ad-hoc kmahjongg
Can also use
-m
(possibly multiple times) to specify manifest file(s):1 2
# guix environment --ad-hoc pkg1 pkg2 ... -m pkgs1.scm -m pkgs2.scm ... guix environment --ad-hoc kmahjongg -m pkgs.scm
Also check out the
--load
option for loading a file for package. -
Spawn a shell and directly execute some commands in it
To run commands in the spawn shell, put the command after
--
at the end. E.g. to getR
and start it1 2
# guix environment --ad-hoc pkg1 ... -- pkg1 guix environment --ad-hoc r -- R
-
Spawn a shell where original environment variables are unset
Use the
--pure
option, e.g. to get R1 2 3 4 5 6 7 8
# show all environment variables currently defined env # guix environment --pure --ad-hoc pkg1 ... -- pkg1 guix environment --pure --ad-hoc r # then in the new shell, the PATH is reduced to only those for the # package, and even basic shell utilities are not in the PATH unless # they are added as one of the packages. echo $PATH
You may use the
--preserve
to control the environment variables to keep, checkguix environment --help
for more details. -
Spawn a shell to run things in an isolated environment
For further isolation, you can use the
--container
option to run in a container where only the/gnu/store
and (by default) the current directory are mounted. You may checkguix environment --help
for other relevant options, e.g.--expose
,--network
,--share
,--no-cwd
,--user
.E.g. to run R in a container:
1 2
# guix environment --ad-hoc pkg1 ... -- pkg1 guix environment --container --ad-hoc r -- R
But seems this feature is not very mature yet. When I tried the above command (on guix (GNU Guix) 510e24f973a918391d8122fd6ad515c0567bf23e), it gave this error:
1
guix environment: error: mount: mount "/home/peter" on "/tmp/guix-directory.QDXQmx//home/peter": Invalid argument
Using Guix time-machine
The guix time-machine
can be used to execute other Guix commands (e.g. guix package
, or guix environment
) at specified Guix revisions (exact commits of the channels, which can be produced by guix describe
)
-
Install package in a particular revision
E.g. to install
emacs
at the revision in the filechannels.scm
1
guix time-machine -C channels.scm -- package -i emacs
The
channels.scm
could be obtained withguix describe
, e.g.1
guix describe -f channels > channels.scm
The
channels.scm
will look something like (exact content of course depends on your channels) this:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
(list (channel (name 'nonguix) (url "https://gitlab.com/nonguix/nonguix") (commit "05fad6e54d497b7427ab7ea488210c7d43c3f676") (introduction (make-channel-introduction "897c1a470da759236cc11798f4e0a5f7d4d59fbc" (openpgp-fingerprint "2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5")))) (channel (name 'guix) (url "https://git.sjtu.edu.cn/sjtug/guix.git") (commit "8a452e156e37568fdd59df169acb4f2092aeb3ac") (introduction (make-channel-introduction "9edb3f66fd807b096b48283debdcddccfea34bad" (openpgp-fingerprint "BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA")))))
Note that it is possible to hand-edit the file to the commit desired.
-
Use time-machine with guix environment
Assuming there is a manifest file
pkgs.scm
containing the needed packages, e.g.1 2 3 4 5 6 7 8 9 10
(specifications->manifest '( ;; R "r" "r-yaml" "r-xgboost" "r-tidymodels" "r-tidyverse" "r-survminer" ))
Then you can open a shell with these packages at the revisions specified in a
channels.scm
1 2
guix time-machine -C channels.scm -- environment --ad-hoc -m pkgs.scm # in this new shell where the packages are visible, you can run anything as needed
And you can directly run things in the new shell, e.g. to run R:
|
|
Use Guix to create docker image
Guix can produce a docker image of a set of packages through the guix pack
command, see Invoking guix pack and guix pack --help
for more
description. In fact, guix pack
can produce other formats, see guix pack --list-formats
for the possible formats.
-
Produce a docker image of a list of packages
The set of packages can be specified as a list when calling
guix pack
. E.g. to getR
andxgboost
:1 2
# guix pack -f docker -S /bin=bin pkg1 pkg2 ... guix pack -f docker -S /bin=bin r r-xgboost
The
-S
option creates a symbolic link to file or directory under the profile (which is otherwise a path with long hash), provided for convenience. In the above example, a symbolic link will be created at/bin
pointing to thebin
directory in the profile (which will be something like/gnu/store/...-profile/bin
), then the user can startR
with/bin/R
.The path to the created tar.gz (something like
/gnu/store/...-docker-pack.tar.gz
with a long hash) file is output to stdout of theguix pack
call, so we can get it like:1 2
PACKLOC=$(guix pack -f docker -S /bin=bin r r-xgboost) # then can easily copy it elsewhere
Then the file produced is a docker image that can be loaded into docker:
1 2 3 4 5
# assume the file name is shortened to docker-pack.tar.gz docker load < docker-pack.tar.gz # docker will show the image tag after loading # the tag of the image is generated from the set of packages docker run -ti r-r-xgboost /bin/R
-
Produce a docker image of packages from a manifest file
The set of packages can also be specified by a manifest file, similar to
guix package
, e.g. if we have a manifest filepkgs.scm
:1
guix pack -f docker -S /bin=bin -m pkgs.scm
NOTE: the documentation specifically mention that the set of packages can be specified by either a list of package names as arguments to
guix pack
, or through a manifest file, but NOT BOTH. It is strange that there is such a limitation, hopefully it will be changed in the future. -
Also specify an entry point command
The
--entry-point
option can specify a command to run when the docker image is started, e.g. to run guile:1 2
# seems the command is relative to the profile path guix pack -f docker --entry-point=bin/guile guile
Then the produced image (say renamed to
pack.tar.gz
), can be loaded into docker and run as follows andguile
will start automatically:1 2 3 4
docker load -i pack.tar.gz #docker run image-id # assume the image id is "guile" docker run guile
-
Also use time-machine to pin package versions
The
guix time-machine
can be used, together with a manifest file, to easily produce a docker image with the set of desired packages pinned to versions at a certain time point.E.g. suppose we have the channel file
channels.scm
, and manifest filepkgs.scm
:1
guix time-machine -C channels.scm -- pack -f docker -S /bin=bin -m pkgs.scm
The above have been tested with
guix (GNU Guix) ff1c7e40252337cb2c992c2d41e0ed4cefe56df0
(installed on top of Debian 10 in a qemu VM), and the produced docker images have been tested on MacOS with Docker version 19.03.8, build afacb8b.
What’s next?
In this part we looked at various ways of installing Guix to try it
out, and showed some commonly used Guix commands. Next time we show a
little demo of managing per-project dependency with Guix, through the
guix time-machine
and guix environment
commands.
Author Peter Lo
LastMod 2021-05-12