Skip to main content
  1. Posts/

Introduction to Guix

·2292 words·11 mins·
ebeem
Author
ebeem
FOSS Enthusiast & Indie Game Developer

TODO Installation

Channels

Channels in Guix are a way to customize and extend the Guix package collection. They allow users to pull packages and updates from multiple repositories. They are declared as a list of channel records in the file channels.scm. These channels are git repositories that store definitions that instruct Guix how to build and install packages. Since these are git repositories, then similar to any git cloned project, it needs to be pulled to kept up to date. Guix can help you update/pull all your configured channels with the command guix pull.

Note: pulling Guix might take a long time depending on how outdated your system is. Expect up to an hour on your first installation.

Adding a channel

  1. Create or edit your ~/.config/guix/channels.scm file to include your desired channels. Here's an example:
(cons* (channel
        (name 'my-channel)
        (url "https://example.com/my-channel.git"))
       %default-channels)

Note: we create a channel record with the name my-channel and the git url, then we use cons to append it to the %default-channels which includes the default Guix channel. It's possible to remove the default Guix channel by returning a new list without appending the default channels.

  1. Save the file and pull Guix channels:
guix pull

Removing a channel

  1. edit your ~/.config/guix/channels.scm file to exclude the target channel.
  2. Save the file and pull Guix channels:
guix pull

NonGuix Channel

Nonguix is a Guix channel that packages some software which cannot be included in the official distribution for ethical or policy-related reasons. Guix official repository offers only Gnu Compatible Free Software.

It will be great if we can use only free software, but sometimes it's necessary to add some nonfree software to get our machine functioning properly. For example, Guix's default kernel is called Linux Libre, it's a custom Linux kernel that doesn't ship with some nonfree drivers embedded into the Linux kernel. These drivers are necessary to get some wifi and bluetooth cards to work.

Rule of thumb: If everything works properly in your case, no missing drivers, all hardware is working as expected, then you probably don't want to add or use the nonguix channel.

Adding the NonGuix channel

  1. Create or edit your ~/.config/guix/channels.scm file to include the NonGuix channel
(cons* (channel
        (name 'nonguix)
        (url "https://gitlab.com/nonguix/nonguix")
        ;; Enable signature verification:
        (introduction
         (make-channel-introduction
          "897c1a470da759236cc11798f4e0a5f7d4d59fbc"
          (openpgp-fingerprint
           "2A39 3FFF 68F4 EF7A 3D29  12AF 6F51 20A0 22FB B2D5"))))
       %default-channels)
  1. Pull Guix channels
guix pull

Note: in case you notice the message below after pulling NonGuix

hint: Consider setting the necessary environment variables by running:

     GUIX_PROFILE="/home/ebeem/.config/guix/current"
     . "$GUIX_PROFILE/etc/profile"

Alternately, see `guix package --search-paths -p "/home/ebeem/.config/guix/current"'.


hint: After setting `PATH', run `hash guix' to make sure your shell refers to `/home/ebeem/.config/guix/current/bin/guix'.

Then execute the below to ensure the updated profile path is active

  GUIX_PROFILE="/home/ebeem/.config/guix/current"
  . "$GUIX_PROFILE/etc/profile"
  hash guix'

Note: with this step, you only make the nonguix packages available to your system. You are still not using the Full Linux kernel or any other nonfree software. Continue to the other sections to learn more.

System Configuration

System configuration in Guix is declarative, meaning you define the desired state of your system in a configuration file, and Guix ensures your system matches that state. Upon installing Guix, you provided system configuration parameters that Guix installer used to create a system configuration file for you in the path /etc/config.scm.

You can take a peak at this file and see all the parameters that have been configured like: locale, timezone, keyboard-layout, host-name, users, packages, services, bootloader, swap-devices, file-systems.

These configurations are system level, this means that they impact all the users on your system. For example, we can add emacs to the declared packages list, this will install emacs globally on your system and make it available to all users. It's important to understand here that unlike other Linux distributions and operating systems. Guix suggests adding packages to user configurations (called home configuration) rather than system configuration. However, some packages must be installed globally, like the Linux kernel, vi to have a text editor and your display manager like GDM. Knowing when to add a package to system or user level might take sometime, but the rule of thumb here, if you can add it to user level, then do so.

Creating System Configuration

It's better to start with the generated Guix configuration located in the path /etc/config.scm. My preference is to have this system configuration added to my dotfiles so I can easily manage and track changes using git.

  1. Copy the generated Guix configuration file to your Guix configuration directory
cp /etc/config.scm ~/.config/guix/system.scm

Applying System Configuration

Upon modifying the system configuration, you will have to tell Guix to apply your changes by providing it with the path of your system configuration.

sudo guix system reconfigure ~/.config/guix/system.scm

Note: Remember that the Guix system configuration contains data that only superusers can access or modify. For example, only superusers can partition disks, manage users, manage system level packages, manage system level services. That's the reason why a sudo is required when you would like to reconfigure your system.

Using Nonfree Linux Kernel

To be able to use the nonfree Linux kernel, you must add the NonGuix channel and pull it so the nonfree software become available to your system.

Edit your ~/.config/guix/system.scm as below

  1. Add needed imports in your system configuration

Just below the line where the gnu module is imported (use-modules (gnu)) Add the below lines

;; Import nonfree linux module.
(use-modules (nongnu packages linux)
             (nongnu system linux-initrd))
  1. Modify the parameters of your operating system record

Now you will have to add the new nonfree Linux kernel as the kernel of your system. You can do so be adding the below lines just below the line where the operating system is defined (operting-system and before the line where locale is defined.

  (kernel linux)
  (initrd microcode-initrd)
  (firmware (list linux-firmware))
  1. Apply the system configuration

Now that you modified the used kernel, you must apply the configuration for it to take affect.

sudo guix system reconfigure ~/.config/guix/system.scm

Note: This might take a long time if this is the first time you reconfigure the system. That's because when you pull the channels, you updated the list of package definitions available with their versions. This means that the latest version of Emacs available becomes Emacs 30, while you're still running Emacs 28. Pulling will NOT upgrade packages, it will just make the new versions available. On the other hand, system reconfigure will update packages if the pulled channels indicate that an update is available.

Note: Avoid running any guix configuration commands under the root user. Using sudo will ensure that your user configured channels are used, if you would like to reconfigure your system as root then you will have to also maintain another list of channels and keep them up to date which is not convenient. Rule of thumb: you probably never want to run any of the Guix commands as a root user, you should use sudo when superuser privileges are required.

Home Configuration

Now that you have a good idea how to modify and apply system level configuration, let's dive into modify your user level configuration (referred to as home configuration). Guix Home configuration allows you to set packages and services per user. Packages are software to be installed, while services can be actual sheperd services, configuration manager.

Creating Home Configuration

  1. Create or edit your ~/.config/guix/home.scm file to include your desired configuration. Here's an example:
(use-modules (gnu home)
             (gnu home services)
             (gnu home services shells)
             (gnu services)
             (gnu packages admin)
             (guix gexp))

(home-environment
 (packages (list htop))
 (services
  (list
   (service home-bash-service-type
            (home-bash-configuration
             (guix-defaults? #t)
             (bash-profile (list (plain-file "bash-profile" "\
export HISTFILE=$XDG_CACHE_HOME/.bash_history"))))))))

Note: we define packages and services for our home configuration. our list of packages in this example is htop only. The services is only home-bash-configuration which create the file bash-profile.

Note: notice that we import some modules that expose the package htop (gnu packages admin) and the home-bash-service-type (gnu home services shells). Read more about how to find out the modules in Installing Packages. Guix also has a utility that will search for package from a string only (not recommended but works).

(packages (map specification->package '(
            "btop"
            "alacritty"
            "gimp"))
  1. Save the file and apply your home configuration:
guix home reconfigure ~/.config/guix/home.scm

Applying the home configuration above will install htop to your home configuration (user level) and create modify the .bash-profile to define the environment variable HISTFILE to the path defined.

Installing Packages

At this point, it should be clear that you can declare your packages either in system.scm to become system level packages that can be accessed by all users on the system, or in home.scm to become user level packages that can be only access by the user who applies the home.scm to their home. We also agreed that it's recommended to install packages on user level if possible to avoid any version conflicts, give more flexibility to users regarding when to upgrade, and have a minimal system configuration that doesn't require frequent updates as opposed to user configuration that might be updated very regularly.

Finding Packages

Similar to any other Linux distribution, Guix comes with its own utility to search and install packages. performing a simple Guix search [PACKAGE_NAME] will list available packages that contain the query in their package name or description. Below is an example to try to search for firefox.

guix search firefox

output:

name: firefox
version: 128.0
outputs:
+ out: everything
systems: x86_64-linux
dependencies: alsa-lib@1.2.4 autoconf@2.13 bzip2@1.0.8 cairo@1.18.0 clang@18.1.8 cups@2.4.2 dbus-glib@0.112 eudev@3.2.14 ffmpeg@6.1.1 freetype@2.13.0 gdk-pixbuf@2.42.10 glib@2.78.0
+ gtk+@2.24.33 gtk+@3.24.41 hunspell@1.7.0 icu4c@73.1 jemalloc@5.3.0 libcanberra@0.30 libevent@2.1.12 libffi@3.4.4 libgnome@2.32.1 libjpeg-turbo@2.1.4 libnotify@0.8.3 libva@2.19.0
+ libvpx@1.12.0 libxcomposite@0.4.5 libxft@2.3.4 libxinerama@1.1.4 libxscrnsaver@1.2.4 libxt@1.2.1 llvm@13.0.1 m4@1.4.19 mesa@24.0.4 mit-krb5@1.20 nasm@2.15.05 node@18.19.0 nspr@4.32
+ pango@1.50.14 perl@5.36.0 pipewire@1.0.3 pixman@0.42.2 pkg-config@0.29.2 pulseaudio@16.1 python@3.10.7 rust-cbindgen@0.26.0 rust@1.77.0 speech-dispatcher@0.11.5 sqlite@3.39.3
+ startup-notification@0.12 unzip@6.0 wasm32-wasi-clang-toolchain@15.0.7 which@2.21 yasm@1.3.0 zip@3.0 zlib@1.2.13
location: nongnu/packages/mozilla.scm:544:2
homepage: https://mozilla.org/firefox/
license: MPL 2.0
synopsis: Trademarkless version of Firefox
description: Full-featured browser client built from Firefox source tree, without the official icon and the name "firefox".
relevance: 37

name: icecat
version: 115.13.0-guix1
outputs:
+ out: everything
systems: x86_64-linux
dependencies: alsa-lib@1.2.4 bzip2@1.0.8 cairo@1.18.0 clang@15.0.7 cups@2.4.2 dbus-glib@0.112 eudev@3.2.14 ffmpeg@5.1.4 font-dejavu@2.37 freetype@2.13.0 gdk-pixbuf@2.42.10 glib@2.78.0
+ gtk+@3.24.41 hunspell@1.7.0 icu4c@73.1 libcanberra@0.30 libevent@2.1.12 libffi@3.4.4 libgnome@2.32.1 libjpeg-turbo@2.1.4 libnotify@0.8.3 libpng-apng@1.6.39 libvpx@1.12.0
+ libxcomposite@0.4.5 libxft@2.3.4 libxinerama@1.1.4 libxscrnsaver@1.2.4 libxt@1.2.1 llvm@15.0.7 m4@1.4.19 mesa@24.0.4 mit-krb5@1.20 nasm@2.15.05 node@18.19.0 nspr@4.35 pango@1.50.14
+ pciutils@3.8.0 perl@5.36.0 pixman@0.42.2 pkg-config@0.29.2 pulseaudio@16.1 python-wrapper@3.10.7 rust-cbindgen@0.26.0 rust@1.75.0 shared-mime-info@2.3 sqlite@3.39.3 unzip@6.0 which@2.21
+ yasm@1.3.0 zip@3.0 zlib@1.2.13
location: gnu/packages/gnuzilla.scm:2001:4
homepage: https://www.gnu.org/software/gnuzilla/
license: MPL 2.0
synopsis: Entirely free browser derived from Mozilla Firefox
description: IceCat is the GNU version of the Firefox browser.  It is entirely free software, which does not recommend non-free plugins and addons.  It also features built-in
+ privacy-protecting features.  This package also includes the `geckodriver' command, which can be useful for automated web testing.
relevance: 5

Let's try to analyze the output, you will most likely see so many packages. The exciting part here is that if you don't configure the Nonguix channel, you will not see firefox listed as it has some trademark on its arts. However, we will see ictcat which is described as the GNU version of firefox. We can also see the location of the package which we can use to import the package module into our configuration.

We can also minimize the output to get only the information we are interested in Note: there is an easier way to perform this task using recsel but it's not installed by default.

guix search firefox | grep -E "^(name|version|location)" | sed '/location:/a \\n'

output:

name: firefox
version: 128.0
location: nongnu/packages/mozilla.scm:544:2

name: icecat
version: 115.13.0-guix1
location: gnu/packages/gnuzilla.scm:2001:4

Now we can quickly identify the name of the package, available version, and the location of the package definition and even the line in which it's defined in the module.

Installing a package

To install firefox, we will declare it in our home configuration since a browser is typically a user level program (doesn't have to be available to all users, they can install it if they desire).

  1. Identify your target package name and location

In our case, target is firefox, location is nongnu/packages/mozilla.scm

  1. Declare the module in your home configuration (system configuration if you want system level) by adding a new import to use-modules. This import should match the location with slashes replaced by spaces and without the extension .scm

nongnu/packages/mozilla.scm > =nongnu packages mozilla

(use-modules (gnu home)
              (gnu home services)
              (gnu home services shells)
              (gnu services)
              (gnu packages admin)
              (guix gexp)

			  ;; ensure that the paranthesis are closed and your definition is inside
              (nongnu packages mozilla))
  1. Add the package name to the list of packages
(packages (list htop firefox))
  1. Save the file and apply your home configuration:
guix home reconfigure ~/.config/guix/home.scm

Note: Bare in mind that installing packages from the Guix utility is as simple as guix install htop, but this is not very declarative, and even though there are ways to extract installed packages, in my opinion, it's best to declare them in your configuration and then apply them. However, one might want to try packages first with guix install [PACKAGE_NAME] and then see if they would like to keep it. Without this package name specified in your system or home configuration file, next system or home reconfigure will uninstall these packages.

Note: sometimes you will need to logout from your account/shell and login again for environment variables to be updated, before you assume that the package wasn't installed, try to reboot or logout.