~ruther/guix-local

d12c4452a49b355369636de1dfc766b5bad6437b — Ludovic Courtès 5 months ago 5b218cd
shell, inferior: Store GC roots under /var/guix/profiles.

Fixes guix/guix#2410.

Until now, ‘guix shell’ and ‘guix time-machine’ would store GC roots under
~/.cache/guix.  However, this directory is unreadable to guix-daemon when it’s
running without root privileges.  This commit changes ‘guix shell’ and ‘guix
time-machine’ so they store GC roots under /var/guix/profiles/per-user/$USER,
in a world-readable directory.

An added benefit is that, in cluster setups, user homes no longer need to be
mounted on the head node for GC to work (assuming ‘guix build -r’ and similar
are not used).

* guix/inferior.scm (%inferior-cache-directory): Change default value to be
under ‘%profile-directory’.
(%legacy-inferior-cache-directory): New variable.
(cached-channel-instance): Add ‘maybe-remove-expired-cache-entries’ call.
* guix/scripts/environment.scm (launch-environment/container)[nesting-mappings]:
Add /inferiors and /profiles sub-directories of ‘%profile-directory’.  Call
‘mkdir-p’ for these two directories.
* guix/scripts/shell.scm (%profile-cache-directory): Change default value to
be under ‘%profile-directory’.
(%legacy-cache-directory): New variable.
(guix-shell): Add call to ‘maybe-remove-expired-cache-entries’.

Change-Id: Ie7d6c16a55b35c7beb18078c967d6fc902bf68d0
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
3 files changed, 45 insertions(+), 10 deletions(-)

M guix/inferior.scm
M guix/scripts/environment.scm
M guix/scripts/shell.scm
M guix/inferior.scm => guix/inferior.scm +16 -4
@@ 1,5 1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2018-2024 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2018-2025 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 860,9 860,13 @@ failing when GUIX is too old and lacks the 'guix repl' command."
;;;

(define %inferior-cache-directory
  ;; Directory for cached inferiors (GC roots).
  (make-parameter (string-append (cache-directory #:ensure? #f)
                                 "/inferiors")))
  ;; Directory for cached inferiors (GC roots).  It must be world-readable so
  ;; the daemon can traverse it.
  (make-parameter (string-append %profile-directory "/inferiors")))

(define %legacy-inferior-cache-directory
  ;; Former directory for cached inferiors, by default under $HOME/.cache.
  (string-append (cache-directory #:ensure? #f) "/inferiors"))

(define* (channel-full-commit channel #:key (verify-certificate? #t))
  "Return the commit designated by CHANNEL as quickly as possible.  If


@@ 950,6 954,14 @@ X.509 host certificate; otherwise, warn about the problem and keep going."
                                      #:entry-expiration
                                      (file-expiration-time ttl))

  ;; Clean the legacy cache directory as well.  Remove this call once at least
  ;; one year has passed.
  (maybe-remove-expired-cache-entries %legacy-inferior-cache-directory
                                      cache-entries
                                      #:entry-expiration
                                      (file-expiration-time ttl))


  (if (file-exists? cached)
      cached
      (run-with-store store

M guix/scripts/environment.scm => guix/scripts/environment.scm +14 -1
@@ 793,11 793,24 @@ WHILE-LIST."

  (define (nesting-mappings)
    ;; Files shared with the host when enabling nesting.

    ;; Make sure these two directories exist so they can be shared.
    (mkdir-p (string-append %profile-directory "/profiles"))
    (mkdir-p (string-append %profile-directory "/inferiors"))

    (cons* (file-system-mapping
            (source (%store-prefix))
            (target source))
           (file-system-mapping
            (source (cache-directory))
            (source (cache-directory))           ;~/.cache/guix/checkouts etc.
            (target source)
            (writable? #t))
           (file-system-mapping                  ;'guix shell' cached GC roots
            (source (string-append %profile-directory "/profiles"))
            (target source)
            (writable? #t))
           (file-system-mapping           ;'guix time-machine' cached GC roots
            (source (string-append %profile-directory "/inferiors"))
            (target source)
            (writable? #t))
           (let ((uri (string->uri (%daemon-socket-uri))))

M guix/scripts/shell.scm => guix/scripts/shell.scm +15 -5
@@ 1,5 1,5 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2021-2024 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2021-2025 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2023 Janneke Nieuwenhuizen <janneke@gnu.org>
;;;
;;; This file is part of GNU Guix.


@@ 327,10 327,13 @@ echo ~a >> ~a
;;;

(define %profile-cache-directory
  ;; Directory where profiles created by 'guix shell' alone (without extra
  ;; options) are cached.
  (make-parameter (string-append (cache-directory #:ensure? #f)
                                 "/profiles")))
  ;; Directory where profiles (GC roots) created by 'guix shell' are cached.
  ;; It must be world-readable so the daemon can traverse it.
  (make-parameter (string-append %profile-directory "/profiles")))

(define %legacy-cache-directory
  ;; Former cache directory, by default under $HOME/.cache.
  (string-append (cache-directory #:ensure? #f) "/profiles"))

(define (profile-cache-primary-key)
  "Return the \"primary key\" used when computing keys for the profile cache.


@@ 592,6 595,13 @@ to make sure your shell does not clobber environment variables."))) )
                 (maybe-remove-expired-cache-entries
                  (%profile-cache-directory)
                  cache-entries
                  #:entry-expiration entry-expiration)

                 ;; Clean the legacy cache directory as well.  Remove this
                 ;; call once at least one year has passed.
                 (maybe-remove-expired-cache-entries
                  %legacy-cache-directory
                  cache-entries
                  #:entry-expiration entry-expiration)))

    (if (assoc-ref opts 'export-manifest?)