system: Remove erroneous system binding in profile maker.
[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
LC
22 #:use-module (gnu services)
23 #:use-module (gnu system shadow) ; 'user-account', etc.
24 #:use-module (gnu system linux) ; 'pam-service', etc.
25 #:use-module (gnu packages admin)
151a2c07
LC
26 #:use-module ((gnu packages linux)
27 #:select (udev))
db4fdc04 28 #:use-module ((gnu packages base)
23ed63a1 29 #:select (glibc-final))
db4fdc04 30 #:use-module (gnu packages package-management)
b5f4e686 31 #:use-module (guix gexp)
db4fdc04
LC
32 #:use-module (guix monads)
33 #:use-module (srfi srfi-1)
34 #:use-module (srfi srfi-26)
35 #:use-module (ice-9 format)
a00dd9fb 36 #:export (root-file-system-service
023f391c 37 file-system-service
a00dd9fb
LC
38 user-processes-service
39 host-name-service
151a2c07 40 udev-service
db4fdc04
LC
41 mingetty-service
42 nscd-service
43 syslog-service
8b198abe
LC
44 guix-service
45 %base-services))
db4fdc04
LC
46
47;;; Commentary:
48;;;
49;;; Base system services---i.e., services that 99% of the users will want to
50;;; use.
51;;;
52;;; Code:
53
a00dd9fb
LC
54(define (root-file-system-service)
55 "Return a service whose sole purpose is to re-mount read-only the root file
56system upon shutdown (aka. cleanly \"umounting\" root.)
57
58This service must be the root of the service dependency graph so that its
59'stop' action is invoked when dmd is the only process left."
a00dd9fb
LC
60 (with-monad %store-monad
61 (return
62 (service
63 (documentation "Take care of the root file system.")
64 (provision '(root-file-system))
65 (start #~(const #t))
66 (stop #~(lambda _
67 ;; Return #f if successfully stopped.
23ed63a1 68 (sync)
a00dd9fb
LC
69
70 (call-with-blocked-asyncs
71 (lambda ()
72 (let ((null (%make-void-port "w")))
73 ;; Close 'dmd.log'.
74 (display "closing log\n")
75 ;; XXX: Ideally we'd use 'stop-logging', but that one
76 ;; doesn't actually close the port as of dmd 0.1.
77 (close-port (@@ (dmd comm) log-output-port))
78 (set! (@@ (dmd comm) log-output-port) null)
79
80 ;; Redirect the default output ports..
81 (set-current-output-port null)
82 (set-current-error-port null)
83
84 ;; Close /dev/console.
85 (for-each close-fdes '(0 1 2))
86
23ed63a1 87 ;; At this point, there are no open files left, so the
a00dd9fb 88 ;; root file system can be re-mounted read-only.
23ed63a1
LC
89 (mount #f "/" #f
90 (logior MS_REMOUNT MS_RDONLY)
91 #:update-mtab? #f)
92
93 #f)))))
a00dd9fb
LC
94 (respawn? #f)))))
95
023f391c 96(define* (file-system-service device target type
d4c87617 97 #:key (check? #t) options (title 'any))
023f391c 98 "Return a service that mounts DEVICE on TARGET as a file system TYPE with
d4c87617
LC
99OPTIONS. TITLE is a symbol specifying what kind of name DEVICE is: 'label for
100a partition label, 'device for a device file name, or 'any. When CHECK? is
101true, check the file system before mounting it."
023f391c
LC
102 (with-monad %store-monad
103 (return
104 (service
105 (provision (list (symbol-append 'file-system- (string->symbol target))))
106 (requirement '(root-file-system))
107 (documentation "Check, mount, and unmount the given file system.")
108 (start #~(lambda args
d4c87617
LC
109 (let ((device (canonicalize-device-spec #$device '#$title)))
110 #$(if check?
111 #~(check-file-system device #$type)
112 #~#t)
113 (mount device #$target #$type 0 #$options))
023f391c
LC
114 #t))
115 (stop #~(lambda args
116 ;; Normally there are no processes left at this point, so
117 ;; TARGET can be safely unmounted.
118 (umount #$target)
119 #f))))))
120
7d57cfd3
LC
121(define %do-not-kill-file
122 ;; Name of the file listing PIDs of processes that must survive when halting
123 ;; the system. Typical example is user-space file systems.
124 "/etc/dmd/do-not-kill")
125
023f391c 126(define* (user-processes-service requirements #:key (grace-delay 2))
a00dd9fb
LC
127 "Return the service that is responsible for terminating all the processes so
128that the root file system can be re-mounted read-only, just before
129rebooting/halting. Processes still running GRACE-DELAY seconds after SIGTERM
130has been sent are terminated with SIGKILL.
131
023f391c
LC
132The returned service will depend on 'root-file-system' and on all the services
133listed in REQUIREMENTS.
134
a00dd9fb
LC
135All the services that spawn processes must depend on this one so that they are
136stopped before 'kill' is called."
137 (with-monad %store-monad
138 (return (service
139 (documentation "When stopped, terminate all user processes.")
140 (provision '(user-processes))
023f391c 141 (requirement (cons 'root-file-system requirements))
a00dd9fb
LC
142 (start #~(const #t))
143 (stop #~(lambda _
7d57cfd3
LC
144 (define (kill-except omit signal)
145 ;; Kill all the processes with SIGNAL except those
146 ;; listed in OMIT and the current process.
147 (let ((omit (cons (getpid) omit)))
148 (for-each (lambda (pid)
149 (unless (memv pid omit)
150 (false-if-exception
151 (kill pid signal))))
152 (processes))))
153
154 (define omitted-pids
155 ;; List of PIDs that must not be killed.
156 (if (file-exists? #$%do-not-kill-file)
157 (map string->number
158 (call-with-input-file #$%do-not-kill-file
159 (compose string-tokenize
160 (@ (ice-9 rdelim) read-string))))
161 '()))
162
a00dd9fb
LC
163 ;; When this happens, all the processes have been
164 ;; killed, including 'deco', so DMD-OUTPUT-PORT and
165 ;; thus CURRENT-OUTPUT-PORT are dangling.
166 (call-with-output-file "/dev/console"
167 (lambda (port)
168 (display "sending all processes the TERM signal\n"
169 port)))
170
7d57cfd3
LC
171 (if (null? omitted-pids)
172 (begin
173 ;; Easy: terminate all of them.
174 (kill -1 SIGTERM)
175 (sleep #$grace-delay)
176 (kill -1 SIGKILL))
177 (begin
178 ;; Kill them all except OMITTED-PIDS. XXX: We
179 ;; would like to (kill -1 SIGSTOP) to get a fixed
180 ;; list of processes, like 'killall5' does, but
181 ;; that seems unreliable.
182 (kill-except omitted-pids SIGTERM)
183 (sleep #$grace-delay)
184 (kill-except omitted-pids SIGKILL)
185 (delete-file #$%do-not-kill-file)))
a00dd9fb
LC
186
187 (display "all processes have been terminated\n")
188 #f))
189 (respawn? #f)))))
190
db4fdc04 191(define (host-name-service name)
51da7ca0 192 "Return a service that sets the host name to @var{name}."
db4fdc04
LC
193 (with-monad %store-monad
194 (return (service
195 (documentation "Initialize the machine's host name.")
196 (provision '(host-name))
b5f4e686
LC
197 (start #~(lambda _
198 (sethostname #$name)))
db4fdc04
LC
199 (respawn? #f)))))
200
201(define* (mingetty-service tty
202 #:key
203 (motd (text-file "motd" "Welcome.\n"))
52322163
LC
204 auto-login
205 login-program
206 login-pause?
51da7ca0
LC
207
208 ;; Allow empty passwords by default so that
209 ;; first-time users can log in when the 'root'
210 ;; account has just been created.
db4fdc04 211 (allow-empty-passwords? #t))
52322163
LC
212 "Return a service to run mingetty on @var{tty}.
213
214When @var{allow-empty-passwords?} is true, allow empty log-in password. When
215@var{auto-login} is true, it must be a user name under which to log-in
216automatically. @var{login-pause?} can be set to @code{#t} in conjunction with
217@var{auto-login}, in which case the user will have to press a key before the
218login shell is launched.
219
220When true, @var{login-program} is a gexp or a monadic gexp denoting the name
221of the log-in program (the default is the @code{login} program from the Shadow
222tool suite.)
223
224@var{motd} is a monadic value containing a text file to use as
51da7ca0 225the ``message of the day''."
52322163
LC
226 (mlet %store-monad ((motd motd)
227 (login-program (cond ((gexp? login-program)
228 (return login-program))
229 ((not login-program)
230 (return #f))
231 (else
232 login-program))))
db4fdc04
LC
233 (return
234 (service
235 (documentation (string-append "Run mingetty on " tty "."))
236 (provision (list (symbol-append 'term- (string->symbol tty))))
237
238 ;; Since the login prompt shows the host name, wait for the 'host-name'
239 ;; service to be done.
a00dd9fb 240 (requirement '(user-processes host-name))
db4fdc04 241
b5f4e686 242 (start #~(make-forkexec-constructor
1c6b445b
LC
243 (list (string-append #$mingetty "/sbin/mingetty")
244 "--noclear" #$tty
245 #$@(if auto-login
246 #~("--autologin" #$auto-login)
247 #~())
248 #$@(if login-program
249 #~("--loginprog" #$login-program)
250 #~())
251 #$@(if login-pause?
252 #~("--loginpause")
253 #~()))))
b5f4e686 254 (stop #~(make-kill-destructor))
db4fdc04
LC
255
256 (pam-services
257 ;; Let 'login' be known to PAM. All the mingetty services will have
258 ;; that PAM service, but that's fine because they're all identical and
259 ;; duplicates are removed.
260 (list (unix-pam-service "login"
261 #:allow-empty-passwords? allow-empty-passwords?
262 #:motd motd)))))))
263
264(define* (nscd-service #:key (glibc glibc-final))
265 "Return a service that runs libc's name service cache daemon (nscd)."
b5f4e686 266 (with-monad %store-monad
db4fdc04
LC
267 (return (service
268 (documentation "Run libc's name service cache daemon (nscd).")
269 (provision '(nscd))
a00dd9fb 270 (requirement '(user-processes))
4b2615e1
LC
271
272 (activate #~(begin
273 (use-modules (guix build utils))
274 (mkdir-p "/var/run/nscd")))
275
1c6b445b
LC
276 (start #~(make-forkexec-constructor
277 (list (string-append #$glibc "/sbin/nscd")
278 "-f" "/dev/null" "--foreground")))
b5f4e686 279 (stop #~(make-kill-destructor))
db4fdc04 280
b5f4e686 281 (respawn? #f)))))
db4fdc04
LC
282
283(define (syslog-service)
51da7ca0 284 "Return a service that runs @code{syslogd} with reasonable default settings."
db4fdc04
LC
285
286 ;; Snippet adapted from the GNU inetutils manual.
287 (define contents "
1f3fc60d 288 # Log all error messages, authentication messages of
db4fdc04
LC
289 # level notice or higher and anything of level err or
290 # higher to the console.
291 # Don't log private authentication messages!
1f3fc60d 292 *.err;auth.notice;authpriv.none /dev/console
db4fdc04
LC
293
294 # Log anything (except mail) of level info or higher.
295 # Don't log private authentication messages!
296 *.info;mail.none;authpriv.none /var/log/messages
297
298 # Same, in a different place.
299 *.info;mail.none;authpriv.none /dev/tty12
300
301 # The authpriv file has restricted access.
302 authpriv.* /var/log/secure
303
304 # Log all the mail messages in one place.
305 mail.* /var/log/maillog
306")
307
308 (mlet %store-monad
b5f4e686 309 ((syslog.conf (text-file "syslog.conf" contents)))
db4fdc04
LC
310 (return
311 (service
312 (documentation "Run the syslog daemon (syslogd).")
313 (provision '(syslogd))
a00dd9fb 314 (requirement '(user-processes))
b5f4e686 315 (start
1c6b445b
LC
316 #~(make-forkexec-constructor
317 (list (string-append #$inetutils "/libexec/syslogd")
318 "--no-detach" "--rcfile" #$syslog.conf)))
b5f4e686 319 (stop #~(make-kill-destructor))))))
db4fdc04
LC
320
321(define* (guix-build-accounts count #:key
ab6a279a 322 (group "guixbuild")
db4fdc04 323 (first-uid 30001)
db4fdc04
LC
324 (shadow shadow))
325 "Return a list of COUNT user accounts for Guix build users, with UIDs
326starting at FIRST-UID, and under GID."
327 (with-monad %store-monad
328 (return (unfold (cut > <> count)
329 (lambda (n)
330 (user-account
331 (name (format #f "guixbuilder~2,'0d" n))
459dd9ea 332 (system? #t)
db4fdc04 333 (uid (+ first-uid n -1))
ab6a279a 334 (group group)
3d116a70
LC
335
336 ;; guix-daemon expects GROUP to be listed as a
337 ;; supplementary group too:
338 ;; <http://lists.gnu.org/archive/html/bug-guix/2013-01/msg00239.html>.
339 (supplementary-groups (list group))
340
db4fdc04
LC
341 (comment (format #f "Guix Build User ~2d" n))
342 (home-directory "/var/empty")
b5f4e686 343 (shell #~(string-append #$shadow "/sbin/nologin"))))
db4fdc04
LC
344 1+
345 1))))
346
2c5c696c
LC
347(define (hydra-key-authorization guix)
348 "Return a gexp with code to register the hydra.gnu.org public key with
349GUIX."
350 #~(unless (file-exists? "/etc/guix/acl")
351 (let ((pid (primitive-fork)))
352 (case pid
353 ((0)
354 (let* ((key (string-append #$guix
355 "/share/guix/hydra.gnu.org.pub"))
356 (port (open-file key "r0b")))
357 (format #t "registering public key '~a'...~%" key)
358 (close-port (current-input-port))
2c5c696c
LC
359 (dup port 0)
360 (execl (string-append #$guix "/bin/guix")
361 "guix" "archive" "--authorize")
362 (exit 1)))
363 (else
364 (let ((status (cdr (waitpid pid))))
365 (unless (zero? status)
366 (format (current-error-port) "warning: \
367failed to register hydra.gnu.org public key: ~a~%" status))))))))
368
db4fdc04 369(define* (guix-service #:key (guix guix) (builder-group "guixbuild")
2c5c696c 370 (build-accounts 10) authorize-hydra-key?)
51da7ca0
LC
371 "Return a service that runs the build daemon from @var{guix}, and has
372@var{build-accounts} user accounts available under @var{builder-group}.
2c5c696c 373
51da7ca0
LC
374When @var{authorize-hydra-key?} is true, the @code{hydra.gnu.org} public key
375provided by @var{guix} is authorized upon activation, meaning that substitutes
376from @code{hydra.gnu.org} are used by default."
185f6691 377 (define activate
e97c5be9
LC
378 ;; Assume that the store has BUILDER-GROUP as its group. We could
379 ;; otherwise call 'chown' here, but the problem is that on a COW unionfs,
380 ;; chown leads to an entire copy of the tree, which is a bad idea.
185f6691 381
e97c5be9
LC
382 ;; Optionally authorize hydra.gnu.org's key.
383 (and authorize-hydra-key?
384 (hydra-key-authorization guix)))
185f6691 385
b5f4e686 386 (mlet %store-monad ((accounts (guix-build-accounts build-accounts
ab6a279a 387 #:group builder-group)))
db4fdc04
LC
388 (return (service
389 (provision '(guix-daemon))
a00dd9fb 390 (requirement '(user-processes))
b5f4e686 391 (start
1c6b445b
LC
392 #~(make-forkexec-constructor
393 (list (string-append #$guix "/bin/guix-daemon")
394 "--build-users-group" #$builder-group)))
b5f4e686 395 (stop #~(make-kill-destructor))
db4fdc04
LC
396 (user-accounts accounts)
397 (user-groups (list (user-group
398 (name builder-group)
e97c5be9
LC
399
400 ;; Use a fixed GID so that we can create the
401 ;; store with the right owner.
402 (id 30000))))
185f6691 403 (activate activate)))))
db4fdc04 404
151a2c07
LC
405(define* (udev-service #:key (udev udev))
406 "Run @var{udev}, which populates the @file{/dev} directory dynamically."
407 (with-monad %store-monad
408 (return (service
409 (provision '(udev))
410 (requirement '(root-file-system))
411 (documentation "Populate the /dev directory.")
412 (start #~(lambda ()
1c6b445b
LC
413 (define udevd
414 (string-append #$udev "/libexec/udev/udevd"))
415
ed09bb11
LC
416 (define (wait-for-udevd)
417 ;; Wait until someone's listening on udevd's control
418 ;; socket.
419 (let ((sock (socket AF_UNIX SOCK_SEQPACKET 0)))
420 (let try ()
421 (catch 'system-error
422 (lambda ()
423 (connect sock PF_UNIX "/run/udev/control")
424 (close-port sock))
425 (lambda args
426 (format #t "waiting for udevd...~%")
427 (usleep 500000)
428 (try))))))
429
081c5b2d
LC
430 ;; Allow udev to find the modules.
431 (setenv "LINUX_MODULE_DIRECTORY"
432 "/run/booted-system/kernel/lib/modules")
433
151a2c07
LC
434 (let ((pid (primitive-fork)))
435 (case pid
436 ((0)
1c6b445b 437 (exec-command (list udevd)))
151a2c07 438 (else
ed09bb11
LC
439 ;; Wait until udevd is up and running. This
440 ;; appears to be needed so that the events
441 ;; triggered below are actually handled.
442 (wait-for-udevd)
443
444 ;; Trigger device node creation.
445 (system* (string-append #$udev "/bin/udevadm")
446 "trigger" "--action=add")
447
081c5b2d
LC
448 ;; Wait for things to settle down.
449 (system* (string-append #$udev "/bin/udevadm")
450 "settle")
151a2c07
LC
451 pid)))))
452 (stop #~(make-kill-destructor))))))
453
8b198abe
LC
454(define %base-services
455 ;; Convenience variable holding the basic services.
456 (let ((motd (text-file "motd" "
457This is the GNU operating system, welcome!\n\n")))
458 (list (mingetty-service "tty1" #:motd motd)
459 (mingetty-service "tty2" #:motd motd)
460 (mingetty-service "tty3" #:motd motd)
461 (mingetty-service "tty4" #:motd motd)
462 (mingetty-service "tty5" #:motd motd)
463 (mingetty-service "tty6" #:motd motd)
464 (syslog-service)
465 (guix-service)
151a2c07
LC
466 (nscd-service)
467 (udev-service))))
8b198abe 468
db4fdc04 469;;; base.scm ends here