[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Should I upgrade root user's guix too?

From: Chris Marusich
Subject: Re: Should I upgrade root user's guix too?
Date: Mon, 25 Sep 2017 14:12:11 -0700
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.3 (gnu/linux)

Quiliro Ordonez Baca <address@hidden> writes:

> Very nice thread: very descriptive and enlighting. Thank you.
> I have just one question: In GuixSD, the root user needs updating for the
> Guix-daemon to update as you say is needed on a foreign distro?

Basically, yes, on a foreign distro, the reason you should run "guix
pull" and "guix package -u ." as root is to ensure that guix-daemon is
up-to-date.  This assumes that the "guix" package (which provides the
guix-daemon executable) is installed in the root user's profile, and
that you have configured your system so that at boot, it automatically
starts the guix-daemon that is installed in root's profile (info '(guix)
Binary Installation').

The truth is, it's a little complicated.  With the current
implementation, the behavior can be influenced through environment
variables, so the exact answer to the question of "What should I do?"
depends on how your system is configured and on how you invoke the
"guix" program.I've just spent some time refreshing myself on how this
works, so I'll take a few minutes to try to clarify the behavior.

Let's take a look at the "guix" launcher script to see what happens when
we invoke a command like "guix package -i" or "guix pull".  If you look
at the guix launcher script [1], you'll find that it invokes the
following procedure:

  (define (maybe-augment-load-paths!)
      (unless (getenv "GUIX_UNINSTALLED")
        (let ((module-dir (config-lookup "guilemoduledir"))
              (object-dir (config-lookup "guileobjectdir")))
          (push! module-dir %load-path)
          (push! object-dir %load-compiled-path))
        (let ((updates-dir (and=> (or (getenv "XDG_CONFIG_HOME")
                                      (and=> (getenv "HOME")
                                             (cut string-append <> "/.config")))
                                  (cut string-append <> "/guix/latest"))))
          (when (and updates-dir (file-exists? updates-dir))
            ;; XXX: Currently 'guix pull' puts both .scm and .go files in
            ;; UPDATES-DIR.
            (push! updates-dir %load-path)
            (push! updates-dir %load-compiled-path)))))

This procedure modifies the Guile load paths (info '(guile) Load
Paths'), which is the mechanism by which Guile finds modules to use.
Specifically, if XDG_CONFIG_HOME is set, the procedure adds
$XDG_CONFIG_HOME/guix/latest to the front of the load paths; if
XDG_CONFIG_HOME is not set, but HOME is set, then the procedure adds
$HOME/.config/guix/latest to the front of the load paths; if neither
XDG_CONFIG_HOME nor HOME are set (or if one of them was set, but it
points to a non-existent file), then the procedure takes no action.

After the launcher script (maybe) augments the load paths, it invokes
the following procedure:

  (define (run-guix-main)
    (let ((guix-main (module-ref (resolve-interface '(guix ui))
      (bindtextdomain "guix" (config-lookup "localedir"))
      (bindtextdomain "guix-packages" (config-lookup "localedir"))
      (apply guix-main (command-line))))

Note that it uses the procedure resolve-interface to find the module
named (guix ui).  Because the program previously added a directory such
as $HOME/.config/guix/latest to front of the load paths, that is where
Guile will find the (guix ui) module [2].  Within (guix ui), we use
similar tricks to run the requested command.

What is the point of doing it this way?  Well, consider what happens
when a user alice runs "guix package -i hello".  In a normal setup, the
"guix" command that alice invokes does not reside in Alice's profile; it
resides elsewhere (run "which guix" to see where!).  On GuixSD, this is
normally /run/current-system/profile/bin/guix, and on a foreign distro,
this might be /usr/local/bin/guix (a symlink to
/var/guix/profiles/per-user/root/guix-profile/bin/guix).  As described
above, this "guix" command is a very thin shim; its sole purpose is to
find the (guix ui) module and run the guix-main procedure defined there.

Let's assume that alice runs "guix package -i hello" in an environment
in which XDG_CONFIG_HOME is unset, but HOME is set to /home/alice.  This
is a common configuration, and it's the one I have on both my GuixSD
system and on my Ubuntu system.  Now, when alice runs "guix package -i
hello" in this environment, the "guix" executable will wind up finding
(guix ui) under /home/alice/.config/guix/latest.  Because the "guix"
executable is simply a thin shim as described above, it will find (guix
ui) in that location regardless of where the "guix" executable happens
to reside.  Likewise, the guix-main procedure defined in (guix ui) will
search for the (guix scripts package) module, it will also find it under
/home/alice/.config/guix/latest, and it will delegate control to the
guix-package procedure defined there [3].

As a result, even though alice's invocation of "guix package -i hello"
might start by invoking a "guix" launcher script that resides outside of
her home directory (e.g., at /usr/local/bin/guix), all of the code which
defines the business logic of the "guix package" command will come from
/home/alice/.config/guix/latest.  When I say "all of the code which
defines the business logic of the "guix package" command, I mean
everything in (guix ui), (guix scripts package), all of the package
definitions in modules with names like (gnu packages *), and all of the
supporting Guix code that these Guile modules might use (e.g., (guix
monads)).  If a different user bob runs the same "guix package -i hello"
command using the same "guix" executable as alice, then (assuming that
in bob's environment, XDG_CONFIG_HOME is unset, and HOME is set to
/home/bob) all the code which defines the business logic will come from
/home/bob/.config/guix/latest.  In this way, alice and bob have two
independent installations of Guix, including the package definitions.
When alice runs "guix package -i hello", she'll use her package
definition for GNU Hello, and when bob runs it, he'll use his.

"guix pull" is just another example of this.  When alice runs "guix
pull," it will ultimately run code from the (guix scripts pull) module
defined in /home/alice/.config/guix/latest/guix/scripts/pull.scm.  The
code for (guix scripts pull) is currently designed to deploy the latest
version of Guix (which contains all the modules, including the various
scripts and the package definitions) to /home/alice/.config/guix/latest.
It does this by downloading a more recent version, compiling it, and
then flipping the /home/alice/.config/guix/latest symlink to point to
the newly built version.  Once this is complete, every command that
alice runs, like "guix package -i hello", will use the new code (and new
package definitions) that have been installed to
/home/alice/.config/guix/latest.  However, if bob runs the same command,
he will continue to use whatever version of the code (and package
definitions) that he was using before; it will not change for bob until
bob runs "guix pull" himself.  The root user is no different.  Assuming
a normal setup, the root user has a deployment of Guix under
/root/.config/guix/latest, which can only be updated by running "guix
pull" as root.

Because the delegation mechanism described above relies on indirection
via environment variables, it's possible that if you configure your
system differently, things might behave differently.  For example, on my
Ubuntu machine, by default sudo is configured so that it will not change
the HOME environment variable.  As a result, if a user named alice runs
"sudo guix pull" on my Ubuntu machine, it will cause
/home/alice/.config/guix/latest to become a symlink owned by root, which
is not what I intended.  For this reason, on my Ubuntu machine I always
run "sudo -H guix pull" instead of "sudo guix pull" when I want to
update root's Guix installation (this causes sudo to set the HOME
environment variable to /root; see 'man 8 sudo' for details).  On
GuixSD, this same problem does not occur (because sudo is already
configured to set HOME to /root).  In any case, you should test on your
own system and figure out what environment variables are set in various
situations.  You can find out easily by running commands like "env" and
"sudo env".

On GuixSD, the guix-daemon is usually deployed at the system level (the
guix-service-type implicitly installs the guix package to the system
profile [4]).  Therefore, on GuixSD, you upgrade the guix-daemon like
you would upgrade any other part of the overall system: by running "guix
system reconfigure" as root.  On a foreign distro, the guix-daemon is
usually deployed in root's profile.  Therefore, on a foreign distro, you
upgrade the guix-daemon like you would upgrade any other package in
root's profile: by running "guix package -u ." as root.  Regardless of
whether you use GuixSD or a foreign distro, when you run a "guix"
command as root, it will usually use whatever script implementations and
package definitions are present in root's deployment of Guix, so before
you run those commands as root, you should first run "guix pull" as root
to ensure that you're using the latest and greatest.

Note that in the future, the behavior of "guix pull" is likely to change
[5].  I hope my attempt to explain things has helped to clarify how it
works today and how it enables multiple users to have independent
installations of Guix (including package definitions).  I hope it helps
you understand when you should run what commands.  If anything is
unclear, just remember that you can always look into the source code
(it's free software, after all!), and the people on the email list or
IRC are usually very helpful.







Attachment: signature.asc
Description: PGP signature

reply via email to

[Prev in Thread] Current Thread [Next in Thread]