doc: Mention 'guix lint' and '--list-dependent' in 'HACKING'.
[jackhill/guix/guix.git] / gnu / system.scm
index 48946af..2469ade 100644 (file)
   #:use-module (guix records)
   #:use-module (guix packages)
   #:use-module (guix derivations)
+  #:use-module (guix profiles)
   #:use-module (gnu packages base)
   #:use-module (gnu packages bash)
+  #:use-module (gnu packages guile)
+  #:use-module (gnu packages which)
   #:use-module (gnu packages admin)
   #:use-module (gnu packages linux)
   #:use-module (gnu packages package-management)
+  #:use-module (gnu packages which)
+  #:use-module (gnu packages less)
+  #:use-module (gnu packages zile)
+  #:use-module (gnu packages nano)
+  #:use-module (gnu packages lsof)
   #:use-module (gnu services)
   #:use-module (gnu services dmd)
   #:use-module (gnu services base)
             operating-system-initrd
             operating-system-users
             operating-system-groups
+            operating-system-issue
             operating-system-packages
             operating-system-timezone
             operating-system-locale
             operating-system-file-systems
+            operating-system-activation-script
 
             operating-system-derivation
             operating-system-profile
-            operating-system-grub.cfg))
+            operating-system-grub.cfg
+
+            %base-packages))
 
 ;;; Commentary:
 ;;;
   (bootloader operating-system-bootloader)        ; <grub-configuration>
 
   (initrd operating-system-initrd                 ; (list fs) -> M derivation
-          (default qemu-initrd))
+          (default base-initrd))
 
   (host-name operating-system-host-name)          ; string
 
-  (file-systems operating-system-file-systems     ; list of fs
-                (default '()))
+  (file-systems operating-system-file-systems)    ; list of fs
 
   (users operating-system-users                   ; list of user accounts
          (default '()))
   (groups operating-system-groups                 ; list of user groups
-          (default (list (user-group
-                          (name "root")
-                          (id 0)))))
+          (default %base-groups))
 
   (skeletons operating-system-skeletons           ; list of name/monadic value
              (default (default-skeletons)))
+  (issue operating-system-issue                   ; string
+         (default %default-issue))
 
   (packages operating-system-packages             ; list of (PACKAGE OUTPUT...)
-            (default (list coreutils              ; or just PACKAGE
-                           grep
-                           sed
-                           findutils
-                           guile
-                           bash
-                           (@ (gnu packages dmd) dmd)
-                           guix
-                           tzdata)))
+            (default %base-packages))             ; or just PACKAGE
 
   (timezone operating-system-timezone)            ; string
-  (locale   operating-system-locale)              ; string
+  (locale   operating-system-locale               ; string
+            (default "en_US.UTF-8"))
 
   (services operating-system-user-services        ; list of monadic services
             (default %base-services))
 ;;; Derivation.
 ;;;
 
-(define* (union inputs
-                #:key (guile (%guile-for-build)) (system (%current-system))
-                (name "union"))
-  "Return a derivation that builds the union of INPUTS.  INPUTS is a list of
-input tuples."
-  (define builder
-    #~(begin
-        (use-modules (guix build union))
-
-        (define inputs '#$inputs)
-
-        (setvbuf (current-output-port) _IOLBF)
-        (setvbuf (current-error-port) _IOLBF)
-
-        (format #t "building union `~a' with ~a packages...~%"
-                #$output (length inputs))
-        (union-build #$output inputs)))
-
-  (gexp->derivation name builder
-                    #:system system
-                    #:modules '((guix build union))
-                    #:guile-for-build guile
-                    #:local-build? #t))
-
 (define* (file-union name files)
   "Return a derivation that builds a directory containing all of FILES.  Each
 item in FILES must be a list where the first element is the file name to use
@@ -179,10 +159,14 @@ as 'needed-for-boot'."
 
   (sequence %store-monad
             (map (match-lambda
-                  (($ <file-system> device target type flags opts #f check?)
+                  (($ <file-system> device title target type flags opts
+                                    #f check? create?)
                    (file-system-service device target type
+                                        #:title title
                                         #:check? check?
-                                        #:options opts)))
+                                        #:create-mount-point? create?
+                                        #:options opts
+                                        #:flags flags)))
                  file-systems)))
 
 (define (essential-services os)
@@ -211,8 +195,34 @@ explicitly appear in OS."
 ;;; /etc.
 ;;;
 
+(define %base-packages
+  ;; Default set of packages globally visible.  It should include anything
+  ;; required for basic administrator tasks.
+  (cons* procps psmisc which less zile nano
+         (@ (gnu packages admin) dmd) guix
+         lsof                                 ;for Guix's 'list-runtime-roots'
+         util-linux inetutils isc-dhcp
+         net-tools                        ; XXX: remove when Inetutils suffices
+
+         ;; Get 'insmod' & co. from kmod, not module-init-tools, since udev
+         ;; already depends on it anyway.
+         kmod udev
+
+         e2fsprogs kbd
+
+         ;; The packages below are also in %FINAL-INPUTS, so take them from
+         ;; there to avoid duplication.
+         (map canonical-package
+              (list guile-2.0 bash coreutils findutils grep sed))))
+
+(define %default-issue
+  ;; Default contents for /etc/issue.
+  "
+This is the GNU system.  Welcome.\n")
+
 (define* (etc-directory #:key
                         (locale "C") (timezone "Europe/Paris")
+                        (issue "Hello!\n")
                         (skeletons '())
                         (pam-services '())
                         (profile "/run/current-system/profile")
@@ -227,15 +237,7 @@ explicitly appear in OS."
 /bin/sh
 /run/current-system/profile/bin/sh
 /run/current-system/profile/bin/bash\n"))
-       (issue      (text-file "issue" "
-This is an alpha preview of the GNU system.  Welcome.
-
-This image features the GNU Guix package manager, which was used to
-build it (http://www.gnu.org/software/guix/).  The init system is
-GNU dmd (http://www.gnu.org/software/dmd/).
-
-You can log in as 'guest' or 'root' with no password.
-"))
+       (issue      (text-file "issue" issue))
 
        ;; TODO: Generate bashrc from packages' search-paths.
        (bashrc    (text-file* "bashrc"  "
@@ -245,8 +247,11 @@ export LC_ALL=\"" locale "\"
 export TZ=\"" timezone "\"
 export TZDIR=\"" tzdata "/share/zoneinfo\"
 
-export PATH=/run/setuid-programs:/run/current-system/profile/sbin
-export PATH=$HOME/.guix-profile/bin:/run/current-system/profile/bin:$PATH
+# Tell 'modprobe' & co. where to look for modules.
+export LINUX_MODULE_DIRECTORY=/run/booted-system/kernel/lib/modules
+
+export PATH=$HOME/.guix-profile/bin:/run/current-system/profile/bin
+export PATH=/run/setuid-programs:/run/current-system/profile/sbin:$PATH
 export CPATH=$HOME/.guix-profile/include:" profile "/include
 export LIBRARY_PATH=$HOME/.guix-profile/lib:" profile "/lib
 alias ls='ls -p --color'
@@ -268,10 +273,9 @@ alias ll='ls -l'
                   ("sudoers" ,#~#$sudoers)))))
 
 (define (operating-system-profile os)
-  "Return a derivation that builds the default profile of OS."
-  ;; TODO: Replace with a real profile with a manifest.
-  (union (operating-system-packages os)
-         #:name "default-profile"))
+  "Return a derivation that builds the system profile of OS."
+  (profile-derivation (manifest (map package->manifest-entry
+                                     (operating-system-packages os)))))
 
 (define %root-account
   ;; Default root account.
@@ -309,6 +313,7 @@ alias ll='ls -l'
        (skeletons   (operating-system-skeletons os)))
    (etc-directory #:pam-services pam-services
                   #:skeletons skeletons
+                  #:issue (operating-system-issue os)
                   #:locale (operating-system-locale os)
                   #:timezone (operating-system-timezone os)
                   #:sudoers (operating-system-sudoers os)
@@ -336,7 +341,8 @@ alias ll='ls -l'
 'active-groups'."
   #~(list #$(user-group-name group)
           #$(user-group-password group)
-          #$(user-group-id group)))
+          #$(user-group-id group)
+          #$(user-group-system? group)))
 
 (define (user-account->gexp account)
   "Turn ACCOUNT, a <user-account> object, into a list-valued gexp suitable for
@@ -348,7 +354,8 @@ alias ll='ls -l'
       #$(user-account-comment account)
       #$(user-account-home-directory account)
       ,#$(user-account-shell account)             ; this one is a gexp
-      #$(user-account-password account)))
+      #$(user-account-password account)
+      #$(user-account-system? account)))
 
 (define (operating-system-activation-script os)
   "Return the activation script for OS---i.e., the code that \"activates\" the
@@ -384,7 +391,7 @@ etc."
     (define group-specs
       (map user-group->gexp groups))
 
-    (gexp->file "boot"
+    (gexp->file "activate"
                 #~(begin
                     (eval-when (expand load eval)
                       ;; Make sure 'use-modules' below succeeds.
@@ -447,7 +454,7 @@ we're running in the final root."
 (define (operating-system-root-file-system os)
   "Return the root file system of OS."
   (find (match-lambda
-         (($ <file-system> _ "/") #t)
+         (($ <file-system> _ "/") #t)
          (_ #f))
         (operating-system-file-systems os)))
 
@@ -455,9 +462,10 @@ we're running in the final root."
   "Return a gexp denoting the initrd file of OS."
   (define boot-file-systems
     (filter (match-lambda
-             (($ <file-system> device "/")
+             (($ <file-system> device title "/")
               #t)
-             (($ <file-system> device mount-point type flags options boot?)
+             (($ <file-system> device title mount-point type flags
+                               options boot?)
               boot?))
             (operating-system-file-systems os)))
 
@@ -465,17 +473,22 @@ we're running in the final root."
       ((initrd ((operating-system-initrd os) boot-file-systems)))
     (return #~(string-append #$initrd "/initrd"))))
 
-(define (operating-system-grub.cfg os)
-  "Return the GRUB configuration file for OS."
+(define (kernel->grub-label kernel)
+  "Return a label for the GRUB menu entry that boots KERNEL."
+  (string-append "GNU system with "
+                 (string-titlecase (package-name kernel)) " "
+                 (package-version kernel)
+                 " (technology preview)"))
+
+(define* (operating-system-grub.cfg os #:optional (old-entries '()))
+  "Return the GRUB configuration file for OS.  Use OLD-ENTRIES to populate the
+\"old entries\" menu."
   (mlet* %store-monad
       ((system      (operating-system-derivation os))
        (root-fs ->  (operating-system-root-file-system os))
        (kernel ->   (operating-system-kernel os))
        (entries ->  (list (menu-entry
-                           (label (string-append
-                                   "GNU system with "
-                                   (package-full-name kernel)
-                                   " (technology preview)"))
+                           (label (kernel->grub-label kernel))
                            (linux kernel)
                            (linux-arguments
                             (list (string-append "--root="
@@ -484,7 +497,22 @@ we're running in the final root."
                                   #~(string-append "--load=" #$system
                                                    "/boot")))
                            (initrd #~(string-append #$system "/initrd"))))))
-    (grub-configuration-file (operating-system-bootloader os) entries)))
+    (grub-configuration-file (operating-system-bootloader os) entries
+                             #:old-entries old-entries)))
+
+(define (operating-system-parameters-file os)
+  "Return a file that describes the boot parameters of OS.  The primary use of
+this file is the reconstruction of GRUB menu entries for old configurations."
+  (mlet %store-monad ((initrd   (operating-system-initrd-file os))
+                      (root ->  (operating-system-root-file-system os))
+                      (label -> (kernel->grub-label
+                                 (operating-system-kernel os))))
+    (gexp->file "parameters"
+                #~(boot-parameters (version 0)
+                                   (label #$label)
+                                   (root-device #$(file-system-device root))
+                                   (kernel #$(operating-system-kernel os))
+                                   (initrd #$initrd)))))
 
 (define (operating-system-derivation os)
   "Return a derivation that builds OS."
@@ -493,10 +521,12 @@ we're running in the final root."
        (etc         (operating-system-etc-directory os))
        (boot        (operating-system-boot-script os))
        (kernel  ->  (operating-system-kernel os))
-       (initrd      (operating-system-initrd-file os)))
+       (initrd      (operating-system-initrd-file os))
+       (params      (operating-system-parameters-file os)))
     (file-union "system"
                 `(("boot" ,#~#$boot)
                   ("kernel" ,#~#$kernel)
+                  ("parameters" ,#~#$params)
                   ("initrd" ,initrd)
                   ("profile" ,#~#$profile)
                   ("etc" ,#~#$etc)))))