Merge branch 'master' into core-updates
[jackhill/guix/guix.git] / gnu / system.scm
CommitLineData
033adfe7
LC
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2013 Ludovic Courtès <ludo@gnu.org>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (gnu system)
20 #:use-module (guix store)
21 #:use-module (guix monads)
22 #:use-module (guix records)
23 #:use-module (guix packages)
24 #:use-module (guix derivations)
25 #:use-module (gnu packages linux-initrd)
26 #:use-module (gnu packages base)
27 #:use-module (gnu packages bash)
9de46ffb 28 #:use-module (gnu packages admin)
033adfe7
LC
29 #:use-module (gnu packages package-management)
30 #:use-module (gnu system dmd)
31 #:use-module (gnu system grub)
32 #:use-module (gnu system shadow)
33 #:use-module (gnu system linux)
34 #:use-module (ice-9 match)
35 #:use-module (srfi srfi-1)
36 #:use-module (srfi srfi-26)
37 #:export (operating-system
38 operating-system?
39 operating-system-services
40 operating-system-packages
41
42 operating-system-derivation))
43
44;;; Commentary:
45;;;
46;;; This module supports whole-system configuration.
47;;;
48;;; Code:
49
50;; System-wide configuration.
51;; TODO: Add per-field docstrings/stexi.
52(define-record-type* <operating-system> operating-system
53 make-operating-system
54 operating-system?
55 (kernel operating-system-kernel ; package
56 (default linux-libre))
57 (bootloader operating-system-bootloader ; package
58 (default grub))
59 (bootloader-entries operating-system-bootloader-entries ; list
60 (default '()))
61 (initrd operating-system-initrd
62 (default gnu-system-initrd))
63
64 (host-name operating-system-host-name) ; string
65
66 (file-systems operating-system-file-systems ; list of fs
67 (default '()))
68
69 (users operating-system-users ; list of user accounts
70 (default '()))
71 (groups operating-system-groups ; list of user groups
72 (default (list (user-group
73 (name "root")
74 (id 0))
75 (user-group
76 (name "users")
77 (id 100)
78 (members '("guest"))))))
79
80 (packages operating-system-packages ; list of (PACKAGE OUTPUT...)
4f62d8d6
LC
81 (default (list coreutils ; or just PACKAGE
82 grep
83 sed
84 findutils
85 guile
86 bash
87 (@ (gnu packages dmd) dmd)
3141a8bd
LC
88 guix
89 tzdata)))
033adfe7
LC
90
91 (timezone operating-system-timezone) ; string
92 (locale operating-system-locale) ; string
93
94 (services operating-system-services ; list of monadic services
95 (default
96 (let ((motd (text-file "motd" "
97This is the GNU operating system, welcome!\n\n")))
98 (list (mingetty-service "tty1" #:motd motd)
99 (mingetty-service "tty2" #:motd motd)
100 (mingetty-service "tty3" #:motd motd)
101 (mingetty-service "tty4" #:motd motd)
102 (mingetty-service "tty5" #:motd motd)
103 (mingetty-service "tty6" #:motd motd)
104 (syslog-service)
105 (guix-service)
106 (nscd-service)
107
108 ;; QEMU networking settings.
109 (static-networking-service "eth0" "10.0.2.10"
110 #:name-servers '("10.0.2.3")
111 #:gateway "10.0.2.2"))))))
112
113
114\f
115;;;
116;;; Derivation.
117;;;
118
119(define* (union inputs
120 #:key (guile (%guile-for-build)) (system (%current-system))
121 (name "union"))
122 "Return a derivation that builds the union of INPUTS. INPUTS is a list of
123input tuples."
124 (define builder
125 '(begin
126 (use-modules (guix build union))
127
128 (setvbuf (current-output-port) _IOLBF)
129 (setvbuf (current-error-port) _IOLBF)
130
131 (let ((output (assoc-ref %outputs "out"))
132 (inputs (map cdr %build-inputs)))
133 (format #t "building union `~a' with ~a packages...~%"
134 output (length inputs))
135 (union-build output inputs))))
136
137 (mlet %store-monad
138 ((inputs (sequence %store-monad
139 (map (match-lambda
4f62d8d6 140 ((or ((? package? p)) (? package? p))
033adfe7
LC
141 (mlet %store-monad
142 ((drv (package->derivation p system)))
143 (return `(,name ,drv))))
4f62d8d6 144 (((? package? p) output)
033adfe7
LC
145 (mlet %store-monad
146 ((drv (package->derivation p system)))
147 (return `(,name ,drv ,output))))
148 (x
149 (return x)))
150 inputs))))
151 (derivation-expression name builder
152 #:system system
153 #:inputs inputs
154 #:modules '((guix build union))
155 #:guile-for-build guile)))
156
157(define* (file-union files
158 #:key (inputs '()) (name "file-union"))
159 "Return a derivation that builds a directory containing all of FILES. Each
160item in FILES must be a list where the first element is the file name to use
161in the new directory, and the second element is the target file.
162
163The subset of FILES corresponding to plain store files is automatically added
164as an inputs; additional inputs, such as derivations, are taken from INPUTS."
165 (mlet %store-monad ((inputs (lower-inputs inputs)))
166 (let* ((outputs (append-map (match-lambda
167 ((_ (? derivation? drv))
168 (list (derivation->output-path drv)))
169 ((_ (? derivation? drv) sub-drv ...)
170 (map (cut derivation->output-path drv <>)
171 sub-drv))
172 (_ '()))
173 inputs))
174 (inputs (append inputs
175 (filter (match-lambda
176 ((_ file)
177 ;; Elements of FILES that are store
178 ;; files and that do not correspond to
179 ;; the output of INPUTS are considered
180 ;; inputs (still here?).
181 (and (direct-store-path? file)
182 (not (member file outputs)))))
183 files))))
184 (derivation-expression name
185 `(let ((out (assoc-ref %outputs "out")))
186 (mkdir out)
187 (chdir out)
188 ,@(map (match-lambda
189 ((name target)
190 `(symlink ,target ,name)))
191 files))
192
193 #:inputs inputs))))
194
195(define (links inputs)
196 "Return a directory with symbolic links to all of INPUTS. This is
197essentially useful when one wants to keep references to all of INPUTS, be they
198directories or regular files."
199 (define builder
200 '(begin
201 (use-modules (srfi srfi-1))
202
203 (let ((out (assoc-ref %outputs "out")))
204 (mkdir out)
205 (chdir out)
206 (fold (lambda (file number)
207 (symlink file (number->string number))
208 (+ 1 number))
209 0
210 (map cdr %build-inputs))
211 #t)))
212
213 (mlet %store-monad ((inputs (lower-inputs inputs)))
214 (derivation-expression "links" builder
215 #:inputs inputs)))
216
217(define* (etc-directory #:key
3141a8bd 218 (locale "C") (timezone "Europe/Paris")
033adfe7
LC
219 (accounts '())
220 (groups '())
221 (pam-services '())
222 (profile "/var/run/current-system/profile"))
223 "Return a derivation that builds the static part of the /etc directory."
224 (mlet* %store-monad
225 ((services (package-file net-base "etc/services"))
226 (protocols (package-file net-base "etc/protocols"))
227 (rpc (package-file net-base "etc/rpc"))
228 (passwd (passwd-file accounts))
229 (shadow (passwd-file accounts #:shadow? #t))
230 (group (group-file groups))
231 (pam.d (pam-services->directory pam-services))
232 (login.defs (text-file "login.defs" "# Empty for now.\n"))
233 (issue (text-file "issue" "
234This is an alpha preview of the GNU system. Welcome.
235
236This image features the GNU Guix package manager, which was used to
237build it (http://www.gnu.org/software/guix/). The init system is
238GNU dmd (http://www.gnu.org/software/dmd/).
239
240You can log in as 'guest' or 'root' with no password.
241"))
242
3141a8bd
LC
243 ;; Assume TZDATA is installed---e.g., as part of the system packages.
244 ;; Users can choose not to have it.
245 (tzdir (package-file tzdata "share/zoneinfo"))
246
033adfe7
LC
247 ;; TODO: Generate bashrc from packages' search-paths.
248 (bashrc (text-file "bashrc" (string-append "
249export PS1='\\u@\\h\\$ '
3141a8bd
LC
250
251export LC_ALL=\"" locale "\"
252export TZ=\"" timezone "\"
253export TZDIR=\"" tzdir "\"
254
033adfe7
LC
255export PATH=$HOME/.guix-profile/bin:" profile "/bin:" profile "/sbin
256export CPATH=$HOME/.guix-profile/include:" profile "/include
257export LIBRARY_PATH=$HOME/.guix-profile/lib:" profile "/lib
258alias ls='ls -p --color'
259alias ll='ls -l'
260")))
261
262 (files -> `(("services" ,services)
263 ("protocols" ,protocols)
264 ("rpc" ,rpc)
265 ("pam.d" ,(derivation->output-path pam.d))
266 ("login.defs" ,login.defs)
267 ("issue" ,issue)
268 ("profile" ,bashrc)
269 ("passwd" ,passwd)
270 ("shadow" ,shadow)
271 ("group" ,group))))
272 (file-union files
273 #:inputs `(("net" ,net-base)
274 ("pam.d" ,pam.d))
275 #:name "etc")))
276
277(define (operating-system-derivation os)
278 "Return a derivation that builds OS."
279 (mlet* %store-monad
280 ((services (sequence %store-monad
281 (cons (host-name-service
282 (operating-system-host-name os))
283 (operating-system-services os))))
284 (pam-services ->
285 ;; Services known to PAM.
286 (delete-duplicates
287 (cons %pam-other-services
288 (append-map service-pam-services services))))
289
290 (bash-file (package-file bash "bin/bash"))
9de46ffb 291 (dmd-file (package-file (@ (gnu packages admin) dmd) "bin/dmd"))
033adfe7
LC
292 (accounts -> (cons (user-account
293 (name "root")
294 (password "")
295 (uid 0) (gid 0)
296 (comment "System administrator")
78ed0038 297 (home-directory "/"))
033adfe7
LC
298 (append (operating-system-users os)
299 (append-map service-user-accounts
300 services))))
301 (groups -> (append (operating-system-groups os)
302 (append-map service-user-groups services)))
303 (packages -> (operating-system-packages os))
304
305 ;; TODO: Replace with a real profile with a manifest.
306 (profile-drv (union packages
307 #:name "default-profile"))
308 (profile -> (derivation->output-path profile-drv))
309 (etc-drv (etc-directory #:accounts accounts #:groups groups
310 #:pam-services pam-services
3141a8bd
LC
311 #:locale (operating-system-locale os)
312 #:timezone (operating-system-timezone os)
033adfe7
LC
313 #:profile profile))
314 (etc -> (derivation->output-path etc-drv))
315 (dmd-conf (dmd-configuration-file services etc))
316
317
318 (boot (text-file "boot"
319 (object->string
320 `(execl ,dmd-file "dmd"
321 "--config" ,dmd-conf))))
322 (kernel -> (operating-system-kernel os))
323 (kernel-dir (package-file kernel))
324 (initrd -> (operating-system-initrd os))
325 (initrd-file (package-file initrd))
326 (entries -> (list (menu-entry
327 (label (string-append
328 "GNU system with "
329 (package-full-name kernel)
330 " (technology preview)"))
331 (linux kernel)
332 (linux-arguments `("--root=/dev/vda1"
333 ,(string-append "--load=" boot)))
334 (initrd initrd))))
335 (grub.cfg (grub-configuration-file entries))
336 (extras (links (delete-duplicates
78ed0038
LC
337 (append (append-map service-inputs services)
338 (append-map user-account-inputs accounts))))))
033adfe7
LC
339 (file-union `(("boot" ,boot)
340 ("kernel" ,kernel-dir)
341 ("initrd" ,initrd-file)
342 ("dmd.conf" ,dmd-conf)
033adfe7
LC
343 ("profile" ,profile)
344 ("grub.cfg" ,grub.cfg)
345 ("etc" ,etc)
78ed0038 346 ("system-inputs" ,(derivation->output-path extras)))
033adfe7
LC
347 #:inputs `(("kernel" ,kernel)
348 ("initrd" ,initrd)
349 ("bash" ,bash)
350 ("profile" ,profile-drv)
351 ("etc" ,etc-drv)
78ed0038 352 ("system-inputs" ,extras))
033adfe7
LC
353 #:name "system")))
354
355;;; system.scm ends here