pull: Rewrite using gexps.
[jackhill/guix/guix.git] / gnu / services / base.scm
CommitLineData
db4fdc04
LC
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2013, 2014 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 services base)
185f6691
LC
20 #:use-module ((guix store)
21 #:select (%store-prefix))
db4fdc04 22 #:use-module (gnu services)
4a3b3b07 23 #:use-module (gnu services networking)
db4fdc04
LC
24 #:use-module (gnu system shadow) ; 'user-account', etc.
25 #:use-module (gnu system linux) ; 'pam-service', etc.
26 #:use-module (gnu packages admin)
151a2c07 27 #:use-module ((gnu packages linux)
8a7330fd 28 #:select (eudev kbd e2fsprogs lvm2 fuse alsa-utils))
db4fdc04 29 #:use-module ((gnu packages base)
bdb36958 30 #:select (canonical-package glibc))
db4fdc04 31 #:use-module (gnu packages package-management)
e2f4b305 32 #:use-module ((gnu build file-systems)
2c071ce9 33 #:select (mount-flags->bit-mask))
b5f4e686 34 #:use-module (guix gexp)
db4fdc04
LC
35 #:use-module (guix monads)
36 #:use-module (srfi srfi-1)
37 #:use-module (srfi srfi-26)
38 #:use-module (ice-9 format)
a00dd9fb 39 #:export (root-file-system-service
023f391c 40 file-system-service
5dae0186 41 device-mapping-service
a00dd9fb
LC
42 user-processes-service
43 host-name-service
62ca0fdf 44 console-font-service
151a2c07 45 udev-service
db4fdc04
LC
46 mingetty-service
47 nscd-service
48 syslog-service
8b198abe
LC
49 guix-service
50 %base-services))
db4fdc04
LC
51
52;;; Commentary:
53;;;
54;;; Base system services---i.e., services that 99% of the users will want to
55;;; use.
56;;;
57;;; Code:
58
a00dd9fb
LC
59(define (root-file-system-service)
60 "Return a service whose sole purpose is to re-mount read-only the root file
61system upon shutdown (aka. cleanly \"umounting\" root.)
62
63This service must be the root of the service dependency graph so that its
64'stop' action is invoked when dmd is the only process left."
a00dd9fb
LC
65 (with-monad %store-monad
66 (return
67 (service
68 (documentation "Take care of the root file system.")
69 (provision '(root-file-system))
70 (start #~(const #t))
71 (stop #~(lambda _
72 ;; Return #f if successfully stopped.
23ed63a1 73 (sync)
a00dd9fb
LC
74
75 (call-with-blocked-asyncs
76 (lambda ()
77 (let ((null (%make-void-port "w")))
78 ;; Close 'dmd.log'.
79 (display "closing log\n")
80 ;; XXX: Ideally we'd use 'stop-logging', but that one
81 ;; doesn't actually close the port as of dmd 0.1.
82 (close-port (@@ (dmd comm) log-output-port))
83 (set! (@@ (dmd comm) log-output-port) null)
84
85 ;; Redirect the default output ports..
86 (set-current-output-port null)
87 (set-current-error-port null)
88
89 ;; Close /dev/console.
90 (for-each close-fdes '(0 1 2))
91
23ed63a1 92 ;; At this point, there are no open files left, so the
a00dd9fb 93 ;; root file system can be re-mounted read-only.
23ed63a1
LC
94 (mount #f "/" #f
95 (logior MS_REMOUNT MS_RDONLY)
96 #:update-mtab? #f)
97
98 #f)))))
a00dd9fb
LC
99 (respawn? #f)))))
100
023f391c 101(define* (file-system-service device target type
2c071ce9 102 #:key (flags '()) (check? #t)
5dae0186
LC
103 create-mount-point? options (title 'any)
104 (requirements '()))
023f391c 105 "Return a service that mounts DEVICE on TARGET as a file system TYPE with
d4c87617
LC
106OPTIONS. TITLE is a symbol specifying what kind of name DEVICE is: 'label for
107a partition label, 'device for a device file name, or 'any. When CHECK? is
4e469051 108true, check the file system before mounting it. When CREATE-MOUNT-POINT? is
2c071ce9 109true, create TARGET if it does not exist yet. FLAGS is a list of symbols,
5dae0186
LC
110such as 'read-only' etc. Optionally, REQUIREMENTS may be a list of service
111names such as device-mapping services."
023f391c
LC
112 (with-monad %store-monad
113 (return
114 (service
115 (provision (list (symbol-append 'file-system- (string->symbol target))))
5dae0186 116 (requirement `(root-file-system ,@requirements))
023f391c
LC
117 (documentation "Check, mount, and unmount the given file system.")
118 (start #~(lambda args
d4c87617 119 (let ((device (canonicalize-device-spec #$device '#$title)))
4e469051
LC
120 #$(if create-mount-point?
121 #~(mkdir-p #$target)
122 #~#t)
d4c87617 123 #$(if check?
1b09031f
LC
124 #~(begin
125 ;; Make sure fsck.ext2 & co. can be found.
126 (setenv "PATH"
127 (string-append
128 #$e2fsprogs "/sbin:"
129 "/run/current-system/profile/sbin:"
130 (getenv "PATH")))
131 (check-file-system device #$type))
d4c87617 132 #~#t)
2c071ce9
LC
133 (mount device #$target #$type
134 #$(mount-flags->bit-mask flags)
135 #$options))
023f391c
LC
136 #t))
137 (stop #~(lambda args
138 ;; Normally there are no processes left at this point, so
139 ;; TARGET can be safely unmounted.
6a3f4c74
LC
140
141 ;; Make sure PID 1 doesn't keep TARGET busy.
142 (chdir "/")
143
023f391c
LC
144 (umount #$target)
145 #f))))))
146
7d57cfd3
LC
147(define %do-not-kill-file
148 ;; Name of the file listing PIDs of processes that must survive when halting
149 ;; the system. Typical example is user-space file systems.
150 "/etc/dmd/do-not-kill")
151
023f391c 152(define* (user-processes-service requirements #:key (grace-delay 2))
a00dd9fb
LC
153 "Return the service that is responsible for terminating all the processes so
154that the root file system can be re-mounted read-only, just before
155rebooting/halting. Processes still running GRACE-DELAY seconds after SIGTERM
156has been sent are terminated with SIGKILL.
157
023f391c
LC
158The returned service will depend on 'root-file-system' and on all the services
159listed in REQUIREMENTS.
160
a00dd9fb
LC
161All the services that spawn processes must depend on this one so that they are
162stopped before 'kill' is called."
163 (with-monad %store-monad
164 (return (service
165 (documentation "When stopped, terminate all user processes.")
166 (provision '(user-processes))
023f391c 167 (requirement (cons 'root-file-system requirements))
a00dd9fb
LC
168 (start #~(const #t))
169 (stop #~(lambda _
7d57cfd3
LC
170 (define (kill-except omit signal)
171 ;; Kill all the processes with SIGNAL except those
172 ;; listed in OMIT and the current process.
173 (let ((omit (cons (getpid) omit)))
174 (for-each (lambda (pid)
175 (unless (memv pid omit)
176 (false-if-exception
177 (kill pid signal))))
178 (processes))))
179
180 (define omitted-pids
181 ;; List of PIDs that must not be killed.
182 (if (file-exists? #$%do-not-kill-file)
183 (map string->number
184 (call-with-input-file #$%do-not-kill-file
185 (compose string-tokenize
186 (@ (ice-9 rdelim) read-string))))
187 '()))
188
d656c14e
LC
189 (define lset= (@ (srfi srfi-1) lset=))
190
a00dd9fb
LC
191 ;; When this happens, all the processes have been
192 ;; killed, including 'deco', so DMD-OUTPUT-PORT and
193 ;; thus CURRENT-OUTPUT-PORT are dangling.
194 (call-with-output-file "/dev/console"
195 (lambda (port)
196 (display "sending all processes the TERM signal\n"
197 port)))
198
7d57cfd3
LC
199 (if (null? omitted-pids)
200 (begin
201 ;; Easy: terminate all of them.
202 (kill -1 SIGTERM)
203 (sleep #$grace-delay)
204 (kill -1 SIGKILL))
205 (begin
206 ;; Kill them all except OMITTED-PIDS. XXX: We
207 ;; would like to (kill -1 SIGSTOP) to get a fixed
208 ;; list of processes, like 'killall5' does, but
209 ;; that seems unreliable.
210 (kill-except omitted-pids SIGTERM)
211 (sleep #$grace-delay)
212 (kill-except omitted-pids SIGKILL)
213 (delete-file #$%do-not-kill-file)))
a00dd9fb 214
d656c14e
LC
215 (let wait ()
216 (let ((pids (processes)))
217 (unless (lset= = pids (cons 1 omitted-pids))
218 (format #t "waiting for process termination\
219 (processes left: ~s)~%"
220 pids)
221 (sleep 2)
222 (wait))))
223
a00dd9fb
LC
224 (display "all processes have been terminated\n")
225 #f))
226 (respawn? #f)))))
227
db4fdc04 228(define (host-name-service name)
51da7ca0 229 "Return a service that sets the host name to @var{name}."
db4fdc04
LC
230 (with-monad %store-monad
231 (return (service
232 (documentation "Initialize the machine's host name.")
233 (provision '(host-name))
b5f4e686
LC
234 (start #~(lambda _
235 (sethostname #$name)))
db4fdc04
LC
236 (respawn? #f)))))
237
62ca0fdf
LC
238(define (unicode-start tty)
239 "Return a gexp to start Unicode support on @var{tty}."
240
241 ;; We have to run 'unicode_start' in a pipe so that when it invokes the
242 ;; 'tty' command, that command returns TTY.
243 #~(begin
244 (let ((pid (primitive-fork)))
245 (case pid
246 ((0)
247 (close-fdes 0)
248 (dup2 (open-fdes #$tty O_RDONLY) 0)
249 (close-fdes 1)
250 (dup2 (open-fdes #$tty O_WRONLY) 1)
251 (execl (string-append #$kbd "/bin/unicode_start")
252 "unicode_start"))
253 (else
254 (zero? (cdr (waitpid pid))))))))
255
256(define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
257 "Return a service that sets up Unicode support in @var{tty} and loads
258@var{font} for that tty (fonts are per virtual console in Linux.)"
259 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
260 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
261 ;; codepoints notably found in the UTF-8 manual.
262 (let ((device (string-append "/dev/" tty)))
263 (with-monad %store-monad
264 (return (service
265 (documentation "Load a Unicode console font.")
266 (provision (list (symbol-append 'console-font-
267 (string->symbol tty))))
268
269 ;; Start after mingetty has been started on TTY, otherwise the
270 ;; settings are ignored.
271 (requirement (list (symbol-append 'term-
272 (string->symbol tty))))
273
274 (start #~(lambda _
275 (and #$(unicode-start device)
276 (zero?
277 (system* (string-append #$kbd "/bin/setfont")
278 "-C" #$device #$font)))))
279 (stop #~(const #t))
280 (respawn? #f))))))
281
db4fdc04
LC
282(define* (mingetty-service tty
283 #:key
284 (motd (text-file "motd" "Welcome.\n"))
52322163
LC
285 auto-login
286 login-program
287 login-pause?
51da7ca0
LC
288
289 ;; Allow empty passwords by default so that
290 ;; first-time users can log in when the 'root'
291 ;; account has just been created.
db4fdc04 292 (allow-empty-passwords? #t))
52322163
LC
293 "Return a service to run mingetty on @var{tty}.
294
295When @var{allow-empty-passwords?} is true, allow empty log-in password. When
296@var{auto-login} is true, it must be a user name under which to log-in
297automatically. @var{login-pause?} can be set to @code{#t} in conjunction with
298@var{auto-login}, in which case the user will have to press a key before the
299login shell is launched.
300
301When true, @var{login-program} is a gexp or a monadic gexp denoting the name
302of the log-in program (the default is the @code{login} program from the Shadow
303tool suite.)
304
305@var{motd} is a monadic value containing a text file to use as
51da7ca0 306the ``message of the day''."
52322163
LC
307 (mlet %store-monad ((motd motd)
308 (login-program (cond ((gexp? login-program)
309 (return login-program))
310 ((not login-program)
311 (return #f))
312 (else
313 login-program))))
db4fdc04
LC
314 (return
315 (service
316 (documentation (string-append "Run mingetty on " tty "."))
317 (provision (list (symbol-append 'term- (string->symbol tty))))
318
319 ;; Since the login prompt shows the host name, wait for the 'host-name'
320 ;; service to be done.
a00dd9fb 321 (requirement '(user-processes host-name))
db4fdc04 322
b5f4e686 323 (start #~(make-forkexec-constructor
1c6b445b
LC
324 (list (string-append #$mingetty "/sbin/mingetty")
325 "--noclear" #$tty
326 #$@(if auto-login
327 #~("--autologin" #$auto-login)
328 #~())
329 #$@(if login-program
330 #~("--loginprog" #$login-program)
331 #~())
332 #$@(if login-pause?
333 #~("--loginpause")
334 #~()))))
b5f4e686 335 (stop #~(make-kill-destructor))
db4fdc04
LC
336
337 (pam-services
338 ;; Let 'login' be known to PAM. All the mingetty services will have
339 ;; that PAM service, but that's fine because they're all identical and
340 ;; duplicates are removed.
341 (list (unix-pam-service "login"
342 #:allow-empty-passwords? allow-empty-passwords?
343 #:motd motd)))))))
344
bdb36958 345(define* (nscd-service #:key (glibc (canonical-package glibc)))
db4fdc04 346 "Return a service that runs libc's name service cache daemon (nscd)."
b5f4e686 347 (with-monad %store-monad
db4fdc04
LC
348 (return (service
349 (documentation "Run libc's name service cache daemon (nscd).")
350 (provision '(nscd))
a00dd9fb 351 (requirement '(user-processes))
4b2615e1
LC
352
353 (activate #~(begin
354 (use-modules (guix build utils))
355 (mkdir-p "/var/run/nscd")))
356
1c6b445b
LC
357 (start #~(make-forkexec-constructor
358 (list (string-append #$glibc "/sbin/nscd")
359 "-f" "/dev/null" "--foreground")))
b5f4e686 360 (stop #~(make-kill-destructor))
db4fdc04 361
b5f4e686 362 (respawn? #f)))))
db4fdc04
LC
363
364(define (syslog-service)
51da7ca0 365 "Return a service that runs @code{syslogd} with reasonable default settings."
db4fdc04
LC
366
367 ;; Snippet adapted from the GNU inetutils manual.
368 (define contents "
1f3fc60d 369 # Log all error messages, authentication messages of
db4fdc04
LC
370 # level notice or higher and anything of level err or
371 # higher to the console.
372 # Don't log private authentication messages!
6a191274 373 *.alert;auth.notice;authpriv.none /dev/console
db4fdc04
LC
374
375 # Log anything (except mail) of level info or higher.
376 # Don't log private authentication messages!
377 *.info;mail.none;authpriv.none /var/log/messages
378
379 # Same, in a different place.
380 *.info;mail.none;authpriv.none /dev/tty12
381
382 # The authpriv file has restricted access.
383 authpriv.* /var/log/secure
384
385 # Log all the mail messages in one place.
386 mail.* /var/log/maillog
387")
388
389 (mlet %store-monad
b5f4e686 390 ((syslog.conf (text-file "syslog.conf" contents)))
db4fdc04
LC
391 (return
392 (service
393 (documentation "Run the syslog daemon (syslogd).")
394 (provision '(syslogd))
a00dd9fb 395 (requirement '(user-processes))
b5f4e686 396 (start
1c6b445b
LC
397 #~(make-forkexec-constructor
398 (list (string-append #$inetutils "/libexec/syslogd")
399 "--no-detach" "--rcfile" #$syslog.conf)))
b5f4e686 400 (stop #~(make-kill-destructor))))))
db4fdc04
LC
401
402(define* (guix-build-accounts count #:key
ab6a279a 403 (group "guixbuild")
db4fdc04 404 (first-uid 30001)
db4fdc04
LC
405 (shadow shadow))
406 "Return a list of COUNT user accounts for Guix build users, with UIDs
407starting at FIRST-UID, and under GID."
408 (with-monad %store-monad
409 (return (unfold (cut > <> count)
410 (lambda (n)
411 (user-account
412 (name (format #f "guixbuilder~2,'0d" n))
459dd9ea 413 (system? #t)
db4fdc04 414 (uid (+ first-uid n -1))
ab6a279a 415 (group group)
3d116a70
LC
416
417 ;; guix-daemon expects GROUP to be listed as a
418 ;; supplementary group too:
419 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
420 (supplementary-groups (list group))
421
db4fdc04
LC
422 (comment (format #f "Guix Build User ~2d" n))
423 (home-directory "/var/empty")
b5f4e686 424 (shell #~(string-append #$shadow "/sbin/nologin"))))
db4fdc04
LC
425 1+
426 1))))
427
2c5c696c
LC
428(define (hydra-key-authorization guix)
429 "Return a gexp with code to register the hydra.gnu.org public key with
430GUIX."
431 #~(unless (file-exists? "/etc/guix/acl")
432 (let ((pid (primitive-fork)))
433 (case pid
434 ((0)
435 (let* ((key (string-append #$guix
436 "/share/guix/hydra.gnu.org.pub"))
437 (port (open-file key "r0b")))
438 (format #t "registering public key '~a'...~%" key)
439 (close-port (current-input-port))
2c5c696c
LC
440 (dup port 0)
441 (execl (string-append #$guix "/bin/guix")
442 "guix" "archive" "--authorize")
443 (exit 1)))
444 (else
445 (let ((status (cdr (waitpid pid))))
446 (unless (zero? status)
447 (format (current-error-port) "warning: \
448failed to register hydra.gnu.org public key: ~a~%" status))))))))
449
db4fdc04 450(define* (guix-service #:key (guix guix) (builder-group "guixbuild")
c11a6eb1
LC
451 (build-accounts 10) authorize-hydra-key?
452 (use-substitutes? #t)
453 (extra-options '()))
51da7ca0
LC
454 "Return a service that runs the build daemon from @var{guix}, and has
455@var{build-accounts} user accounts available under @var{builder-group}.
2c5c696c 456
51da7ca0
LC
457When @var{authorize-hydra-key?} is true, the @code{hydra.gnu.org} public key
458provided by @var{guix} is authorized upon activation, meaning that substitutes
c11a6eb1
LC
459from @code{hydra.gnu.org} are used by default.
460
461If @var{use-substitutes?} is false, the daemon is run with
462@option{--no-substitutes} (@pxref{Invoking guix-daemon,
463@option{--no-substitutes}}).
464
465Finally, @var{extra-options} is a list of additional command-line options
466passed to @command{guix-daemon}."
185f6691 467 (define activate
e97c5be9
LC
468 ;; Assume that the store has BUILDER-GROUP as its group. We could
469 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
470 ;; chown leads to an entire copy of the tree, which is a bad idea.
185f6691 471
e97c5be9
LC
472 ;; Optionally authorize hydra.gnu.org's key.
473 (and authorize-hydra-key?
474 (hydra-key-authorization guix)))
185f6691 475
b5f4e686 476 (mlet %store-monad ((accounts (guix-build-accounts build-accounts
ab6a279a 477 #:group builder-group)))
db4fdc04
LC
478 (return (service
479 (provision '(guix-daemon))
a00dd9fb 480 (requirement '(user-processes))
b5f4e686 481 (start
1c6b445b
LC
482 #~(make-forkexec-constructor
483 (list (string-append #$guix "/bin/guix-daemon")
c11a6eb1
LC
484 "--build-users-group" #$builder-group
485 #$@(if use-substitutes?
486 '()
487 '("--no-substitutes"))
488 #$@extra-options)))
b5f4e686 489 (stop #~(make-kill-destructor))
db4fdc04
LC
490 (user-accounts accounts)
491 (user-groups (list (user-group
492 (name builder-group)
41717509 493 (system? #t)
e97c5be9
LC
494
495 ;; Use a fixed GID so that we can create the
496 ;; store with the right owner.
497 (id 30000))))
185f6691 498 (activate activate)))))
db4fdc04 499
ecd06ca9
LC
500(define (udev-rules-union packages)
501 "Return the union of the @code{lib/udev/rules.d} directories found in each
502item of @var{packages}."
503 (define build
504 #~(begin
505 (use-modules (guix build union)
506 (guix build utils)
507 (srfi srfi-1)
508 (srfi srfi-26))
509
510 (define %standard-locations
511 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
512
513 (define (rules-sub-directory directory)
514 ;; Return the sub-directory of DIRECTORY containing udev rules, or
515 ;; #f if none was found.
516 (find directory-exists?
517 (map (cut string-append directory <>) %standard-locations)))
518
519 (mkdir-p (string-append #$output "/lib/udev"))
520 (union-build (string-append #$output "/lib/udev/rules.d")
521 (filter-map rules-sub-directory '#$packages))))
522
523 (gexp->derivation "udev-rules" build
524 #:modules '((guix build union)
525 (guix build utils))
526 #:local-build? #t))
527
8a7330fd 528(define* (udev-service #:key (udev eudev) (rules '()))
ecd06ca9
LC
529 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
530extra rules from the packages listed in @var{rules}."
531 (mlet* %store-monad ((rules (udev-rules-union (cons udev rules)))
532 (udev.conf (text-file* "udev.conf"
533 "udev_rules=\"" rules
534 "/lib/udev/rules.d\"\n")))
151a2c07
LC
535 (return (service
536 (provision '(udev))
a69576ea
LC
537
538 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device
539 ;; nodes can be added: see
540 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
7f239fd3 541 (requirement '(root-file-system))
a69576ea
LC
542
543 (documentation "Populate the /dev directory, dynamically.")
151a2c07 544 (start #~(lambda ()
66a99a06
LC
545 (define find
546 (@ (srfi srfi-1) find))
547
1c6b445b 548 (define udevd
66a99a06
LC
549 ;; Choose the right 'udevd'.
550 (find file-exists?
551 (map (lambda (suffix)
552 (string-append #$udev suffix))
553 '("/libexec/udev/udevd" ;udev
554 "/sbin/udevd")))) ;eudev
1c6b445b 555
ed09bb11
LC
556 (define (wait-for-udevd)
557 ;; Wait until someone's listening on udevd's control
558 ;; socket.
559 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
560 (let try ()
561 (catch 'system-error
562 (lambda ()
563 (connect sock PF_UNIX "/run/udev/control")
564 (close-port sock))
565 (lambda args
566 (format #t "waiting for udevd...~%")
567 (usleep 500000)
568 (try))))))
569
081c5b2d
LC
570 ;; Allow udev to find the modules.
571 (setenv "LINUX_MODULE_DIRECTORY"
572 "/run/booted-system/kernel/lib/modules")
573
66a99a06 574 ;; The first one is for udev, the second one for eudev.
ecd06ca9 575 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
66a99a06 576 (setenv "EUDEV_RULES_DIRECTORY" #$rules)
ecd06ca9 577
151a2c07
LC
578 (let ((pid (primitive-fork)))
579 (case pid
580 ((0)
1c6b445b 581 (exec-command (list udevd)))
151a2c07 582 (else
ed09bb11
LC
583 ;; Wait until udevd is up and running. This
584 ;; appears to be needed so that the events
585 ;; triggered below are actually handled.
586 (wait-for-udevd)
587
588 ;; Trigger device node creation.
589 (system* (string-append #$udev "/bin/udevadm")
590 "trigger" "--action=add")
591
081c5b2d
LC
592 ;; Wait for things to settle down.
593 (system* (string-append #$udev "/bin/udevadm")
594 "settle")
151a2c07 595 pid)))))
66d5d8c0
LC
596 (stop #~(make-kill-destructor))
597
598 ;; When halting the system, 'udev' is actually killed by
599 ;; 'user-processes', i.e., before its own 'stop' method was
600 ;; called. Thus, make sure it is not respawned.
601 (respawn? #f)))))
151a2c07 602
5dae0186
LC
603(define (device-mapping-service target command)
604 "Return a service that maps device @var{target}, a string such as
605@code{\"home\"} (meaning @code{/dev/mapper/home}), by executing @var{command},
606a gexp."
607 (with-monad %store-monad
608 (return (service
609 (provision (list (symbol-append 'device-mapping-
610 (string->symbol target))))
611 (requirement '(udev))
612 (documentation "Map a device node using Linux's device mapper.")
613 (start #~(lambda ()
614 #$command))
615 (stop #~(const #f))
616 (respawn? #f)))))
617
8b198abe
LC
618(define %base-services
619 ;; Convenience variable holding the basic services.
620 (let ((motd (text-file "motd" "
621This is the GNU operating system, welcome!\n\n")))
62ca0fdf
LC
622 (list (console-font-service "tty1")
623 (console-font-service "tty2")
624 (console-font-service "tty3")
625 (console-font-service "tty4")
626 (console-font-service "tty5")
627 (console-font-service "tty6")
628
629 (mingetty-service "tty1" #:motd motd)
8b198abe
LC
630 (mingetty-service "tty2" #:motd motd)
631 (mingetty-service "tty3" #:motd motd)
632 (mingetty-service "tty4" #:motd motd)
633 (mingetty-service "tty5" #:motd motd)
634 (mingetty-service "tty6" #:motd motd)
4a3b3b07
LC
635 (static-networking-service "lo" "127.0.0.1"
636 #:provision '(loopback))
8b198abe
LC
637 (syslog-service)
638 (guix-service)
151a2c07 639 (nscd-service)
ecd06ca9 640
52bd5734
LC
641 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
642 ;; used, so enable them by default. The FUSE and ALSA rules are
643 ;; less critical, but handy.
644 (udev-service #:rules (list lvm2 fuse alsa-utils)))))
8b198abe 645
db4fdc04 646;;; base.scm ends here