summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gnu-system.am1
-rw-r--r--gnu/packages/patches/dmd-getpw.patch19
-rw-r--r--gnu/packages/system.scm3
-rw-r--r--gnu/system/dmd.scm30
-rw-r--r--gnu/system/vm.scm14
5 files changed, 51 insertions, 16 deletions
diff --git a/gnu-system.am b/gnu-system.am
index 8fba97db0f..5a51fde498 100644
--- a/gnu-system.am
+++ b/gnu-system.am
@@ -227,6 +227,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/cpio-gets-undeclared.patch		\
   gnu/packages/patches/dbus-localstatedir.patch			\
   gnu/packages/patches/diffutils-gets-undeclared.patch		\
+  gnu/packages/patches/dmd-getpw.patch				\
   gnu/packages/patches/emacs-configure-sh.patch			\
   gnu/packages/patches/ffmpeg-check.patch			\
   gnu/packages/patches/findutils-absolute-paths.patch		\
diff --git a/gnu/packages/patches/dmd-getpw.patch b/gnu/packages/patches/dmd-getpw.patch
new file mode 100644
index 0000000000..c4f9c35951
--- /dev/null
+++ b/gnu/packages/patches/dmd-getpw.patch
@@ -0,0 +1,19 @@
+When bootstrapping and running as PID 1, /etc/{passwd,shadow} may be unavailable.
+Gracefully handle that.
+
+diff --git a/modules/dmd/support.scm b/modules/dmd/support.scm
+index 9b592c5..602e409 100644
+--- a/modules/dmd/support.scm
++++ b/modules/dmd/support.scm
+@@ -151,7 +151,10 @@ There is NO WARRANTY, to the extent permitted by law.")))
+ 
+ 
+ ;; Home directory of the user.
+-(define user-homedir (passwd:dir (getpwuid (getuid))))
++(define user-homedir
++  (or (false-if-exception (passwd:dir (getpwuid (getuid))))
++      (getenv "HOME")
++      "/"))
+ 
+ ;; Logfile.
+ (define default-logfile
diff --git a/gnu/packages/system.scm b/gnu/packages/system.scm
index f92d874099..536234f4aa 100644
--- a/gnu/packages/system.scm
+++ b/gnu/packages/system.scm
@@ -45,7 +45,8 @@
                                  version ".tar.gz"))
              (sha256
               (base32
-               "07mddw0p62fcphwjzgb6rfa0pjz5sy6jzbha0sm2vc3rqf459jxg"))))
+               "07mddw0p62fcphwjzgb6rfa0pjz5sy6jzbha0sm2vc3rqf459jxg"))
+             (patches (list (search-patch "dmd-getpw.patch")))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags '("--localstatedir=/var")))
diff --git a/gnu/system/dmd.scm b/gnu/system/dmd.scm
index df38172def..aec7d03759 100644
--- a/gnu/system/dmd.scm
+++ b/gnu/system/dmd.scm
@@ -266,10 +266,13 @@ true, it must be a string specifying the default network gateway."
                       '())))))))
 
 
-(define (dmd-configuration-file services)
-  "Return the dmd configuration file for SERVICES."
+(define (dmd-configuration-file services etc)
+  "Return the dmd configuration file for SERVICES, that initializes /etc from
+ETC on startup."
   (define config
     `(begin
+       (use-modules (ice-9 ftw))
+
        (register-services
         ,@(map (match-lambda
                 (($ <service> documentation provision requirement
@@ -282,6 +285,29 @@ true, it must be a string specifying the default network gateway."
                     #:start ,start
                     #:stop ,stop)))
                services))
+
+       ;; /etc is a mixture of static and dynamic settings.  Here is where we
+       ;; initialize it from the static part.
+       (format #t "populating /etc from ~a...~%" ,etc)
+       (let ((rm-f (lambda (f)
+                     (false-if-exception (delete-file f)))))
+         (rm-f "/etc/static")
+         (symlink ,etc "/etc/static")
+         (for-each (lambda (file)
+                     ;; TODO: Handle 'shadow' specially so that changed
+                     ;; password aren't lost.
+                     (let ((target (string-append "/etc/" file))
+                           (source (string-append "/etc/static/" file)))
+                       (rm-f target)
+                       (symlink source target)))
+                   (scandir ,etc
+                            (lambda (file)
+                              (not (member file '("." ".."))))))
+
+         ;; Prevent ETC from being GC'd.
+         (symlink ,etc "/var/nix/gcroots/etc-directory"))
+
+       (format #t "starting services...~%")
        (for-each start ',(append-map service-provision services))))
 
   (text-file "dmd.conf" (object->string config)))
diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm
index ffbc07ee85..7afbd70044 100644
--- a/gnu/system/vm.scm
+++ b/gnu/system/vm.scm
@@ -577,7 +577,6 @@ Happy birthday, GNU!                                http://www.gnu.org/gnu30
 
        (bash-file (package-file bash "bin/bash"))
        (dmd-file  (package-file dmd "bin/dmd"))
-       (dmd-conf  (dmd-configuration-file services))
        (accounts -> (cons* (user-account
                             (name "root")
                             (password "")
@@ -632,26 +631,15 @@ Happy birthday, GNU!                                http://www.gnu.org/gnu30
                                    #:pam-services pam-services
                                    #:profile profile))
        (etc     ->  (derivation->output-path etc-drv))
+       (dmd-conf  (dmd-configuration-file services etc))
 
 
        (populate -> `((directory "/nix/store" 0 ,build-user-gid)
                       (directory "/etc")
                       (directory "/var/log")      ; for dmd
                       (directory "/var/run/nscd")
-                      ("/etc/static" -> ,etc)
-                      ("/etc/shadow" -> "/etc/static/shadow")
-                      ("/etc/passwd" -> "/etc/static/passwd")
-                      ("/etc/group" -> "/etc/static/group")
-                      ("/etc/login.defs" -> "/etc/static/login.defs")
-                      ("/etc/pam.d" -> "/etc/static/pam.d")
-                      ("/etc/profile" -> "/etc/static/profile")
-                      ("/etc/issue" -> "/etc/static/issue")
-                      ("/etc/services" -> "/etc/static/services")
-                      ("/etc/protocols" -> "/etc/static/protocols")
-                      ("/etc/rpc" -> "/etc/static/rpc")
                       (directory "/var/nix/gcroots")
                       ("/var/nix/gcroots/default-profile" -> ,profile)
-                      ("/var/nix/gcroots/etc-directory" -> ,etc)
                       (directory "/tmp")
                       (directory "/var/nix/profiles/per-user/root" 0 0)
                       (directory "/var/nix/profiles/per-user/guest"