(setq plaintext 'everywhere)



Getting Started With Guix Home

Table of Contents

1 Introduction

[2023-10-18 Wed]

Guix-home is part of the guix package manager and allows you to configure your home environment (your dotfiles) in a declarative way. It provides you with all the benefits of guix, such as rolling back your configuration, but for your home environment. You also no longer need another program such as gnu-stow or chezmoi to manage you dotfiles and it works both on the guix system as well as on foreign distros.

2 Testing

Once you have a config you can test it inside a throw away container with:

guix home container home-configuration.scm

And to apply it to your actual system run:

guix home reconfigure home-configuration.scm

3 Shells

If you already use guix as a package manager then letting guix-home configure your shell(s) will make your life easier as it automatically sets the proper environment variables and sources your guix profiles. The shells that can be configured with guix-home, at the time of writing, are zsh, bash and fish.

A basic home configuration with bash looks like this:

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

(home-environment
 ;; (package (list package-name))
 (services
  (list (service home-bash-service-type
                 (home-bash-configuration
                  (guix-defaults? #f)
                  (bashrc (list (local-file ".config/bash/bashrc")))
                  (aliases '(("grep" . "grep --color=auto")
                             (".."   . "cd ../")))
                  (bash-profile (list (local-file ".config/bash/bash_profile"))))))))

The package definition is where you specify the package that should be include in your guix-home profile. I will not go into detail on it here.

The (guix-defaults? #f) will make sure that only your configuration is included in the resulting .bashrc configuration. The main bashrc configuration is taken from a local file, .config/bash/bashrc (relative to the guix-home config file). Using (local-file...) is the easiest way to migrate to guix-home without having to rewrite all you dotfiles to guile scheme, it also allows you to edit the config file in the major mode specific to that file (if you use emacs). The aliases are defined explicitly and must be list of cons pairs where each cons pair consists of ("alias_name" . "alias value"), that will be written to ~/.bashrc as

alias alias_name="alias_value"

Configurations for the other shells look very similar.

4 Environment Variables

You can also define you environment variables inside you guix-home configuration. They will be system wide variables that are sourced from the ~/.profile file.

Just like the bash aliases, environent variables are defined in a list of cons pairs. A simple configuration will look like:

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

(home-environment
 ...
 (simple-service 'br/env-vars-service
                 home-environment-variables-service-type
                 `(("BROWSER" . "librewolf")
                   ("EDITOR"  . "emacsclient --create-frame --alternate-editor=")
                   ("SHELL"   . ,(file-append fish "/bin/fish")))))

br/env-vars-service is just a placeholder and can be named whatever you like and the definitions of the environment variables follow the same idea as the bash aliases described above. One interesting part is the definition of SHELL; (file-append fish "/bin/fish") will expand to the new guix-home profile directory. That way you will always use the latest installed version of fish.

5 Channels

If you use channels other than the default ones you can extend the home-channels-service-type like this:

(use-modules
 ...
 (gnu home services guix)
 (guix channels))

(home-environment
 ...
 (simple-service 'br/home-channels-service
                 home-channels-service-type
                 (list
                  (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")))))))

The example adds the nonguix channel to the list of channels.

6 Other Configuration Files

To search for guix-home service types you can run

guix home search "home"

from the terminal, replace home with a key word that you are interested in to narrow down the search results. For all configuration files that do not have a specific service type and that reside inside XDG_CONFIG_HOME you can use the service type home-xdg-configuration-files-service-type.

(use-modules
 ...
 (gnu home services xdg))

(home-environment
 ...
 (service home-xdg-configuration-files-service-type
          (map br/xdg-config-files-symlink-target
               '(
                 "alacritty/alacritty.yml"
                 "emacs/early-init.el"
                 "emacs/init.el"
                 ))))

To reduce the verbosity of the home-xdg-configation-files-service-type configuration, I created a function that expands every string in the given list to a cons pair of ("SOURCE" . "TARGET"), as can be seen above. The function is defined as:

(define (br/xdg-config-files-symlink-target file)
  ;; Create a list such that it can be used with
  ;; 'home-xdg-configuration-files-service-type'.
  (list file
        (local-file (string-append
                     (or (getenv "DOTFILE_DIR")
                         (string-append (getenv "HOME")
                                        "/.local/my-projects/dotfiles"))
                     "/.config/" file))))

It assumes that you either have the environent variable DOTFILE_DIR set to where you dotfiles live or that you dotfiles live in ~/.local/my-projects/dotfiles. It also assumes that the dofile directory has a .config directory that resembles XDG_CONFIG_HOME.

7 Combining Everything

Combining all the above configurations will results in:

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

(define (br/xdg-config-files-symlink-target file)
  ;; Create a list such that it can be used with
  ;; 'home-xdg-configuration-files-service-type'.
  (list file
        (local-file (string-append
                     (or (getenv "DOTFILE_DIR")
                         (string-append (getenv "HOME")
                                        "/.local/my-projects/dotfiles"))
                     "/.config/" file))))

(home-environment
 ;; (package nil)
 (services
  (list (service home-bash-service-type
                 (home-bash-configuration
                  ;; the defaults are included in my bash/bashrc
                  ;; without the aliases
                  (guix-defaults? #f)
                  (bashrc (list (local-file ".config/bash/bashrc")))
                  ;; not all abbreviations make sense as aliases
                  (aliases '(("grep" . "grep --color=auto")
                             (".."   . "cd ../")))
                  (bash-profile (list (local-file ".config/bash/bash_profile")))))
        (simple-service 'br/env-vars-service
                        home-environment-variables-service-type
                        `(("BROWSER" . "librewolf")
                          ("DMENU"   . "dmenu -i -p")
                          ("EDITOR"  . "emacsclient --create-frame --alternate-editor=")
                          ("SHELL"   . ,(file-append fish "/bin/fish"))))
        (simple-service 'br/home-channels-service
                        home-channels-service-type

                        (list
                         (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"))))))
        (service home-xdg-configuration-files-service-type
                 (map br/xdg-config-files-symlink-target
                      '(
                        "alacritty/alacritty.yml"
                        "emacs/early-init.el"
                        "emacs/init.el"
                        ))))))

You should store this configuration in home-configuration.scm at the root of your dotfile directory.

8 Sources



If something is not working, please create an issue here.