Subject: [bug#77638] [PATCH 7/8] linux-container: Set up “lo” and generate /etc/hosts by default.

From: Ludovic Courtès <[email-masked]>
Date: Tue, 8 Apr 2025 14:24:47 +0200

* gnu/build/linux-container.scm (run-container): Add #:loopback-network?
and honor it via #:populate-file-system.
(call-with-container): Add #:loopback-network? and pass it to
‘run-container’.
* guix/scripts/environment.scm (launch-environment/container): Remove
call to ‘set-network-interface-up’ and remove generation of /etc/hosts.
* guix/scripts/home.scm (spawn-home-container): Likewise.

Change-Id: I5933a4e8dc6d8e19235a79696b62299d74d1ba21
---
 gnu/build/linux-container.scm | 25 ++++++++++++++++++++++++-
 guix/scripts/environment.scm  | 11 -----------
 guix/scripts/home.scm         | 15 ++-------------
 3 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/gnu/build/linux-container.scm b/gnu/build/linux-container.scm
index 4dcdaa8f33..345ce2de08 100644
--- a/gnu/build/linux-container.scm
+++ b/gnu/build/linux-container.scm
@@ -237,6 +237,7 @@ (define (namespaces->bit-mask namespaces)
 (define* (run-container root mounts namespaces host-uids thunk
                         #:key (guest-uid 0) (guest-gid 0)
                         (populate-file-system (const #t))
+                        (loopback-network? #t)
                         writable-root?)
   "Run THUNK in a new container process and return its PID.  ROOT specifies
 the root directory for the container.  MOUNTS is a list of <file-system>
@@ -244,6 +245,9 @@ (define* (run-container root mounts namespaces host-uids thunk
 is a list of symbols that correspond to the possible Linux namespaces: mnt,
 ipc, uts, user, and net.
 
+When LOOPBACK-NETWORK? is true and 'net is amount NAMESPACES, set up the
+loopback device (\"lo\") and a minimal /etc/hosts.
+
 When WRITABLE-ROOT? is false, remount the container's root as read-only before
 calling THUNK.  Call POPULATE-FILE-SYSTEM before the root is (potentially)
 made read-only.
@@ -275,7 +279,21 @@ (define* (run-container root mounts namespaces host-uids thunk
                                           #:mount-/sys?  (memq 'net
                                                                namespaces)
                                           #:populate-file-system
-                                          populate-file-system
+                                          (lambda ()
+                                            (populate-file-system)
+                                            (when (and (memq 'net namespaces)
+                                                       loopback-network?)
+                                              (set-network-interface-up "lo")
+
+                                              ;; When isolated from the
+                                              ;; network, provide a minimal
+                                              ;; /etc/hosts to resolve
+                                              ;; "localhost".
+                                              (mkdir-p "/etc")
+                                              (call-with-output-file "/etc/hosts"
+                                                (lambda (port)
+                                                  (display "127.0.0.1 localhost\n" port)
+                                                  (chmod port #o444)))))
                                           #:writable-root?
                                           (or writable-root?
                                               (not (memq 'mnt namespaces)))))
@@ -350,6 +368,7 @@ (define* (call-with-container mounts thunk #:key (namespaces %namespaces)
                               (relayed-signals (list SIGINT SIGTERM))
                               (child-is-pid1? #t)
                               (populate-file-system (const #t))
+                              (loopback-network? #t)
                               writable-root?
                               (process-spawned-hook (const #t)))
   "Run THUNK in a new container process and return its exit status; call
@@ -371,6 +390,9 @@ (define* (call-with-container mounts thunk #:key (namespaces %namespaces)
 RELAYED-SIGNALS is the list of signals that are \"relayed\" to the container
 process when caught by its parent.
 
+When LOOPBACK-NETWORK? is true and 'net is amount NAMESPACES, set up the
+loopback device (\"lo\") and a minimal /etc/hosts.
+
 When WRITABLE-ROOT? is false, remount the container's root as read-only before
 calling THUNK.  Call POPULATE-FILE-SYSTEM before the root is (potentially)
 made read-only.
@@ -430,6 +452,7 @@ (define* (call-with-container mounts thunk #:key (namespaces %namespaces)
                                #:guest-uid guest-uid
                                #:guest-gid guest-gid
                                #:populate-file-system populate-file-system
+                               #:loopback-network? loopback-network?
                                #:writable-root? writable-root?)))
        (install-signal-handlers pid)
        (process-spawned-hook pid)
diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm
index 8f3bea8c30..ddd34394dd 100644
--- a/guix/scripts/environment.scm
+++ b/guix/scripts/environment.scm
@@ -901,10 +901,6 @@ (define* (launch-environment/container #:key command bash user user-mappings
 
             (setenv "HOME" home-dir)
 
-            (unless network?
-              ;; Allow local AF_INET communications.
-              (set-network-interface-up "lo"))
-
             ;; For convenience, start in the user's current working
             ;; directory or, if unmapped, the home directory.
             (chdir (if map-cwd?
@@ -959,13 +955,6 @@ (define* (launch-environment/container #:key command bash user user-mappings
             (write-passwd (list passwd))
             (write-group groups)
 
-            (unless network?
-              ;; When isolated from the network, provide a minimal /etc/hosts
-              ;; to resolve "localhost".
-              (call-with-output-file "/etc/hosts"
-                (lambda (port)
-                  (display "127.0.0.1 localhost\n" port))))
-
             ;; Call an additional setup procedure, if provided.
             (when setup-hook
               (setup-hook profile)))
diff --git a/guix/scripts/home.scm b/guix/scripts/home.scm
index 6fcb0ca382..fbf6d670ac 100644
--- a/guix/scripts/home.scm
+++ b/guix/scripts/home.scm
@@ -288,14 +288,11 @@ (define* (spawn-home-container home
      (with-imported-modules `(((guix config) => ,(make-config.scm))
                               ,@(source-module-closure
                                  '((guix profiles)
-                                   (guix build utils)
-                                   (guix build syscalls))
+                                   (guix build utils))
                                  #:select? not-config?))
        #~(begin
            (use-modules (guix build utils)
-                        ((guix profiles) #:select (load-profile))
-                        ((guix build syscalls)
-                         #:select (set-network-interface-up)))
+                        ((guix profiles) #:select (load-profile)))
 
            (define shell
              #$(user-shell))
@@ -347,14 +344,6 @@ (define* (spawn-home-container home
      (write-passwd (list passwd))
      (write-group groups)
 
-     (unless network?
-       ;; When isolated from the network, provide a minimal /etc/hosts
-       ;; to resolve "localhost".
-       (call-with-output-file "/etc/hosts"
-         (lambda (port)
-           (display "127.0.0.1 localhost\n" port)
-           (chmod port #o444))))
-
      ;; Create /tmp; bits of code expect it, such as
      ;; 'least-authority-wrapper'.
      (mkdir-p "/tmp"))
-- 
2.49.0