Subject: bug#39925: `guix pull` failure in multi-machine setup

From: Ludovic Courtès <[email-masked]>
Date: Thu, 05 Mar 2020 18:20:58 +0100

Hi,

Lars-Dominik Braun <[email-masked]> skribis:

> I’m using guix on a multi-machine setup with a single remote guix-daemon that
> can be reached via SSH. Thus GUIX_DAEMON_SOCKET=ssh://master.<domain> on the
> compute nodes. Running `guix pull` on master works fine (the variable is not
> set here), but it does not on a compute node. Instead it fails with this error:
>
> ---snip---
> Backtrace:
>            1 (primitive-load "/gnu/store/n5wgvz287dwm62474mr42x34wl5j5wh7-compute-guix-derivation")
> In ice-9/eval.scm:
>    293:34  0 (_ #(#(#(#(#(#(#(#(#(#(#(#(#<directory (guile-user) 7f19dd213140> (?)) #) # ?) ?) ?) ?) ?) ?) ?) ?) ?) ?))
>
> ice-9/eval.scm:293:34: Throw to key `srfi-34' with args `(#<condition &store-connection-error [file: "/var/guix/daemon-socket/socket" errno: 111] 7f19dba3a090>)'.
> guix pull: error: You found a bug: the program '/gnu/store/n5wgvz287dwm62474mr42x34wl5j5wh7-compute-guix-derivation'
> failed to compute the derivation for Guix (version: "aac148a87b9a79b9992b8b1a9d76c217175d4a88"; system: "x86_64-linux";
> host version: "aac148a87b9a79b9992b8b1a9d76c217175d4a88"; pull-version: 1).
> Please report it by email to <[email-masked]>.
> ---snap---
>
> Obviously the socket on that compute machine is not working, because it’s on an
> NFS share /var/guix belonging to master. But why is the socket considered in
> the first place?

This is a limitation in ‘build-aux/build-self.scm’:

      ;; Use the port beneath the current store as the stdin of BUILD.  This
      ;; way, we know 'open-pipe*' will not close it on 'exec'.  If PORT is
      ;; not a file port (e.g., it's an SSH channel), then the subprocess's
      ;; stdin will actually be /dev/null.
      (let* ((pipe   (with-input-from-port port
                       (lambda ()
                          ;; …
                                      (if (file-port? port)  ;<- here
                                          (number->string
                                           (logior major minor))
                                          "none"))))))

We could work around it by letting the ‘GUIX_DAEMON_SOCKET’ environment
variable through, along these lines:

diff --git a/build-aux/build-self.scm b/build-aux/build-self.scm
index f2e785b7f1..18a78b5f41 100644
--- a/build-aux/build-self.scm
+++ b/build-aux/build-self.scm
@@ -400,6 +400,7 @@ files."
                                              #:pull-version pull-version))
                       (system (if system (return system) (current-system)))
                       (home -> (getenv "HOME"))
+                      (daemon-socket -> (getenv "GUIX_DAEMON_SOCKET"))
 
                       ;; Note: Use the deprecated names here because the
                       ;; caller might be Guix <= 0.16.0.
@@ -424,6 +425,8 @@ files."
                           (when home
                             ;; Inherit HOME so that 'xdg-directory' works.
                             (setenv "HOME" home))
+                          (when (and (not (file-port? port) daemon-socket))
+                            (setenv "GUIX_DAEMON_SOCKET" daemon-socket))
                           (open-pipe* OPEN_READ
                                       (derivation->output-path build)
                                       source system version

It’s a bit hacky though, and won’t work with old Guix revisions anyway.

However, for your use case, you could perhaps simply pull on one machine
and use ‘guix copy’ to send Guix elsewhere?  Or even explicitly run
‘guix pull’ on each node?

Thanks,
Ludo’.