Keeping one’s home tidy
How much effort to recreate your work environment when you switch to a new machine? What would it take to roll back to your previous environment once you’ve noticed a program no longer behaves as expected? What about sharing your environment with friends of yours? These are some of the things that Guix Home, which landed in Guix as a “technology preview” in September 2021, aims to make effortless, reliable, and fun.
In a nutshell, Guix Home brings the fully declarative configuration of Guix System to home directories. With Guix System, users and administrators provide a configuration file that defines the operating system configuration; with Guix Home, users provide a configuration file that defines the configuration of their work environment in their home directory—their home environment. That configuration is meant to stand alone, to describe all the relevant aspects of your work environment. But what exactly goes in a home environment?
“Dot files” don’t live in a vacuum
Among seasoned Unix-style users, we often equate “home environment” with
“dot files”—configuration files in our home directory, from
~/.emacs and everything under
These files are precious and many store them under version control, to
keep track of changes made to their configuration. That’s a good idea,
but is that all it takes to describe the home environment? To roll
back to a previous version?
Of course not. Dot files don’t exist in a vacuum; at the very least, your home environment is not just a set of dot files, but also a set of installed packages. They work together: if you upgrade a package, the corresponding dot file might need to be adjusted; if a package is missing, its dot file is not of any use. Sometimes a home environment contains additional things: daemons (programs that run in the background), or periodically executed jobs.
Guix Home goes beyond dot files: it lets you declare and instantiate all these aspects that make up your home environment.
Guix Home was initially developed by Andrew Tropin as part of the rde project; it was integrated in Guix proper six months ago. I am writing this as an adopter and contributor, but there were a number of earlier adopters and earlier contributors. In fact, despite being still very much under development, the tool has already attracted a number of excited users eager to find a way to keep their home tidy!
The idea of writing down a declaration of your home environment that you can reproduce anytime is a natural followup to everything Guix does—you could already declare a package set in a manifest or even a complete operating system. It had been floating around, in Nix land with Home Manager and in Guix land with the now-defunct Guix Home Manager by Julien Lepiller. The latter was similar to today’s Guix Home, but went one step further by making your home directory read-only—yes, read-only! The main advantage is that it would ensure statelessness—you’d be sure that absolutely all your home configuration is under Guix Home Manager’s control; sub-directories containing mutable data would have to be explicitly declared. The downside is that it raised the barrier to entry: you’d have to either switch entirely, or not use it at all. Guix Home takes a more pragmatic approach and happily coexists with configuration managed “the old way”.
To get started, you need a Home configuration file. There’s
but as always, starting from a blank page is a bit intimidating. So
instead of starting from a blank page, you can let
guix home import
generate an initial config for you:
guix home import ~/src/guix-config
This will create the
~/src/guix-config directory and populate it with a
bunch of files among which
home-configuration.scm along these lines:
(use-modules (gnu home) (gnu packages) (gnu services) (guix gexp) (gnu home services shells)) (home-environment (packages (map (compose list specification->package+output) (list "emacs-geiser-guile" "emacs-geiser" "pinentry-emacs" "emacs-exwm" "gnome-maps" "pipe-viewer" "emacs" "pavucontrol" "git" "xterm" "qemu" "openssh"))) (services (list (service home-bash-service-type (home-bash-configuration (aliases '(("grep" . "grep --color=auto") ("ll" . "ls -l") ("ls" . "ls -p --color=auto") ("qemu" . "qemu-system-x86_64 -enable-kvm -m 512") ("rm" . "rm --one-file-system"))) (bashrc (list (local-file "/home/charlie/src/guix-config/.bashrc" "bashrc"))) (bash-profile (list (local-file "/home/charlie/src/guix-config/.bash_profile" "bash_profile"))))))))
guix home import automatically added the packages of
packages field. Because I’m using
Bash, it also added an instance of
with aliases extracted from my
~/.bashrc; it also made copies of
~/.bash_profile and refers to them.
Now that I have an initial configuration, I can first test it in an isolated container:
guix home container ~/src/guix-config/home-configuration.scm
This command gives an interactive shell in a container where my home
environment, as declared in
home-configuration.scm, is deployed.
There I can see my home directory as it would look like if I deploy my
home environment “for real”: I can see my
~/.bashrc and co., I can
check that all the packages declared are in
$PATH and visible in
~/.guix-home, and so on. And all this is safe: my actual home
directory has been left unchanged!
Once satisfied with my configuration, I can instantiate it:
guix home reconfigure ~/src/guix-config/home-configuration.scm
At that point, my actual home directory corresponds to that
configuration. Some of my dot files are now provided by Guix Home, and
thus they’re symbolic links (“symlinks”) to their read-only copy in
$ ls -l ~/.bashrc ~/.bash_profile lrwxrwxrwx 1 charlie users 56 Mar 7 15:46 /home/charlie/.bash_profile -> /gnu/store/lpdydssyyxx9n0xvp2jmv7yqgyr2pcg3-bash_profile lrwxrwxrwx 1 charlie users 50 Mar 7 15:46 /home/charlie/.bashrc -> /gnu/store/kxc0j4i05sib04vf92nr8xxkb8isdfn7-bashrc
But don’t worry: before creating those symlinks,
guix home reconfigure
created backups of existing files under
TIMESTAMP is a
And voilà, I have my first Guix Home generation!
$ guix home describe Generation 1 Mar 07 2022 15:46:20 (current) file name: /var/guix/profiles/per-user/charlie/guix-home-1-link canonical file name: /gnu/store/qr1c5jpfrj815ncv6yr2lfdgs8nq8kkn-home channels: guix: repository URL: https://git.savannah.gnu.org/git/guix.git branch: master commit: 3ac1366648f933f7244c2d0b9926f7ba5d92a113 configuration file: /gnu/store/xfgasfms9rhhigyj7i8za77zpqx6zbhn-configuration.scm
guix home describe shows provenance tracking we know and love from
Guix System: all the info we need to redeploy the same home environment
elsewhere, or at a different point in time. It’s also information
guix home reconfigure relies on to make sure you never accidentally
downgrade you home environment to an older Guix revision.
Alright, at this point, you might be thinking that it’s a lot of fuss
but the “only” benefit over dot files under version control is that
guix home also takes care of installing packages. Guix Home really
shines once you use higher-level services, and when you start composing
To the example above, in the
services field, we can add a service
declaration that runs
a program that adjusts the display color temperature according to the
time of day:
(service home-redshift-service-type (home-redshift-configuration (location-provider 'manual) (latitude 35.81) ;northern hemisphere (longitude -0.80))) ;west of Greenwich
The effect is that, as soon as we log in, under Xorg, Redshift will be
started in the background as a Shepherd
~/.profile takes care of spawning
in turn spawns the
$ herd status Started: + root + redshift
We gained another thing here: a consistent, unified configuration
language. Instead of learning Redshift’s configuration file format, we
home-redshift-configuration record, right in Scheme. Under
the hood, that configuration is converted into Redshift’s file format;
any error is caught at configuration time, when running
guix home reconfigure, and we can be sure that Redshift is passed a valid
We can similarly define a periodic mcron job, for example one that updates a GNU Idutils search database (that’s a pretty convenient and speedy way to look for code or documents!):
(simple-service 'idutils home-mcron-service-type ;; Every day at 12:15 and 19:15. (list #~(job '(next-minute-from (next-hour '(12 19)) '(15)) (string-append #$idutils "/bin/mkid \ -o $HOME/.idutils/src.db $HOME/src"))))
guix home creates a Shepherd service that start mcron with a
configuration file containing definitions for periodic jobs, which we
can inspect via
$ herd schedule mcron | head -5 Sun Mar 20 19:15:00 2022 +0000 /gnu/store/2d026nan309qkci968k8gpa8fcv9q4mv-idutils-4.6/bin/mkid -o $HOME/.idutils/src $HOME/src Mon Mar 21 12:15:00 2022 +0000 /gnu/store/2d026nan309qkci968k8gpa8fcv9q4mv-idutils-4.6/bin/mkid -o $HOME/.idutils/src $HOME/src
If you already use Guix System, all the above certainly looks familiar:
Guix Home builds upon the service
that powers Guix System; Home services are defined in the
(gnu home services …) module
That framework lets us define relations among
“services”, in a broad sense, and how services extend each other—in
the example above,
mcron both extend
giving it a daemon to take care of. We can see those relations at play
guix home extension-graph home-configuration.scm
… which, for the configuration described above, gives a graph that looks like this:
shepherd, but we also see lower-level
guix home instantiates for us, such as the
service which takes care of deploying packages listed in the
~/.guix-home/profile. Each arrow denotes a service
extension. You can read
about service composition. To satisfy our math and
functional-programming geek audience, we should mention that service
types and their extension operation form a
Let’s be clear: Guix Home is pretty new and chances are that
guix home search—the command to search for services by keyword—won’t give you the
service you’re looking for. There’s also a bunch of open questions
left, such as how to reuse services initially defined for Guix System in
cases where they could be equally useful in Guix
But while it’s still a “technology preview”, it’s already a tool that tinkerers can play with and benefit from. Patches adding new services have already been proposed; maybe your favorite service is next? Consider contributing.
With a new release and ten-year anniversary coming up, we’re happy to celebrate with a tool that extends the reach of declarative and reproducible deployment!
About GNU Guix
GNU Guix is a transactional package manager and an advanced distribution of the GNU system that respects user freedom. Guix can be used on top of any system running the Hurd or the Linux kernel, or it can be used as a standalone operating system distribution for i686, x86_64, ARMv7, AArch64 and POWER9 machines.
In addition to standard package management features, Guix supports transactional upgrades and roll-backs, unprivileged package management, per-user profiles, and garbage collection. When used as a standalone GNU/Linux distribution, Guix offers a declarative, stateless approach to operating system configuration management. Guix is highly customizable and hackable through Guile programming interfaces and extensions to the Scheme language.