Getting Started with Guix Home

Intro

Don’t you hate it when you spend a lot of time configuring the tools you use for your personal workflow on Linux and then later have to figure out how to replicate it all on another machine?

How about when you install an update to your window manager or some other program and you can’t seem to log back in to your desktop environment?

In this video I’m going to show you the quickest way to start using Guix Home to manage the chaos of your personal computing configuration. I’ll explain a little bit about how it works and then I’ll walk you through a basic home-environment configuration so that you can get started with it quickly.

Let’s get started!

Understanding Guix Home

Guix Home is a feature of GNU Guix which makes it possible to install and apply configurations for the tools you use in your day to day computing workflow.

It uses the same configuration model as Guix System but applied to your $HOME folder instead of the entire system.

Here’s an example of a basic home-environment configuration file named home-config.scm which installs a couple of programs and configures Bash with a few useful settings:

(use-modules (gnu)
             (gnu home)
             (gnu home services shells))

(home-environment
 (packages (specifications->packages
            (list "git"
                  "emacs-no-x-toolkit")))

 (services (list (service home-bash-service-type
                          (home-bash-configuration
                           (environment-variables '(("PS1" . "\\[\\e[1;32m\\]\\u \\[\\e[1;34m\\]\\w \\[\\e[0m\\]λ ")
                                                    ("EDITOR" . "emacsclient")))
                           (aliases '(("gs" . "git status"))))))))

Let’s walk through this line by line:

The use-modules expression imports a number of modules that provide packages and services that we’ll use in this home configuration. The Guix manual pages will tell you which module you need to import to use each service type.

home-environment is the actual configuration expression that gets evaluated when guix home reads this file. You will most often deal with the two primary fields, packages and services.

The packages field expects a list of packages for software to be installed in your home folder. We’re using the specifications->packages procedure in this case to pass a list of strings representing Guix packages so that it returns the corresponding package definitions. We’ll talk more about this in a later video!

The services field expects a list of home services with their associated configurations. In this case, we’re including the home-bash-service-type which accepts a home-bash-configuration to customize various aspects of Bash across its own configuration files.

The home-bash-configuration expression is used here to set a couple of environment-variables and aliases in the resulting ~/.bash_profile and ~/.bashrc files. More details and configuration fields can be found in the Guix manual.

What is a service?

A quick side note on Guix services:

A “service” in Guix is not simply a program that runs in the background like in most Linux systems. It is actually the mechanism for applying a number of things to your system or home configuration:

  • Placing configuration files needed by the associated program
  • Installing packages to enable the configuration to operate
  • Creating special user accounts or other system-level configuration
  • Optionally configuring background services to run at the system or user level

We’ll cover services in more detail in a future video, including writing your own home services!

Testing the Configuration

Now that we’ve got this configuration ready, it’d be great to test it out without breaking our current home folder setup. Luckily Guix Home provides us with the guix home container command to see the final result configured in a temporary container environment!

Let’s test out this configuration:

guix home container ~/dotfiles/config/home/home-config.scm

Once the new configuration is built, we will immediately be dropped into a Bash shell in the container environment. The custom Bash prompt and aliases we configured are already active and emacs is available on the $PATH.

If we run a quick ls command, we’ll be able to see the .bash_profile and .bashrc files that were generated for us by home-bash-profile-service:

crafter ~ λ ls -al
total 0
drwxr-xr-x 5 crafter users 180 Nov  1 09:19 ./
drwxr-xr-x 3 crafter users  60 Nov  1 09:19 ../
lrwxrwxrwx 1 crafter users  56 Nov  1 09:19 .bash_profile -> /gnu/store/g779bp3xz2ipyy2pld1vxkdi6vizs39c-bash_profile
lrwxrwxrwx 1 crafter users  50 Nov  1 09:19 .bashrc -> /gnu/store/5dvm2bfwfwan5hsaxl1icqkmbf0wmjf0-bashrc
drwxr-xr-x 2 crafter users  40 Nov  1 09:19 .cache/
drwxr-xr-x 3 crafter users  60 Nov  1 09:19 .config/
lrwxrwxrwx 1 crafter users  48 Nov  1 09:19 .guix-home -> /gnu/store/0jg05s4gxf5ynqrrqkc75w3hr0qvwi2k-home
drwxr-xr-x 4 crafter users  80 Nov  1 09:19 .local/
lrwxrwxrwx 1 crafter users  57 Nov  1 09:19 .profile -> /gnu/store/nqribhmgwcmd8fgblwkcsi1x4wsy2m1h-shell-profile

These generated files are actually symbolic links into the /gnu/store path which is where Guix keeps all of the configuration files it generates before linking them into your $HOME folder. We’ll talk more about this a bit later in the video.

Applying the Configuration

Once you’ve inspected the $HOME folder inside of the container and tested that the appropriate programs are installed, it’s now time to apply the configuration to your actual home folder!

To do this, we use the guix home reconfigure command:

guix home reconfigure ~/dotfiles/config/home/home-config.scm

After this command completes, your home folder will be updated with the result of building your home-environment configuration!

But wait, what if guix home had to overwrite files that already existed in your $HOME folder like Bash configuration files?

Don’t worry, if any existing configuration files get replaced, they will be stashed away in one of the <timestamp>-guix-home-legacy-configs-backup folders that get created in your $HOME folder.

crafter ~ λ ls -al 1730454615-guix-home-legacy-configs-backup/
total 16
drwxr-xr-x 2 crafter users 4096 Nov  1 11:50 ./
drwx------ 8 crafter users 4096 Nov  1 12:48 ../
-rw-r--r-- 1 crafter users  447 Nov  1 11:02 .bash_profile
-rw-r--r-- 1 crafter users  719 Nov  1 11:02 .bashrc

This gives you an opportunity to back these old files up or figure out how to integrate the needed parts into your Guix Home configuration so that they get applied in the future.

These folders are not needed by Guix Home, they just contain any files that had to be replaced with your new configuration. If you don’t need the replaced files anymore, you can just delete these folders to clear away the cruft.

Migrating Your Existing Configuration

Now you’re probably thinking “well this looks great, but what about all of the configuration files that I’ve hand-crafted over the years?”

Luckily, Guix Home provides a solution for integrating your existing configuration files into your new home-environment configuration, the home-dotfiles-service-type. You’ll need to make sure you’re up to date with guix pull to use it!

This service accepts a list of directories, each of which containing a folder structure that should be symbolically linked directly into your $HOME folder. For example, if you give it a folder containing a subpath of .emacs.d/init.el, this will be linked directly into your home folder as ~/.emacs.d/init.el.

The Guix manual provides more details and examples about how the folder symlinking works including additional useful options.

Here’s an updated configuration that uses the home-dotfiles-service-type:

(use-modules (gnu)
             (gnu home)
             (gnu home services dotfiles)
             (gnu home services shells))

(home-environment
 (packages (specifications->packages
            (list "git"
                  "emacs-no-x-toolkit")))

 (services (list (service home-bash-service-type
                          (home-bash-configuration
                           (environment-variables '(("PS1" . "\\[\\e[1;32m\\]\\u \\[\\e[1;34m\\]\\w \\[\\e[0m\\]λ ")
                                                    ("EDITOR" . "emacsclient")))
                           (aliases '(("gs" . "git status")))))

                 (service home-dotfiles-service-type
                          (home-dotfiles-configuration
                           (directories '("../../files")))))))

An important details is that the paths you pass to directories are considered to be relative to the path of the home configuration file! In this case, our config file is located at ~/dotfiles/config/home/home-config.scm and the files folder is at ~/dotfiles/files so the relative path becomes ../../files.

After we apply this configuration with guix home reconfigure, we can see the Emacs and Sway configurations linked into the home folder:

crafter ~ λ ls -al ~/.emacs.d/
total 16
drwx------ 3 crafter users 4096 Nov  3 14:18 ./
drwx------ 8 crafter users 4096 Nov  3 14:18 ../
drwx------ 2 crafter users 4096 Nov  1 12:51 auto-save-list/
lrwxrwxrwx 1 crafter users   74 Nov  3 14:18 init.el -> /gnu/store/y6i4ibz1cy5ns1jnr1wfqisl8j53037h-home-dotfiles--emacs-d-init-el

crafter ~ λ ls -al ~/.config/sway/
total 12
drwxr-xr-x 2 crafter users 4096 Nov  3 14:18 ./
drwxr-xr-x 7 crafter users 4096 Nov  3 14:18 ../
lrwxrwxrwx 1 crafter users   77 Nov  3 14:18 config -> /gnu/store/spl92skqqjx94xj80m3mir2gba9qdpsw-home-dotfiles--config-sway-config

Why can’t I edit the files?

One curious thing that happens when you use home-dotfiles-service-type is that the symlinked files are marked as read only!

This is because Guix is taking your files and copying them into the “store” where all files meant to be immutable, meaning they should not be edited to preserve the current state of the system.

This is actually a good thing! It’s how Guix provides you with stability guarantees because random configuration changes won’t break your system unless you use guix home reconfigure to apply the new changes.

You can sometimes get around this in programs like Emacs which enable you to re-evaluate sections of your configuration without reloading the entire configuration file.

Rolling it Back!

One of the greatest benefits of using Guix Home to manage your $HOME folder is that you can quickly fix your configuration when it breaks!

If you realize that there’s some problem with your configuration after you apply it, you can always roll it back to the previous generation using the guix home roll-back command:

guix home roll-back

Not only will this put your configuration files back the way they were before the last time you ran guix home reconfigure, it will also downgrade any programs back to the versions you had installed at the time. This can save you from a huge headache if something goes wrong!

Guix Home actually stores many of the previous “generations” (builds) of your configuration so you can even go back further in time when things really go wrong.

If you’d like to see all of the previous “generations” that you can roll back to, check out the guix home list-generations command:

crafter ~ λ guix home list-generations
Generation 1    Nov 01 2024 11:19:16
  file name: /var/guix/profiles/per-user/crafter/guix-home-1-link
  canonical file name: /gnu/store/0jg05s4gxf5ynqrrqkc75w3hr0qvwi2k-home
  channels:
    guix:
      repository URL: https://git.savannah.gnu.org/git/guix.git
      branch: master
      commit: e85f52e826b0701c3dcf9acf9d81e5ae57aec8f9
  configuration file: /gnu/store/hs82gqczyd5qms3nkcn8874kbchxnchj-configuration.scm
Generation 2    Nov 01 2024 11:54:03    (current)
  file name: /var/guix/profiles/per-user/crafter/guix-home-2-link
  canonical file name: /gnu/store/alhvq73niq128l6lbaxalw89abfyqmng-home
  channels:
    guix:
      repository URL: https://git.savannah.gnu.org/git/guix.git
      branch: master
      commit: e85f52e826b0701c3dcf9acf9d81e5ae57aec8f9
  configuration file: /gnu/store/70r2if11ffgi5sd7dby4wmsqhlz5i79w-configuration.scm

You can switch to a specific generation using the guix home switch-generation command, passing it the desired generation number:

crafter ~ λ guix home switch-generation 1
switched from generation 2 to 1
WARNING: (guile-user): imported module (guix build utils) overrides core binding `delete'
Cleaning up symlinks from previous home at /gnu/store/alhvq73niq128l6lbaxalw89abfyqmng-home.

Removing /home/crafter/.profile... done
Removing /home/crafter/.bash_profile... done
Removing /home/crafter/.bashrc... done
Removing /home/crafter/.config/fontconfig/fonts.conf... done
Removed /home/crafter/.config/fontconfig.
Removing /home/crafter/.config/sway/config... done
Removed /home/crafter/.config/sway.
Skipping /home/crafter/.config (not an empty directory)... done
Removing /home/crafter/.emacs.d/init.el... done
Skipping /home/crafter/.emacs.d (not an empty directory)... done
Cleanup finished.

Symlinking /home/crafter/.profile -> /gnu/store/nqribhmgwcmd8fgblwkcsi1x4wsy2m1h-shell-profile... done
Symlinking /home/crafter/.bash_profile -> /gnu/store/g779bp3xz2ipyy2pld1vxkdi6vizs39c-bash_profile... done
Symlinking /home/crafter/.bashrc -> /gnu/store/5dvm2bfwfwan5hsaxl1icqkmbf0wmjf0-bashrc... done
Symlinking /home/crafter/.config/fontconfig/fonts.conf -> /gnu/store/waz5zaijm4sklnwksk33x6p0p98p24f8-fonts.conf... done
 done
Finished updating symlinks.

Comparing /gnu/store/alhvq73niq128l6lbaxalw89abfyqmng-home/profile/share/fonts and
          /gnu/store/0jg05s4gxf5ynqrrqkc75w3hr0qvwi2k-home/profile/share/fonts... done (same)
Evaluating on-change gexps.

On-change gexps evaluation finished.

This will put us back to the state of your configuration before we linked our existing configuration files into the $HOME folder!

Conclusion

That’s it for our introductory look at how Guix Home can help you manage the chaos of your personal computing configuration!

In future videos I’ll show you some other useful home services that can help you craft an awesome computing environment with all the benefits of Guix Home!

Subscribe to the System Crafters Newsletter!
Stay up to date with the latest System Crafters news and updates! Read the Newsletter page for more information.
Name (optional)
Email Address