From 9b0ac8025860ac426cb1bc7fd417a27fe2bed36a Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Sun, 8 Dec 2013 21:22:22 +0100 Subject: gnu: Populate /etc upon startup. * gnu/packages/patches/dmd-getpw.patch: New file. * gnu-system.am (dist_patch_DATA): Add it. * gnu/packages/system.scm (dmd): Use it. * gnu/system/vm.scm (system-qemu-image): Don't explicitly populate /etc; don't add ETC to the GC roots. * gnu/system/dmd.scm (dmd-configuration-file): Add 'etc' parameter. [config]: Populate /etc from there. --- gnu/packages/patches/dmd-getpw.patch | 19 +++++++++++++++++++ gnu/packages/system.scm | 3 ++- gnu/system/dmd.scm | 30 ++++++++++++++++++++++++++++-- gnu/system/vm.scm | 14 +------------- 4 files changed, 50 insertions(+), 16 deletions(-) create mode 100644 gnu/packages/patches/dmd-getpw.patch (limited to 'gnu') 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 @@ (define-public dmd 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 @@ (define* (static-networking-service interface ip '()))))))) -(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 (($ documentation provision requirement @@ -282,6 +285,29 @@ (define config #: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 @@ (define (system-qemu-image) (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 @@ (define (system-qemu-image) #: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" -- cgit v1.2.3