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