https://guix.gnu.org/feeds/blog/home.atomGNU Guix — Blog — Homefeed author nameGNU Guixhttps://guix.gnu.org/themes/initial/img/icon.png2024-03-20T10:57:55Zhttps://guix.gnu.org/blog/2022/keeping-ones-home-tidy//Keeping one’s home tidyLudovic Courtès2022-03-21T15:30:00Z2022-03-21T15:30:00Z 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…<p>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 <a href="https://guix.gnu.org/manual/devel/en/html_node/Home-Configuration.html">Guix
Home</a>,
which landed in Guix as a “technology preview” in September 2021, aims
to make effortless, reliable, and fun.</p><p>In a nutshell, Guix Home brings the <a href="https://guix.gnu.org/manual/devel/en/html_node/Using-the-Configuration-System.html">fully declarative configuration of
Guix
System</a>
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
<em>home environment</em>. That configuration is meant to <em>stand alone</em>, to
describe all the relevant aspects of your work environment. But what
exactly goes in a home environment?</p><h1>“Dot files” don’t live in a vacuum</h1><p>Among seasoned Unix-style users, we often equate “home environment” with
“dot files”—configuration files in our home directory, from <code>~/.bashrc</code>
and <code>~/.ssh/config</code> to <code>~/.emacs</code> and everything under <code>~/.config</code>.
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?</p><p>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.</p><p>Guix Home goes beyond dot files: it lets you declare and
instantiate all these aspects that make up your home environment.</p><h1>Genesis</h1><p>Guix Home was initially developed by Andrew Tropin as part of the <a href="https://git.sr.ht/~abcdw/rde">rde
project</a>; 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!</p><p>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
<a href="https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-package.html#index-profile-manifest">manifest</a>
or even a <a href="https://guix.gnu.org/manual/devel/en/html_node/Using-the-Configuration-System.html">complete operating
system</a>.
It had been floating around, in Nix land with <a href="https://github.com/nix-community/home-manager">Home
Manager</a> and in Guix land
with the now-defunct <a href="https://framagit.org/tyreunom/guix-home-manager/">Guix Home
Manager</a> 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, <em>read-only</em>!
The main advantage is that it would ensure statelessness—you’d be sure
that absolutely <em>all</em> 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”.</p><h1>Getting started</h1><p>To get started, you need a Home configuration file. There’s
<a href="https://guix.gnu.org/manual/devel/en/html_node/Declaring-the-Home-Environment.html">documentation</a>,
but as always, starting from a blank page is a bit intimidating. So
instead of starting from a blank page, you can let <code>guix home import</code>
generate an initial config for you:</p><pre><code>guix home import ~/src/guix-config</code></pre><p>This will create the <code>~/src/guix-config</code> directory and populate it with a
bunch of files among which <code>home-configuration.scm</code> along these lines:</p><pre><code class="language-scheme">(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"))))))))</code></pre><p><code>guix home import</code> automatically added the packages of <code>~/.guix-profile</code>
to the <code>packages</code> field. Because I’m using
<a href="https://www.gnu.org/software/bash">Bash</a>, it also added an instance of
<a href="https://guix.gnu.org/manual/devel/en/html_node/Shells-Home-Services.html"><code>home-bash-service-type</code></a>
with aliases extracted from my <code>~/.bashrc</code>; it also made copies of
<code>~/.bashrc</code> and <code>~/.bash_profile</code> and refers to them.</p><p>Now that I have an initial configuration, I can first test it in an
<em>isolated container</em>:</p><pre><code>guix home container ~/src/guix-config/home-configuration.scm</code></pre><p>This command gives an interactive shell in a container where my home
environment, as declared in <code>home-configuration.scm</code>, 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 <code>~/.bashrc</code> and co., I can
check that all the packages declared are in <code>$PATH</code> and visible in
<code>~/.guix-home</code>, and so on. And all this is safe: my actual home
directory has been left unchanged!</p><p>Once satisfied with my configuration, I can instantiate it:</p><pre><code>guix home reconfigure ~/src/guix-config/home-configuration.scm</code></pre><p>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
<code>/gnu/store</code>:</p><pre><code>$ 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</code></pre><p>But don’t worry: before creating those symlinks, <code>guix home reconfigure</code>
created backups of existing files under
<code>~/TIMESTAMP-guix-home-legacy-configs-backup</code>, where <code>TIMESTAMP</code> is a
Unix-style timestamp.</p><p>And voilà, I have my first Guix Home generation!</p><pre><code>$ 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</code></pre><p><code>guix home describe</code> 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 <code>guix home reconfigure</code> relies on to make sure you never accidentally
<em>downgrade</em> you home environment to an older Guix revision.</p><h1>Going further</h1><p>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
<code>guix home</code> also takes care of installing packages. Guix Home really
shines once you use higher-level services, and when you start composing
services together.</p><p>To the example above, in the <code>services</code> field, we can add a service
declaration that runs
<a href="https://guix.gnu.org/manual/devel/en/html_node/Desktop-Home-Services.html#index-home_002dredshift_002dservice_002dtype">Redshift</a>,
a program that adjusts the display color temperature according to the
time of day:</p><pre><code class="language-scheme">(service home-redshift-service-type
(home-redshift-configuration
(location-provider 'manual)
(latitude 35.81) ;northern hemisphere
(longitude -0.80))) ;west of Greenwich</code></pre><p>The effect is that, as soon as we log in, under Xorg, Redshift will be
started in the background as a <a href="https://guix.gnu.org/manual/devel/en/html_node/Shepherd-Home-Service.html">Shepherd
service</a>.
The Home-generated <code>~/.profile</code> takes care of spawning <code>shepherd</code>, which
in turn spawns the <code>redshift</code> service:</p><pre><code>$ herd status
Started:
+ root
+ redshift</code></pre><p>We gained another thing here: a consistent, unified configuration
language. Instead of learning Redshift’s configuration file format, we
define a <code>home-redshift-configuration</code> 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 <code>guix home reconfigure</code>, and we can be sure that Redshift is passed a valid
configuration file.</p><p>We can similarly define a <a href="https://guix.gnu.org/manual/devel/en/html_node/Mcron-Home-Service.html#index-home_002dmcron_002dservice_002dtype">periodic mcron
job</a>,
for example one that updates a
<a href="https://www.gnu.org/software/idutils">GNU Idutils</a> search database
(that’s a pretty convenient and speedy way to look for code or
documents!):</p><pre><code class="language-scheme">(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"))))</code></pre><p>Again, <code>guix home</code> creates a Shepherd service that start mcron with a
configuration file containing definitions for periodic jobs, which we
can inspect <em>via</em> <code>herd</code>:</p><pre><code>$ 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</code></pre><h1>Services, composed</h1><p>If you already use Guix System, all the above certainly looks familiar:
Guix Home builds upon the <a href="https://guix.gnu.org/manual/devel/en/html_node/Defining-Services.html">service
framework</a>
that powers Guix System; Home services are defined in the <a href="https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/home/services"><code>(gnu home services …)</code> module
tree</a>.</p><p>That framework lets us define relations among
“services”, in a broad sense, and how services <em>extend</em> each other—in
the example above, <code>redshift</code> and <code>mcron</code> both extend <code>shepherd</code> by
giving it a daemon to take care of. We can see those relations at play
by running:</p><pre><code>guix home extension-graph home-configuration.scm</code></pre><p>… which, for the configuration described above, gives a graph that looks
like this:</p><p><img src="/static/blog/img/home-extension-graph.svg" alt="Extension graph for home services." /></p><p>We see <code>redshift</code>, <code>mcron</code>, and <code>shepherd</code>, but we also see lower-level
services that <code>guix home</code> instantiates for us, such as the <code>profile</code>
service which takes care of deploying packages listed in the <code>packages</code>
field under <code>~/.guix-home/profile</code>. Each arrow denotes a <em>service
extension</em>. You can <a href="https://guix.gnu.org/manual/devel/en/html_node/Service-Composition.html">read
more</a>
(and <a href="https://archive.fosdem.org/2017/schedule/event/composingsystemservicesinguixsd/">view
more!</a>)
about service composition. To satisfy our math and
functional-programming geek audience, we should mention that service
types and their extension operation form a
<a href="https://en.wikipedia.org/wiki/Monoid">monoid</a>.</p><h1>What’s next?</h1><p>Let’s be clear: Guix Home is pretty new and chances are that <code>guix home search</code>—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
Home—<a href="https://guix.gnu.org/manual/devel/en/html_node/Networking-Services.html#index-syncthing_002dservice_002dtype">Syncthing</a>,
for example.</p><p>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
<a href="https://guix.gnu.org/manual/devel/en/html_node/Contributing.html">contributing</a>.</p><p>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!</p><h4>About GNU Guix</h4><p><a href="https://guix.gnu.org">GNU Guix</a> is a transactional package manager and
an advanced distribution of the GNU system that <a href="https://www.gnu.org/distros/free-system-distribution-guidelines.html">respects user
freedom</a>.
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.</p><p>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 <a href="https://www.gnu.org/software/guile">Guile</a>
programming interfaces and extensions to the
<a href="http://schemers.org">Scheme</a> language.</p>