gnu: Add emulation-station.
[jackhill/guix/guix.git] / gnu / services / base.scm
CommitLineData
db4fdc04 1;;; GNU Guix --- Functional package management for GNU
4a4dd5d8 2;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
5eca9459 3;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
4307c476 4;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
db4fdc04
LC
5;;;
6;;; This file is part of GNU Guix.
7;;;
8;;; GNU Guix is free software; you can redistribute it and/or modify it
9;;; under the terms of the GNU General Public License as published by
10;;; the Free Software Foundation; either version 3 of the License, or (at
11;;; your option) any later version.
12;;;
13;;; GNU Guix is distributed in the hope that it will be useful, but
14;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;;; GNU General Public License for more details.
17;;;
18;;; You should have received a copy of the GNU General Public License
19;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
20
21(define-module (gnu services base)
e87f0591 22 #:use-module (guix store)
db4fdc04 23 #:use-module (gnu services)
0adfe95a 24 #:use-module (gnu services dmd)
4a3b3b07 25 #:use-module (gnu services networking)
6e828634 26 #:use-module (gnu system pam)
db4fdc04 27 #:use-module (gnu system shadow) ; 'user-account', etc.
0adfe95a 28 #:use-module (gnu system file-systems) ; 'file-system', etc.
db4fdc04 29 #:use-module (gnu packages admin)
151a2c07 30 #:use-module ((gnu packages linux)
8664cc88 31 #:select (eudev kbd e2fsprogs lvm2 fuse alsa-utils crda gpm))
db4fdc04 32 #:use-module ((gnu packages base)
bdb36958 33 #:select (canonical-package glibc))
db4fdc04 34 #:use-module (gnu packages package-management)
2d1d2dd8
LC
35 #:use-module (gnu packages lsh)
36 #:use-module (gnu packages lsof)
e2f4b305 37 #:use-module ((gnu build file-systems)
2c071ce9 38 #:select (mount-flags->bit-mask))
b5f4e686 39 #:use-module (guix gexp)
6454b333 40 #:use-module (guix records)
db4fdc04
LC
41 #:use-module (srfi srfi-1)
42 #:use-module (srfi srfi-26)
6454b333 43 #:use-module (ice-9 match)
db4fdc04 44 #:use-module (ice-9 format)
a00dd9fb 45 #:export (root-file-system-service
023f391c 46 file-system-service
d6e2a622 47 user-unmount-service
5dae0186 48 device-mapping-service
2a13d05e 49 swap-service
a00dd9fb
LC
50 user-processes-service
51 host-name-service
5eca9459 52 console-keymap-service
62ca0fdf 53 console-font-service
c797fabe
RW
54
55 udev-configuration
56 udev-configuration?
57 udev-configuration-rules
0adfe95a 58 udev-service-type
151a2c07 59 udev-service
80e6f37e 60 udev-rule
66e4f01c
LC
61
62 mingetty-configuration
63 mingetty-configuration?
db4fdc04 64 mingetty-service
cd6f6c22 65 mingetty-service-type
6454b333
LC
66
67 %nscd-default-caches
68 %nscd-default-configuration
69
70 nscd-configuration
71 nscd-configuration?
72
73 nscd-cache
74 nscd-cache?
75
0adfe95a 76 nscd-service-type
db4fdc04
LC
77 nscd-service
78 syslog-service
0adfe95a
LC
79
80 guix-configuration
81 guix-configuration?
8b198abe 82 guix-service
cd6f6c22 83 guix-service-type
1c52181f
LC
84 guix-publish-configuration
85 guix-publish-configuration?
86 guix-publish-service
87 guix-publish-service-type
8664cc88
LC
88 gpm-service-type
89 gpm-service
0adfe95a 90
8b198abe 91 %base-services))
db4fdc04
LC
92
93;;; Commentary:
94;;;
95;;; Base system services---i.e., services that 99% of the users will want to
96;;; use.
97;;;
98;;; Code:
99
0adfe95a
LC
100\f
101;;;
102;;; File systems.
103;;;
a00dd9fb 104
0adfe95a
LC
105(define %root-file-system-dmd-service
106 (dmd-service
be1c2c54
LC
107 (documentation "Take care of the root file system.")
108 (provision '(root-file-system))
109 (start #~(const #t))
110 (stop #~(lambda _
111 ;; Return #f if successfully stopped.
112 (sync)
113
114 (call-with-blocked-asyncs
115 (lambda ()
116 (let ((null (%make-void-port "w")))
117 ;; Close 'dmd.log'.
118 (display "closing log\n")
119 ;; XXX: Ideally we'd use 'stop-logging', but that one
120 ;; doesn't actually close the port as of dmd 0.1.
121 (close-port (@@ (dmd comm) log-output-port))
122 (set! (@@ (dmd comm) log-output-port) null)
123
124 ;; Redirect the default output ports..
125 (set-current-output-port null)
126 (set-current-error-port null)
127
128 ;; Close /dev/console.
129 (for-each close-fdes '(0 1 2))
130
131 ;; At this point, there are no open files left, so the
132 ;; root file system can be re-mounted read-only.
133 (mount #f "/" #f
134 (logior MS_REMOUNT MS_RDONLY)
135 #:update-mtab? #f)
136
137 #f)))))
138 (respawn? #f)))
a00dd9fb 139
0adfe95a 140(define root-file-system-service-type
00184239
LC
141 (dmd-service-type 'root-file-system
142 (const %root-file-system-dmd-service)))
0adfe95a
LC
143
144(define (root-file-system-service)
145 "Return a service whose sole purpose is to re-mount read-only the root file
146system upon shutdown (aka. cleanly \"umounting\" root.)
147
148This service must be the root of the service dependency graph so that its
149'stop' action is invoked when dmd is the only process left."
150 (service root-file-system-service-type #f))
151
152(define (file-system->dmd-service-name file-system)
153 "Return the symbol that denotes the service mounting and unmounting
154FILE-SYSTEM."
155 (symbol-append 'file-system-
156 (string->symbol (file-system-mount-point file-system))))
157
e502bf89
LC
158(define (mapped-device->dmd-service-name md)
159 "Return the symbol that denotes the dmd service of MD, a <mapped-device>."
160 (symbol-append 'device-mapping-
161 (string->symbol (mapped-device-target md))))
162
163(define dependency->dmd-service-name
164 (match-lambda
165 ((? mapped-device? md)
166 (mapped-device->dmd-service-name md))
167 ((? file-system? fs)
168 (file-system->dmd-service-name fs))))
169
0adfe95a
LC
170(define file-system-service-type
171 ;; TODO(?): Make this an extensible service that takes <file-system> objects
172 ;; and returns a list of <dmd-service>.
173 (dmd-service-type
00184239 174 'file-system
0adfe95a
LC
175 (lambda (file-system)
176 (let ((target (file-system-mount-point file-system))
177 (device (file-system-device file-system))
178 (type (file-system-type file-system))
179 (title (file-system-title file-system))
180 (check? (file-system-check? file-system))
181 (create? (file-system-create-mount-point? file-system))
182 (dependencies (file-system-dependencies file-system)))
183 (dmd-service
184 (provision (list (file-system->dmd-service-name file-system)))
185 (requirement `(root-file-system
e502bf89 186 ,@(map dependency->dmd-service-name dependencies)))
0adfe95a
LC
187 (documentation "Check, mount, and unmount the given file system.")
188 (start #~(lambda args
189 ;; FIXME: Use or factorize with 'mount-file-system'.
190 (let ((device (canonicalize-device-spec #$device '#$title))
191 (flags #$(mount-flags->bit-mask
192 (file-system-flags file-system))))
193 #$(if create?
194 #~(mkdir-p #$target)
195 #~#t)
196 #$(if check?
197 #~(begin
198 ;; Make sure fsck.ext2 & co. can be found.
199 (setenv "PATH"
200 (string-append
201 #$e2fsprogs "/sbin:"
202 "/run/current-system/profile/sbin:"
203 (getenv "PATH")))
204 (check-file-system device #$type))
205 #~#t)
206
207 (mount device #$target #$type flags
208 #$(file-system-options file-system))
209
210 ;; For read-only bind mounts, an extra remount is needed,
211 ;; as per <http://lwn.net/Articles/281157/>, which still
212 ;; applies to Linux 4.0.
213 (when (and (= MS_BIND (logand flags MS_BIND))
214 (= MS_RDONLY (logand flags MS_RDONLY)))
215 (mount device #$target #$type
216 (logior MS_BIND MS_REMOUNT MS_RDONLY))))
217 #t))
218 (stop #~(lambda args
219 ;; Normally there are no processes left at this point, so
220 ;; TARGET can be safely unmounted.
221
222 ;; Make sure PID 1 doesn't keep TARGET busy.
223 (chdir "/")
224
225 (umount #$target)
226 #f)))))))
227
228(define* (file-system-service file-system)
229 "Return a service that mounts @var{file-system}, a @code{<file-system>}
230object."
231 (service file-system-service-type file-system))
232
233(define user-unmount-service-type
234 (dmd-service-type
5f44ee4f 235 'user-file-systems
0adfe95a
LC
236 (lambda (known-mount-points)
237 (dmd-service
238 (documentation "Unmount manually-mounted file systems.")
5f44ee4f 239 (provision '(user-file-systems))
0adfe95a
LC
240 (start #~(const #t))
241 (stop #~(lambda args
242 (define (known? mount-point)
243 (member mount-point
244 (cons* "/proc" "/sys" '#$known-mount-points)))
245
246 ;; Make sure we don't keep the user's mount points busy.
247 (chdir "/")
248
249 (for-each (lambda (mount-point)
250 (format #t "unmounting '~a'...~%" mount-point)
251 (catch 'system-error
252 (lambda ()
253 (umount mount-point))
254 (lambda args
255 (let ((errno (system-error-errno args)))
256 (format #t "failed to unmount '~a': ~a~%"
257 mount-point (strerror errno))))))
258 (filter (negate known?) (mount-points)))
259 #f))))))
023f391c 260
d6e2a622
LC
261(define (user-unmount-service known-mount-points)
262 "Return a service whose sole purpose is to unmount file systems not listed
263in KNOWN-MOUNT-POINTS when it is stopped."
0adfe95a 264 (service user-unmount-service-type known-mount-points))
d6e2a622 265
7d57cfd3
LC
266(define %do-not-kill-file
267 ;; Name of the file listing PIDs of processes that must survive when halting
268 ;; the system. Typical example is user-space file systems.
269 "/etc/dmd/do-not-kill")
270
0adfe95a
LC
271(define user-processes-service-type
272 (dmd-service-type
00184239 273 'user-processes
0adfe95a
LC
274 (match-lambda
275 ((requirements grace-delay)
276 (dmd-service
277 (documentation "When stopped, terminate all user processes.")
278 (provision '(user-processes))
5f44ee4f
LC
279 (requirement (cons* 'root-file-system 'user-file-systems
280 (map file-system->dmd-service-name
281 requirements)))
0adfe95a
LC
282 (start #~(const #t))
283 (stop #~(lambda _
284 (define (kill-except omit signal)
285 ;; Kill all the processes with SIGNAL except those listed
286 ;; in OMIT and the current process.
287 (let ((omit (cons (getpid) omit)))
288 (for-each (lambda (pid)
289 (unless (memv pid omit)
290 (false-if-exception
291 (kill pid signal))))
292 (processes))))
293
294 (define omitted-pids
295 ;; List of PIDs that must not be killed.
296 (if (file-exists? #$%do-not-kill-file)
297 (map string->number
298 (call-with-input-file #$%do-not-kill-file
299 (compose string-tokenize
300 (@ (ice-9 rdelim) read-string))))
301 '()))
302
303 (define (now)
304 (car (gettimeofday)))
305
306 (define (sleep* n)
307 ;; Really sleep N seconds.
308 ;; Work around <http://bugs.gnu.org/19581>.
309 (define start (now))
310 (let loop ((elapsed 0))
311 (when (> n elapsed)
312 (sleep (- n elapsed))
313 (loop (- (now) start)))))
314
315 (define lset= (@ (srfi srfi-1) lset=))
316
317 (display "sending all processes the TERM signal\n")
318
319 (if (null? omitted-pids)
320 (begin
321 ;; Easy: terminate all of them.
322 (kill -1 SIGTERM)
323 (sleep* #$grace-delay)
324 (kill -1 SIGKILL))
325 (begin
326 ;; Kill them all except OMITTED-PIDS. XXX: We would
327 ;; like to (kill -1 SIGSTOP) to get a fixed list of
328 ;; processes, like 'killall5' does, but that seems
329 ;; unreliable.
330 (kill-except omitted-pids SIGTERM)
331 (sleep* #$grace-delay)
332 (kill-except omitted-pids SIGKILL)
333 (delete-file #$%do-not-kill-file)))
334
335 (let wait ()
336 (let ((pids (processes)))
337 (unless (lset= = pids (cons 1 omitted-pids))
338 (format #t "waiting for process termination\
339 (processes left: ~s)~%"
340 pids)
341 (sleep* 2)
342 (wait))))
343
344 (display "all processes have been terminated\n")
345 #f))
346 (respawn? #f))))))
347
348(define* (user-processes-service file-systems #:key (grace-delay 4))
a00dd9fb
LC
349 "Return the service that is responsible for terminating all the processes so
350that the root file system can be re-mounted read-only, just before
351rebooting/halting. Processes still running GRACE-DELAY seconds after SIGTERM
352has been sent are terminated with SIGKILL.
353
0adfe95a
LC
354The returned service will depend on 'root-file-system' and on all the dmd
355services corresponding to FILE-SYSTEMS.
023f391c 356
a00dd9fb
LC
357All the services that spawn processes must depend on this one so that they are
358stopped before 'kill' is called."
0adfe95a
LC
359 (service user-processes-service-type
360 (list file-systems grace-delay)))
d656c14e 361
0adfe95a
LC
362\f
363;;;
364;;; Console & co.
365;;;
366
367(define host-name-service-type
368 (dmd-service-type
00184239 369 'host-name
0adfe95a
LC
370 (lambda (name)
371 (dmd-service
372 (documentation "Initialize the machine's host name.")
373 (provision '(host-name))
374 (start #~(lambda _
375 (sethostname #$name)))
376 (respawn? #f)))))
a00dd9fb 377
db4fdc04 378(define (host-name-service name)
51da7ca0 379 "Return a service that sets the host name to @var{name}."
0adfe95a 380 (service host-name-service-type name))
db4fdc04 381
62ca0fdf
LC
382(define (unicode-start tty)
383 "Return a gexp to start Unicode support on @var{tty}."
384
385 ;; We have to run 'unicode_start' in a pipe so that when it invokes the
386 ;; 'tty' command, that command returns TTY.
387 #~(begin
388 (let ((pid (primitive-fork)))
389 (case pid
390 ((0)
391 (close-fdes 0)
392 (dup2 (open-fdes #$tty O_RDONLY) 0)
393 (close-fdes 1)
394 (dup2 (open-fdes #$tty O_WRONLY) 1)
395 (execl (string-append #$kbd "/bin/unicode_start")
396 "unicode_start"))
397 (else
398 (zero? (cdr (waitpid pid))))))))
399
0adfe95a
LC
400(define console-keymap-service-type
401 (dmd-service-type
00184239 402 'console-keymap
0adfe95a
LC
403 (lambda (file)
404 (dmd-service
405 (documentation (string-append "Load console keymap (loadkeys)."))
406 (provision '(console-keymap))
407 (start #~(lambda _
408 (zero? (system* (string-append #$kbd "/bin/loadkeys")
409 #$file))))
410 (respawn? #f)))))
411
5eca9459
AK
412(define (console-keymap-service file)
413 "Return a service to load console keymap from @var{file}."
0adfe95a
LC
414 (service console-keymap-service-type file))
415
416(define console-font-service-type
417 (dmd-service-type
00184239 418 'console-font
0adfe95a
LC
419 (match-lambda
420 ((tty font)
421 (let ((device (string-append "/dev/" tty)))
422 (dmd-service
423 (documentation "Load a Unicode console font.")
424 (provision (list (symbol-append 'console-font-
425 (string->symbol tty))))
426
427 ;; Start after mingetty has been started on TTY, otherwise the settings
428 ;; are ignored.
429 (requirement (list (symbol-append 'term-
430 (string->symbol tty))))
431
432 (start #~(lambda _
433 (and #$(unicode-start device)
434 (zero?
435 (system* (string-append #$kbd "/bin/setfont")
436 "-C" #$device #$font)))))
437 (stop #~(const #t))
438 (respawn? #f)))))))
5eca9459 439
62ca0fdf
LC
440(define* (console-font-service tty #:optional (font "LatGrkCyr-8x16"))
441 "Return a service that sets up Unicode support in @var{tty} and loads
442@var{font} for that tty (fonts are per virtual console in Linux.)"
443 ;; Note: 'LatGrkCyr-8x16' has the advantage of providing three common
444 ;; scripts as well as glyphs for em dash, quotation marks, and other Unicode
445 ;; codepoints notably found in the UTF-8 manual.
0adfe95a 446 (service console-font-service-type (list tty font)))
62ca0fdf 447
66e4f01c
LC
448(define-record-type* <mingetty-configuration>
449 mingetty-configuration make-mingetty-configuration
450 mingetty-configuration?
451 (mingetty mingetty-configuration-mingetty ;<package>
452 (default mingetty))
453 (tty mingetty-configuration-tty) ;string
454 (motd mingetty-configuration-motd ;file-like
455 (default (plain-file "motd" "Welcome.\n")))
456 (auto-login mingetty-auto-login ;string | #f
457 (default #f))
458 (login-program mingetty-login-program ;gexp
459 (default #f))
460 (login-pause? mingetty-login-pause? ;Boolean
461 (default #f))
462
463 ;; Allow empty passwords by default so that first-time users can log in when
464 ;; the 'root' account has just been created.
465 (allow-empty-passwords? mingetty-configuration-allow-empty-passwords?
466 (default #t))) ;Boolean
467
0adfe95a
LC
468(define (mingetty-pam-service conf)
469 "Return the list of PAM service needed for CONF."
470 ;; Let 'login' be known to PAM. All the mingetty services will have that
471 ;; PAM service, but that's fine because they're all identical and duplicates
472 ;; are removed.
473 (list (unix-pam-service "login"
474 #:allow-empty-passwords?
475 (mingetty-configuration-allow-empty-passwords? conf)
476 #:motd
477 (mingetty-configuration-motd conf))))
478
479(define mingetty-dmd-service
480 (match-lambda
66e4f01c
LC
481 (($ <mingetty-configuration> mingetty tty motd auto-login login-program
482 login-pause? allow-empty-passwords?)
0adfe95a
LC
483 (list
484 (dmd-service
485 (documentation "Run mingetty on an tty.")
486 (provision (list (symbol-append 'term- (string->symbol tty))))
487
488 ;; Since the login prompt shows the host name, wait for the 'host-name'
489 ;; service to be done. Also wait for udev essentially so that the tty
490 ;; text is not lost in the middle of kernel messages (XXX).
491 (requirement '(user-processes host-name udev))
492
493 (start #~(make-forkexec-constructor
494 (list (string-append #$mingetty "/sbin/mingetty")
495 "--noclear" #$tty
496 #$@(if auto-login
497 #~("--autologin" #$auto-login)
498 #~())
499 #$@(if login-program
500 #~("--loginprog" #$login-program)
501 #~())
502 #$@(if login-pause?
503 #~("--loginpause")
504 #~()))))
505 (stop #~(make-kill-destructor)))))))
506
507(define mingetty-service-type
508 (service-type (name 'mingetty)
509 (extensions (list (service-extension dmd-root-service-type
510 mingetty-dmd-service)
511 (service-extension pam-root-service-type
512 mingetty-pam-service)))))
513
514(define* (mingetty-service config)
515 "Return a service to run mingetty according to @var{config}, which specifies
516the tty to run, among other things."
517 (service mingetty-service-type config))
db4fdc04 518
6454b333
LC
519(define-record-type* <nscd-configuration> nscd-configuration
520 make-nscd-configuration
521 nscd-configuration?
522 (log-file nscd-configuration-log-file ;string
523 (default "/var/log/nscd.log"))
524 (debug-level nscd-debug-level ;integer
525 (default 0))
526 ;; TODO: See nscd.conf in glibc for other options to add.
527 (caches nscd-configuration-caches ;list of <nscd-cache>
b893f1ae
LC
528 (default %nscd-default-caches))
529 (name-services nscd-configuration-name-services ;list of <packages>
530 (default '()))
531 (glibc nscd-configuration-glibc ;<package>
532 (default (canonical-package glibc))))
6454b333
LC
533
534(define-record-type* <nscd-cache> nscd-cache make-nscd-cache
535 nscd-cache?
536 (database nscd-cache-database) ;symbol
537 (positive-time-to-live nscd-cache-positive-time-to-live) ;integer
538 (negative-time-to-live nscd-cache-negative-time-to-live
539 (default 20)) ;integer
540 (suggested-size nscd-cache-suggested-size ;integer ("default module
541 ;of hash table")
542 (default 211))
543 (check-files? nscd-cache-check-files? ;Boolean
544 (default #t))
545 (persistent? nscd-cache-persistent? ;Boolean
546 (default #t))
547 (shared? nscd-cache-shared? ;Boolean
548 (default #t))
549 (max-database-size nscd-cache-max-database-size ;integer
550 (default (* 32 (expt 2 20))))
551 (auto-propagate? nscd-cache-auto-propagate? ;Boolean
552 (default #t)))
553
554(define %nscd-default-caches
555 ;; Caches that we want to enable by default. Note that when providing an
556 ;; empty nscd.conf, all caches are disabled.
557 (list (nscd-cache (database 'hosts)
558
559 ;; Aggressively cache the host name cache to improve
560 ;; privacy and resilience.
561 (positive-time-to-live (* 3600 12))
562 (negative-time-to-live 20)
563 (persistent? #t))
564
565 (nscd-cache (database 'services)
566
567 ;; Services are unlikely to change, so we can be even more
568 ;; aggressive.
569 (positive-time-to-live (* 3600 24))
570 (negative-time-to-live 3600)
571 (check-files? #t) ;check /etc/services changes
572 (persistent? #t))))
573
574(define %nscd-default-configuration
575 ;; Default nscd configuration.
576 (nscd-configuration))
577
578(define (nscd.conf-file config)
579 "Return the @file{nscd.conf} configuration file for @var{config}, an
580@code{<nscd-configuration>} object."
581 (define cache->config
582 (match-lambda
be1c2c54
LC
583 (($ <nscd-cache> (= symbol->string database)
584 positive-ttl negative-ttl size check-files?
585 persistent? shared? max-size propagate?)
586 (string-append "\nenable-cache\t" database "\tyes\n"
587
588 "positive-time-to-live\t" database "\t"
589 (number->string positive-ttl) "\n"
590 "negative-time-to-live\t" database "\t"
591 (number->string negative-ttl) "\n"
592 "suggested-size\t" database "\t"
593 (number->string size) "\n"
594 "check-files\t" database "\t"
595 (if check-files? "yes\n" "no\n")
596 "persistent\t" database "\t"
597 (if persistent? "yes\n" "no\n")
598 "shared\t" database "\t"
599 (if shared? "yes\n" "no\n")
600 "max-db-size\t" database "\t"
601 (number->string max-size) "\n"
602 "auto-propagate\t" database "\t"
603 (if propagate? "yes\n" "no\n")))))
6454b333
LC
604
605 (match config
606 (($ <nscd-configuration> log-file debug-level caches)
be1c2c54
LC
607 (plain-file "nscd.conf"
608 (string-append "\
6454b333 609# Configuration of libc's name service cache daemon (nscd).\n\n"
be1c2c54
LC
610 (if log-file
611 (string-append "logfile\t" log-file)
612 "")
613 "\n"
614 (if debug-level
615 (string-append "debug-level\t"
616 (number->string debug-level))
617 "")
618 "\n"
619 (string-concatenate
620 (map cache->config caches)))))))
6454b333 621
0adfe95a
LC
622(define (nscd-dmd-service config)
623 "Return a dmd service for CONFIG, an <nscd-configuration> object."
624 (let ((nscd.conf (nscd.conf-file config))
625 (name-services (nscd-configuration-name-services config)))
626 (list (dmd-service
627 (documentation "Run libc's name service cache daemon (nscd).")
628 (provision '(nscd))
629 (requirement '(user-processes))
630 (start #~(make-forkexec-constructor
631 (list (string-append #$(nscd-configuration-glibc config)
632 "/sbin/nscd")
633 "-f" #$nscd.conf "--foreground")
634
635 #:environment-variables
636 (list (string-append "LD_LIBRARY_PATH="
637 (string-join
638 (map (lambda (dir)
639 (string-append dir "/lib"))
640 (list #$@name-services))
641 ":")))))
642 (stop #~(make-kill-destructor))
643
644 (respawn? #f)))))
645
646(define nscd-activation
647 ;; Actions to take before starting nscd.
648 #~(begin
649 (use-modules (guix build utils))
650 (mkdir-p "/var/run/nscd")
651 (mkdir-p "/var/db/nscd"))) ;for the persistent cache
652
653(define nscd-service-type
654 (service-type (name 'nscd)
655 (extensions
656 (list (service-extension activation-service-type
657 (const nscd-activation))
658 (service-extension dmd-root-service-type
659 nscd-dmd-service)))
660
661 ;; This can be extended by providing additional name services
662 ;; such as nss-mdns.
663 (compose concatenate)
664 (extend (lambda (config name-services)
665 (nscd-configuration
666 (inherit config)
667 (name-services (append
668 (nscd-configuration-name-services config)
669 name-services)))))))
670
b893f1ae 671(define* (nscd-service #:optional (config %nscd-default-configuration))
6454b333 672 "Return a service that runs libc's name service cache daemon (nscd) with the
b893f1ae
LC
673given @var{config}---an @code{<nscd-configuration>} object. @xref{Name
674Service Switch}, for an example."
0adfe95a
LC
675 (service nscd-service-type config))
676
677(define syslog-service-type
678 (dmd-service-type
00184239 679 'syslog
0adfe95a
LC
680 (lambda (config-file)
681 (dmd-service
682 (documentation "Run the syslog daemon (syslogd).")
683 (provision '(syslogd))
684 (requirement '(user-processes))
685 (start #~(make-forkexec-constructor
686 (list (string-append #$inetutils "/libexec/syslogd")
687 "--no-detach" "--rcfile" #$config-file)))
688 (stop #~(make-kill-destructor))))))
be1c2c54
LC
689
690;; Snippet adapted from the GNU inetutils manual.
691(define %default-syslog.conf
692 (plain-file "syslog.conf" "
1f3fc60d 693 # Log all error messages, authentication messages of
db4fdc04
LC
694 # level notice or higher and anything of level err or
695 # higher to the console.
696 # Don't log private authentication messages!
6a191274 697 *.alert;auth.notice;authpriv.none /dev/console
db4fdc04
LC
698
699 # Log anything (except mail) of level info or higher.
700 # Don't log private authentication messages!
701 *.info;mail.none;authpriv.none /var/log/messages
702
703 # Same, in a different place.
704 *.info;mail.none;authpriv.none /dev/tty12
705
706 # The authpriv file has restricted access.
707 authpriv.* /var/log/secure
708
709 # Log all the mail messages in one place.
710 mail.* /var/log/maillog
be1c2c54 711"))
0adfe95a 712
be1c2c54
LC
713(define* (syslog-service #:key (config-file %default-syslog.conf))
714 "Return a service that runs @code{syslogd}.
715If configuration file name @var{config-file} is not specified, use some
716reasonable default settings."
0adfe95a 717 (service syslog-service-type config-file))
db4fdc04 718
1c52181f
LC
719\f
720;;;
721;;; Guix services.
722;;;
723
db4fdc04 724(define* (guix-build-accounts count #:key
ab6a279a 725 (group "guixbuild")
db4fdc04 726 (first-uid 30001)
db4fdc04
LC
727 (shadow shadow))
728 "Return a list of COUNT user accounts for Guix build users, with UIDs
729starting at FIRST-UID, and under GID."
5250a4f2
LC
730 (unfold (cut > <> count)
731 (lambda (n)
732 (user-account
733 (name (format #f "guixbuilder~2,'0d" n))
734 (system? #t)
735 (uid (+ first-uid n -1))
736 (group group)
737
738 ;; guix-daemon expects GROUP to be listed as a
739 ;; supplementary group too:
740 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
741 (supplementary-groups (list group "kvm"))
742
743 (comment (format #f "Guix Build User ~2d" n))
744 (home-directory "/var/empty")
745 (shell #~(string-append #$shadow "/sbin/nologin"))))
746 1+
747 1))
db4fdc04 748
2c5c696c
LC
749(define (hydra-key-authorization guix)
750 "Return a gexp with code to register the hydra.gnu.org public key with
751GUIX."
752 #~(unless (file-exists? "/etc/guix/acl")
753 (let ((pid (primitive-fork)))
754 (case pid
755 ((0)
756 (let* ((key (string-append #$guix
757 "/share/guix/hydra.gnu.org.pub"))
758 (port (open-file key "r0b")))
759 (format #t "registering public key '~a'...~%" key)
760 (close-port (current-input-port))
2c5c696c
LC
761 (dup port 0)
762 (execl (string-append #$guix "/bin/guix")
763 "guix" "archive" "--authorize")
764 (exit 1)))
765 (else
766 (let ((status (cdr (waitpid pid))))
767 (unless (zero? status)
768 (format (current-error-port) "warning: \
769failed to register hydra.gnu.org public key: ~a~%" status))))))))
770
0adfe95a
LC
771(define-record-type* <guix-configuration>
772 guix-configuration make-guix-configuration
773 guix-configuration?
774 (guix guix-configuration-guix ;<package>
775 (default guix))
776 (build-group guix-configuration-build-group ;string
777 (default "guixbuild"))
778 (build-accounts guix-configuration-build-accounts ;integer
779 (default 10))
780 (authorize-key? guix-configuration-authorize-key? ;Boolean
781 (default #t))
782 (use-substitutes? guix-configuration-use-substitutes? ;Boolean
783 (default #t))
b0b9f6e0
LC
784 (substitute-urls guix-configuration-substitute-urls ;list of strings
785 (default %default-substitute-urls))
0adfe95a
LC
786 (extra-options guix-configuration-extra-options ;list of strings
787 (default '()))
788 (lsof guix-configuration-lsof ;<package>
789 (default lsof))
790 (lsh guix-configuration-lsh ;<package>
791 (default lsh)))
792
793(define %default-guix-configuration
794 (guix-configuration))
795
796(define (guix-dmd-service config)
797 "Return a <dmd-service> for the Guix daemon service with CONFIG."
798 (match config
799 (($ <guix-configuration> guix build-group build-accounts authorize-key?
b0b9f6e0
LC
800 use-substitutes? substitute-urls extra-options
801 lsof lsh)
0adfe95a
LC
802 (list (dmd-service
803 (documentation "Run the Guix daemon.")
804 (provision '(guix-daemon))
805 (requirement '(user-processes))
806 (start
807 #~(make-forkexec-constructor
808 (list (string-append #$guix "/bin/guix-daemon")
809 "--build-users-group" #$build-group
810 #$@(if use-substitutes?
811 '()
812 '("--no-substitutes"))
b0b9f6e0 813 "--substitute-urls" #$(string-join substitute-urls)
0adfe95a
LC
814 #$@extra-options)
815
816 ;; Add 'lsof' (for the GC) and 'lsh' (for offloading) to the
817 ;; daemon's $PATH.
818 #:environment-variables
819 (list (string-append "PATH=" #$lsof "/bin:" #$lsh "/bin"))))
820 (stop #~(make-kill-destructor)))))))
821
822(define (guix-accounts config)
823 "Return the user accounts and user groups for CONFIG."
824 (match config
825 (($ <guix-configuration> _ build-group build-accounts)
826 (cons (user-group
827 (name build-group)
828 (system? #t)
829
830 ;; Use a fixed GID so that we can create the store with the right
831 ;; owner.
832 (id 30000))
833 (guix-build-accounts build-accounts
834 #:group build-group)))))
835
836(define (guix-activation config)
837 "Return the activation gexp for CONFIG."
838 (match config
839 (($ <guix-configuration> guix build-group build-accounts authorize-key?)
840 ;; Assume that the store has BUILD-GROUP as its group. We could
841 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
842 ;; chown leads to an entire copy of the tree, which is a bad idea.
843
844 ;; Optionally authorize hydra.gnu.org's key.
845 (and authorize-key?
846 (hydra-key-authorization guix)))))
847
848(define guix-service-type
849 (service-type
850 (name 'guix)
851 (extensions
852 (list (service-extension dmd-root-service-type guix-dmd-service)
853 (service-extension account-service-type guix-accounts)
854 (service-extension activation-service-type guix-activation)))))
855
856(define* (guix-service #:optional (config %default-guix-configuration))
857 "Return a service that runs the Guix build daemon according to
858@var{config}."
859 (service guix-service-type config))
860
1c52181f
LC
861
862(define-record-type* <guix-publish-configuration>
863 guix-publish-configuration make-guix-publish-configuration
864 guix-publish-configuration?
865 (guix guix-publish-configuration-guix ;package
866 (default guix))
867 (port guix-publish-configuration-port ;number
868 (default 80))
869 (host guix-publish-configuration-host ;string
870 (default "localhost")))
871
872(define guix-publish-dmd-service
873 (match-lambda
874 (($ <guix-publish-configuration> guix port host)
875 (list (dmd-service
876 (provision '(guix-publish))
877 (requirement '(guix-daemon))
878 (start #~(make-forkexec-constructor
879 (list (string-append #$guix "/bin/guix")
880 "publish" "-u" "guix-publish"
881 "-p" #$(number->string port)
882 (string-append "--listen=" #$host))))
883 (stop #~(make-kill-destructor)))))))
884
885(define %guix-publish-accounts
886 (list (user-group (name "guix-publish") (system? #t))
887 (user-account
888 (name "guix-publish")
889 (group "guix-publish")
890 (system? #t)
891 (comment "guix publish user")
892 (home-directory "/var/empty")
893 (shell #~(string-append #$shadow "/sbin/nologin")))))
894
895(define guix-publish-service-type
896 (service-type (name 'guix-publish)
897 (extensions
898 (list (service-extension dmd-root-service-type
899 guix-publish-dmd-service)
900 (service-extension account-service-type
901 (const %guix-publish-accounts))))))
902
903(define* (guix-publish-service #:key (guix guix) (port 80) (host "localhost"))
904 "Return a service that runs @command{guix publish} listening on @var{host}
905and @var{port} (@pxref{Invoking guix publish}).
906
907This assumes that @file{/etc/guix} already contains a signing key pair as
908created by @command{guix archive --generate-key} (@pxref{Invoking guix
909archive}). If that is not the case, the service will fail to start."
910 (service guix-publish-service-type
911 (guix-publish-configuration (guix guix) (port port) (host host))))
912
0adfe95a
LC
913\f
914;;;
915;;; Udev.
916;;;
917
918(define-record-type* <udev-configuration>
919 udev-configuration make-udev-configuration
920 udev-configuration?
921 (udev udev-configuration-udev ;<package>
922 (default udev))
923 (rules udev-configuration-rules ;list of <package>
924 (default '())))
db4fdc04 925
ecd06ca9
LC
926(define (udev-rules-union packages)
927 "Return the union of the @code{lib/udev/rules.d} directories found in each
928item of @var{packages}."
929 (define build
930 #~(begin
931 (use-modules (guix build union)
932 (guix build utils)
933 (srfi srfi-1)
934 (srfi srfi-26))
935
936 (define %standard-locations
937 '("/lib/udev/rules.d" "/libexec/udev/rules.d"))
938
939 (define (rules-sub-directory directory)
940 ;; Return the sub-directory of DIRECTORY containing udev rules, or
941 ;; #f if none was found.
942 (find directory-exists?
943 (map (cut string-append directory <>) %standard-locations)))
944
945 (mkdir-p (string-append #$output "/lib/udev"))
946 (union-build (string-append #$output "/lib/udev/rules.d")
947 (filter-map rules-sub-directory '#$packages))))
948
be1c2c54
LC
949 (computed-file "udev-rules" build
950 #:modules '((guix build union)
951 (guix build utils))))
ecd06ca9 952
80e6f37e
RW
953(define (udev-rule file-name contents)
954 "Return a directory with a udev rule file FILE-NAME containing CONTENTS."
955 (computed-file file-name
be1c2c54
LC
956 #~(begin
957 (use-modules (guix build utils))
958
959 (define rules.d
960 (string-append #$output "/lib/udev/rules.d"))
961
962 (mkdir-p rules.d)
963 (call-with-output-file
80e6f37e 964 (string-append rules.d "/" #$file-name)
be1c2c54 965 (lambda (port)
80e6f37e 966 (display #$contents port))))
be1c2c54 967 #:modules '((guix build utils))))
7f28bf9a 968
80e6f37e
RW
969(define kvm-udev-rule
970 ;; Return a directory with a udev rule that changes the group of /dev/kvm to
971 ;; "kvm" and makes it #o660. Apparently QEMU-KVM used to ship this rule,
972 ;; but now we have to add it by ourselves.
973
974 ;; Build users are part of the "kvm" group, so we can fearlessly make
975 ;; /dev/kvm 660 (see <http://bugs.gnu.org/18994>, for background.)
976 (udev-rule "90-kvm.rules"
977 "KERNEL==\"kvm\", GROUP=\"kvm\", MODE=\"0660\"\n"))
978
0adfe95a
LC
979(define udev-dmd-service
980 ;; Return a <dmd-service> for UDEV with RULES.
981 (match-lambda
982 (($ <udev-configuration> udev rules)
80e6f37e 983 (let* ((rules (udev-rules-union (cons* udev kvm-udev-rule rules)))
0adfe95a
LC
984 (udev.conf (computed-file "udev.conf"
985 #~(call-with-output-file #$output
986 (lambda (port)
987 (format port
988 "udev_rules=\"~a/lib/udev/rules.d\"\n"
989 #$rules))))))
990 (list
991 (dmd-service
992 (provision '(udev))
993
994 ;; Udev needs /dev to be a 'devtmpfs' mount so that new device nodes can
995 ;; be added: see
996 ;; <http://www.linuxfromscratch.org/lfs/view/development/chapter07/udev.html>.
997 (requirement '(root-file-system))
998
999 (documentation "Populate the /dev directory, dynamically.")
1000 (start #~(lambda ()
1001 (define find
1002 (@ (srfi srfi-1) find))
1003
1004 (define udevd
1005 ;; Choose the right 'udevd'.
1006 (find file-exists?
1007 (map (lambda (suffix)
1008 (string-append #$udev suffix))
1009 '("/libexec/udev/udevd" ;udev
1010 "/sbin/udevd")))) ;eudev
1011
1012 (define (wait-for-udevd)
1013 ;; Wait until someone's listening on udevd's control
1014 ;; socket.
1015 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
1016 (let try ()
1017 (catch 'system-error
1018 (lambda ()
1019 (connect sock PF_UNIX "/run/udev/control")
1020 (close-port sock))
1021 (lambda args
1022 (format #t "waiting for udevd...~%")
1023 (usleep 500000)
1024 (try))))))
1025
1026 ;; Allow udev to find the modules.
1027 (setenv "LINUX_MODULE_DIRECTORY"
1028 "/run/booted-system/kernel/lib/modules")
1029
1030 ;; The first one is for udev, the second one for eudev.
1031 (setenv "UDEV_CONFIG_FILE" #$udev.conf)
1032 (setenv "EUDEV_RULES_DIRECTORY"
1033 (string-append #$rules "/lib/udev/rules.d"))
1034
1035 (let ((pid (primitive-fork)))
1036 (case pid
1037 ((0)
1038 (exec-command (list udevd)))
1039 (else
1040 ;; Wait until udevd is up and running. This
1041 ;; appears to be needed so that the events
1042 ;; triggered below are actually handled.
1043 (wait-for-udevd)
1044
1045 ;; Trigger device node creation.
1046 (system* (string-append #$udev "/bin/udevadm")
1047 "trigger" "--action=add")
1048
1049 ;; Wait for things to settle down.
1050 (system* (string-append #$udev "/bin/udevadm")
1051 "settle")
1052 pid)))))
1053 (stop #~(make-kill-destructor))
1054
1055 ;; When halting the system, 'udev' is actually killed by
1056 ;; 'user-processes', i.e., before its own 'stop' method was called.
1057 ;; Thus, make sure it is not respawned.
1058 (respawn? #f)))))))
1059
1060(define udev-service-type
1061 (service-type (name 'udev)
1062 (extensions
1063 (list (service-extension dmd-root-service-type
1064 udev-dmd-service)))
1065
1066 (compose concatenate) ;concatenate the list of rules
1067 (extend (lambda (config rules)
1068 (match config
1069 (($ <udev-configuration> udev initial-rules)
1070 (udev-configuration
1071 (udev udev)
1072 (rules (append initial-rules rules)))))))))
1073
8a7330fd 1074(define* (udev-service #:key (udev eudev) (rules '()))
ecd06ca9
LC
1075 "Run @var{udev}, which populates the @file{/dev} directory dynamically. Get
1076extra rules from the packages listed in @var{rules}."
0adfe95a
LC
1077 (service udev-service-type
1078 (udev-configuration (udev udev) (rules rules))))
1079
1080(define device-mapping-service-type
1081 (dmd-service-type
00184239 1082 'device-mapping
0adfe95a
LC
1083 (match-lambda
1084 ((target open close)
1085 (dmd-service
1086 (provision (list (symbol-append 'device-mapping- (string->symbol target))))
1087 (requirement '(udev))
1088 (documentation "Map a device node using Linux's device mapper.")
1089 (start #~(lambda () #$open))
1090 (stop #~(lambda _ (not #$close)))
1091 (respawn? #f))))))
151a2c07 1092
722554a3 1093(define (device-mapping-service target open close)
5dae0186 1094 "Return a service that maps device @var{target}, a string such as
722554a3
LC
1095@code{\"home\"} (meaning @code{/dev/mapper/home}). Evaluate @var{open}, a
1096gexp, to open it, and evaluate @var{close} to close it."
0adfe95a
LC
1097 (service device-mapping-service-type
1098 (list target open close)))
1099
1100(define swap-service-type
1101 (dmd-service-type
00184239 1102 'swap
0adfe95a
LC
1103 (lambda (device)
1104 (define requirement
1105 (if (string-prefix? "/dev/mapper/" device)
1106 (list (symbol-append 'device-mapping-
1107 (string->symbol (basename device))))
1108 '()))
1109
1110 (dmd-service
1111 (provision (list (symbol-append 'swap- (string->symbol device))))
1112 (requirement `(udev ,@requirement))
1113 (documentation "Enable the given swap device.")
1114 (start #~(lambda ()
1115 (restart-on-EINTR (swapon #$device))
1116 #t))
1117 (stop #~(lambda _
1118 (restart-on-EINTR (swapoff #$device))
1119 #f))
1120 (respawn? #f)))))
5dae0186 1121
2a13d05e
LC
1122(define (swap-service device)
1123 "Return a service that uses @var{device} as a swap device."
0adfe95a 1124 (service swap-service-type device))
2a13d05e 1125
8664cc88
LC
1126
1127(define-record-type* <gpm-configuration>
1128 gpm-configuration make-gpm-configuration gpm-configuration?
1129 (gpm gpm-configuration-gpm) ;package
1130 (options gpm-configuration-options)) ;list of strings
1131
1132(define gpm-dmd-service
1133 (match-lambda
1134 (($ <gpm-configuration> dmd options)
1135 (list (dmd-service
1136 (requirement '(udev))
1137 (provision '(gpm))
1138 (start #~(lambda ()
1139 ;; 'gpm' runs in the background and sets a PID file.
1140 ;; Note that it requires running as "root".
1141 (false-if-exception (delete-file "/var/run/gpm.pid"))
1142 (fork+exec-command (list (string-append #$gpm "/sbin/gpm")
1143 #$@options))
1144
1145 ;; Wait for the PID file to appear; declare failure if
1146 ;; it doesn't show up.
1147 (let loop ((i 3))
1148 (or (file-exists? "/var/run/gpm.pid")
1149 (if (zero? i)
1150 #f
1151 (begin
1152 (sleep 1)
1153 (loop (1- i))))))))
1154
1155 (stop #~(lambda (_)
1156 ;; Return #f if successfully stopped.
1157 (not (zero? (system* (string-append #$gpm "/sbin/gpm")
1158 "-k"))))))))))
1159
1160(define gpm-service-type
1161 (service-type (name 'gpm)
1162 (extensions
1163 (list (service-extension dmd-root-service-type
1164 gpm-dmd-service)))))
1165
1166(define* (gpm-service #:key (gpm gpm)
1167 (options '("-m" "/dev/input/mice" "-t" "ps2")))
1168 "Run @var{gpm}, the general-purpose mouse daemon, with the given
1169command-line @var{options}. GPM allows users to use the mouse in the console,
1170notably to select, copy, and paste text. The default value of @var{options}
1171uses the @code{ps2} protocol, which works for both USB and PS/2 mice.
1172
1173This service is not part of @var{%base-services}."
1174 ;; To test in QEMU, use "-usbdevice mouse" and then, in the monitor, use
1175 ;; "info mice" and "mouse_set X" to use the right mouse.
1176 (service gpm-service-type
1177 (gpm-configuration (gpm gpm) (options options))))
1178
1179\f
8b198abe
LC
1180(define %base-services
1181 ;; Convenience variable holding the basic services.
ce8a6dfc 1182 (let ((motd (plain-file "motd" "
8b198abe 1183This is the GNU operating system, welcome!\n\n")))
62ca0fdf
LC
1184 (list (console-font-service "tty1")
1185 (console-font-service "tty2")
1186 (console-font-service "tty3")
1187 (console-font-service "tty4")
1188 (console-font-service "tty5")
1189 (console-font-service "tty6")
1190
66e4f01c
LC
1191 (mingetty-service (mingetty-configuration
1192 (tty "tty1") (motd motd)))
1193 (mingetty-service (mingetty-configuration
1194 (tty "tty2") (motd motd)))
1195 (mingetty-service (mingetty-configuration
1196 (tty "tty3") (motd motd)))
1197 (mingetty-service (mingetty-configuration
1198 (tty "tty4") (motd motd)))
1199 (mingetty-service (mingetty-configuration
1200 (tty "tty5") (motd motd)))
1201 (mingetty-service (mingetty-configuration
1202 (tty "tty6") (motd motd)))
1203
4a3b3b07
LC
1204 (static-networking-service "lo" "127.0.0.1"
1205 #:provision '(loopback))
8b198abe
LC
1206 (syslog-service)
1207 (guix-service)
151a2c07 1208 (nscd-service)
ecd06ca9 1209
52bd5734
LC
1210 ;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
1211 ;; used, so enable them by default. The FUSE and ALSA rules are
1212 ;; less critical, but handy.
68ac258b 1213 (udev-service #:rules (list lvm2 fuse alsa-utils crda)))))
8b198abe 1214
db4fdc04 1215;;; base.scm ends here