system: image: Make sure target is set.
[jackhill/guix/guix.git] / gnu / services / shepherd.scm
CommitLineData
db4fdc04 1;;; GNU Guix --- Functional package management for GNU
8b9cad01 2;;; Copyright © 2013, 2014, 2015, 2016, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
750a4239 3;;; Copyright © 2017 Clément Lassieur <clement@lassieur.org>
4245ddcb 4;;; Copyright © 2018 Carlo Zancanaro <carlo@zancanaro.id.au>
d2fc7646 5;;; Copyright © 2020 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
db4fdc04
LC
6;;;
7;;; This file is part of GNU Guix.
8;;;
9;;; GNU Guix is free software; you can redistribute it and/or modify it
10;;; under the terms of the GNU General Public License as published by
11;;; the Free Software Foundation; either version 3 of the License, or (at
12;;; your option) any later version.
13;;;
14;;; GNU Guix is distributed in the hope that it will be useful, but
15;;; WITHOUT ANY WARRANTY; without even the implied warranty of
16;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;;; GNU General Public License for more details.
18;;;
19;;; You should have received a copy of the GNU General Public License
20;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21
0190c1c0 22(define-module (gnu services shepherd)
116244df
LC
23 #:use-module (guix ui)
24 #:use-module (guix sets)
b5f4e686 25 #:use-module (guix gexp)
e87f0591 26 #:use-module (guix store)
0adfe95a 27 #:use-module (guix records)
e87f0591 28 #:use-module (guix derivations) ;imported-modules, etc.
d2fc7646 29 #:use-module (guix utils)
db4fdc04 30 #:use-module (gnu services)
7b44cae5 31 #:use-module (gnu services herd)
0adfe95a 32 #:use-module (gnu packages admin)
db4fdc04 33 #:use-module (ice-9 match)
80a67734 34 #:use-module (ice-9 vlist)
db4fdc04 35 #:use-module (srfi srfi-1)
80a67734 36 #:use-module (srfi srfi-26)
116244df
LC
37 #:use-module (srfi srfi-34)
38 #:use-module (srfi srfi-35)
d4053c71
AK
39 #:export (shepherd-root-service-type
40 %shepherd-root-service
41 shepherd-service-type
42
43 shepherd-service
44 shepherd-service?
45 shepherd-service-documentation
46 shepherd-service-provision
240b57f0 47 shepherd-service-canonical-name
d4053c71 48 shepherd-service-requirement
95ef8b85 49 shepherd-service-one-shot?
d4053c71
AK
50 shepherd-service-respawn?
51 shepherd-service-start
52 shepherd-service-stop
53 shepherd-service-auto-start?
54 shepherd-service-modules
fae685b9 55
70138308
LC
56 shepherd-action
57 shepherd-action?
58 shepherd-action-name
59 shepherd-action-documentation
60 shepherd-action-procedure
61
fae685b9 62 %default-modules
80a67734 63
240b57f0
LC
64 shepherd-service-file
65
a5d78eb6 66 shepherd-service-lookup-procedure
7b44cae5 67 shepherd-service-back-edges
10c41368
LC
68 shepherd-service-upgrade
69
70 user-processes-service-type))
db4fdc04
LC
71
72;;; Commentary:
73;;;
fe1ad5f5 74;;; Instantiating system services as a shepherd configuration file.
db4fdc04
LC
75;;;
76;;; Code:
77
0adfe95a 78
d4053c71 79(define (shepherd-boot-gexp services)
378daa8c
LC
80 #~(begin
81 ;; Keep track of the booted system.
82 (false-if-exception (delete-file "/run/booted-system"))
83 (symlink (readlink "/run/current-system")
84 "/run/booted-system")
0adfe95a 85
378daa8c
LC
86 ;; Close any remaining open file descriptors to be on the safe
87 ;; side. This must be the very last thing we do, because
88 ;; Guile has internal FDs such as 'sleep_pipe' that need to be
89 ;; alive.
90 (let loop ((fd 3))
91 (when (< fd 1024)
92 (false-if-exception (close-fdes fd))
93 (loop (+ 1 fd))))
0adfe95a 94
378daa8c
LC
95 ;; Start shepherd.
96 (execl #$(file-append shepherd "/bin/shepherd")
97 "shepherd" "--config"
98 #$(shepherd-configuration-file services))))
0adfe95a 99
d4053c71 100(define shepherd-root-service-type
0adfe95a 101 (service-type
d4053c71
AK
102 (name 'shepherd-root)
103 ;; Extending the root shepherd service (aka. PID 1) happens by
104 ;; concatenating the list of services provided by the extensions.
0adfe95a
LC
105 (compose concatenate)
106 (extend append)
d4053c71
AK
107 (extensions (list (service-extension boot-service-type
108 shepherd-boot-gexp)
c273d81b 109 (service-extension profile-service-type
dd0804c6
LC
110 (const (list shepherd)))))
111 (description
112 "Run the GNU Shepherd as PID 1---i.e., the operating system's first
113process. The Shepherd takes care of managing services such as daemons by
114ensuring they are started and stopped in the right order.")))
0adfe95a 115
d4053c71
AK
116(define %shepherd-root-service
117 ;; The root shepherd service, aka. PID 1. Its parameter is a list of
118 ;; <shepherd-service> objects.
119 (service shepherd-root-service-type '()))
0adfe95a 120
88cd7bbd
LC
121(define-syntax shepherd-service-type
122 (syntax-rules ()
123 "Return a <service-type> denoting a simple shepherd service--i.e., the type
124for a service that extends SHEPHERD-ROOT-SERVICE-TYPE and nothing else. When
125DEFAULT is given, use it as the service's default value."
126 ((_ service-name proc default)
127 (service-type
128 (name service-name)
129 (extensions
130 (list (service-extension shepherd-root-service-type
131 (compose list proc))))
132 (default-value default)))
133 ((_ service-name proc)
134 (service-type
135 (name service-name)
136 (extensions
137 (list (service-extension shepherd-root-service-type
138 (compose list proc))))))))
0adfe95a 139
fae685b9
LC
140(define %default-imported-modules
141 ;; Default set of modules imported for a service's consumption.
142 '((guix build utils)
479b417b 143 (guix build syscalls)))
fae685b9
LC
144
145(define %default-modules
146 ;; Default set of modules visible in a service's file.
34044d55 147 `((shepherd service)
fae685b9 148 (oop goops)
408ae72c 149 ((guix build utils) #:hide (delete))
479b417b 150 (guix build syscalls)))
fae685b9 151
d4053c71
AK
152(define-record-type* <shepherd-service>
153 shepherd-service make-shepherd-service
154 shepherd-service?
155 (documentation shepherd-service-documentation ;string
0adfe95a 156 (default "[No documentation.]"))
d4053c71
AK
157 (provision shepherd-service-provision) ;list of symbols
158 (requirement shepherd-service-requirement ;list of symbols
0adfe95a 159 (default '()))
95ef8b85
LC
160 (one-shot? shepherd-service-one-shot? ;Boolean
161 (default #f))
d4053c71 162 (respawn? shepherd-service-respawn? ;Boolean
0adfe95a 163 (default #t))
d4053c71
AK
164 (start shepherd-service-start) ;g-expression (procedure)
165 (stop shepherd-service-stop ;g-expression (procedure)
0adfe95a 166 (default #~(const #f)))
70138308
LC
167 (actions shepherd-service-actions ;list of <shepherd-action>
168 (default '()))
d4053c71 169 (auto-start? shepherd-service-auto-start? ;Boolean
fae685b9 170 (default #t))
d4053c71 171 (modules shepherd-service-modules ;list of module names
a91c3fc7 172 (default %default-modules)))
0adfe95a 173
70138308
LC
174(define-record-type* <shepherd-action>
175 shepherd-action make-shepherd-action
176 shepherd-action?
177 (name shepherd-action-name) ;symbol
178 (procedure shepherd-action-procedure) ;gexp
179 (documentation shepherd-action-documentation)) ;string
180
240b57f0
LC
181(define (shepherd-service-canonical-name service)
182 "Return the 'canonical name' of SERVICE."
183 (first (shepherd-service-provision service)))
0adfe95a 184
2d2651e7 185(define (assert-valid-graph services)
d4053c71
AK
186 "Raise an error if SERVICES does not define a valid shepherd service graph,
187for instance if a service requires a nonexistent service, or if more than one
2d2651e7 188service uses a given name.
116244df 189
d4053c71
AK
190These are constraints that shepherd's 'register-service' verifies but we'd
191better verify them here statically than wait until PID 1 halts with an
192assertion failure."
2d2651e7
LC
193 (define provisions
194 ;; The set of provisions (symbols). Bail out if a symbol is given more
195 ;; than once.
196 (fold (lambda (service set)
197 (define (assert-unique symbol)
198 (when (set-contains? set symbol)
199 (raise (condition
200 (&message
201 (message
69daee23 202 (format #f (G_ "service '~a' provided more than once")
2d2651e7
LC
203 symbol)))))))
204
d4053c71
AK
205 (for-each assert-unique (shepherd-service-provision service))
206 (fold set-insert set (shepherd-service-provision service)))
207 (setq 'shepherd)
2d2651e7
LC
208 services))
209
210 (define (assert-satisfied-requirements service)
211 ;; Bail out if the requirements of SERVICE aren't satisfied.
212 (for-each (lambda (requirement)
213 (unless (set-contains? provisions requirement)
214 (raise (condition
215 (&message
216 (message
69daee23 217 (format #f (G_ "service '~a' requires '~a', \
2c2ec261 218which is not provided by any service")
d4053c71 219 (match (shepherd-service-provision service)
2d2651e7
LC
220 ((head . _) head)
221 (_ service))
222 requirement)))))))
d4053c71 223 (shepherd-service-requirement service)))
2d2651e7
LC
224
225 (for-each assert-satisfied-requirements services))
116244df 226
d4053c71 227(define (shepherd-service-file-name service)
fae685b9
LC
228 "Return the file name where the initialization code for SERVICE is to be
229stored."
230 (let ((provisions (string-join (map symbol->string
d4053c71
AK
231 (shepherd-service-provision service)))))
232 (string-append "shepherd-"
fae685b9
LC
233 (string-map (match-lambda
234 (#\/ #\-)
750a4239 235 (#\ #\-)
fae685b9
LC
236 (chr chr))
237 provisions)
238 ".scm")))
239
d4053c71 240(define (shepherd-service-file service)
fae685b9 241 "Return a file defining SERVICE."
33033a62
LC
242 (scheme-file (shepherd-service-file-name service)
243 (with-imported-modules %default-imported-modules
244 #~(begin
245 (use-modules #$@(shepherd-service-modules service))
246
247 (make <service>
248 #:docstring '#$(shepherd-service-documentation service)
249 #:provides '#$(shepherd-service-provision service)
250 #:requires '#$(shepherd-service-requirement service)
95ef8b85
LC
251
252 ;; The 'one-shot?' slot is new in Shepherd 0.6.0.
253 ;; Older versions ignore it.
254 #:one-shot? '#$(shepherd-service-one-shot? service)
255
33033a62
LC
256 #:respawn? '#$(shepherd-service-respawn? service)
257 #:start #$(shepherd-service-start service)
70138308
LC
258 #:stop #$(shepherd-service-stop service)
259 #:actions
260 (make-actions
261 #$@(map (match-lambda
262 (($ <shepherd-action> name proc doc)
263 #~(#$name #$doc #$proc)))
264 (shepherd-service-actions service))))))))
fae685b9 265
63b0ce39
LC
266(define (scm->go file)
267 "Compile FILE, which contains code to be loaded by shepherd's config file,
268and return the resulting '.go' file."
d2fc7646
JN
269 ;; FIXME: %current-target-system may not be bound <https://bugs.gnu.org/29296>
270 (let ((target (%current-target-system)))
271 (with-extensions (list shepherd)
272 (computed-file (string-append (basename (scheme-file-name file) ".scm")
273 ".go")
274 #~(begin
275 (use-modules (system base compile)
276 (system base target))
277
278 ;; Do the same as the Shepherd's 'load-in-user-module'.
279 (let ((env (make-fresh-user-module)))
280 (module-use! env (resolve-interface '(oop goops)))
281 (module-use! env (resolve-interface '(shepherd service)))
282 (with-target #$(or target #~%host-type)
283 (lambda _
284 (compile-file #$file #:output-file #$output
285 #:env env)))))
286
287 ;; It's faster to build locally than to download.
288 #:options '(#:local-build? #t
289 #:substitutable? #f)))))
63b0ce39 290
fe1ad5f5
AK
291(define (shepherd-configuration-file services)
292 "Return the shepherd configuration file for SERVICES."
2d2651e7 293 (assert-valid-graph services)
116244df 294
33033a62 295 (let ((files (map shepherd-service-file services)))
23ed63a1
LC
296 (define config
297 #~(begin
081bd3bd
LC
298 (use-modules (srfi srfi-34)
299 (system repl error-handling))
b9c7ed71 300
8b9cad01
LC
301 ;; Specify the default environment visible to all the services.
302 ;; Without this statement, all the environment variables of PID 1
303 ;; are inherited by child services.
304 (default-environment-variables
305 '("PATH=/run/current-system/profile/bin"))
306
8aa752ba
LC
307 ;; Booting off a DVD, especially on a slow machine, can make
308 ;; everything slow. Thus, increase the timeout compared to the
309 ;; default 5s in the Shepherd 0.7.0. See
310 ;; <https://bugs.gnu.org/40572>.
e3358a83 311 (default-pid-file-timeout 30)
8aa752ba 312
234ea8a7
LC
313 ;; Arrange to spawn a REPL if something goes wrong. This is better
314 ;; than a kernel panic.
b9c7ed71
LC
315 (call-with-error-handling
316 (lambda ()
63b0ce39 317 (apply register-services
408ae72c
LC
318 (parameterize ((current-warning-port
319 (%make-void-port "w")))
320 (map load-compiled '#$(map scm->go files))))))
63b0ce39 321
63b0ce39
LC
322 (format #t "starting services...~%")
323 (for-each (lambda (service)
324 ;; In the Shepherd 0.3 the 'start' method can raise
325 ;; '&action-runtime-error' if it fails, so protect
326 ;; against it. (XXX: 'action-runtime-error?' is not
327 ;; exported is 0.3, hence 'service-error?'.)
328 (guard (c ((service-error? c)
329 (format (current-error-port)
330 "failed to start service '~a'~%"
331 service)))
332 (start service)))
333 '#$(append-map shepherd-service-provision
334 (filter shepherd-service-auto-start?
335 services)))
336
337 ;; Hang up stdin. At this point, we assume that 'start' methods
338 ;; that required user interaction on the console (e.g.,
339 ;; 'cryptsetup open' invocations, post-fsck emergency REPL) have
340 ;; completed. User interaction becomes impossible after this
341 ;; call; this avoids situations where services wrongfully lead
342 ;; PID 1 to read from stdin (the console), which users may not
343 ;; have access to (see <https://bugs.gnu.org/23697>).
344 (redirect-port (open-input-file "/dev/null")
345 (current-input-port))))
23ed63a1 346
33033a62 347 (scheme-file "shepherd.conf" config)))
db4fdc04 348
a5d78eb6
LC
349(define* (shepherd-service-lookup-procedure services
350 #:optional
351 (provision
352 shepherd-service-provision))
353 "Return a procedure that, when passed a symbol, return the item among
354SERVICES that provides this symbol. PROVISION must be a one-argument
355procedure that takes a service and returns the list of symbols it provides."
356 (let ((services (fold (lambda (service result)
357 (fold (cut vhash-consq <> service <>)
358 result
359 (provision service)))
360 vlist-null
361 services)))
362 (lambda (name)
363 (match (vhash-assq name services)
364 ((_ . service) service)
365 (#f #f)))))
366
6673bddc
LC
367(define* (shepherd-service-back-edges services
368 #:key
369 (provision shepherd-service-provision)
370 (requirement shepherd-service-requirement))
d4053c71 371 "Return a procedure that, when given a <shepherd-service> from SERVICES,
6673bddc
LC
372returns the list of <shepherd-service> that depend on it.
373
374Use PROVISION and REQUIREMENT as one-argument procedures that return the
375symbols provided/required by a service."
80a67734 376 (define provision->service
6673bddc 377 (shepherd-service-lookup-procedure services provision))
80a67734
LC
378
379 (define edges
380 (fold (lambda (service edges)
381 (fold (lambda (requirement edges)
382 (vhash-consq (provision->service requirement) service
383 edges))
384 edges
6673bddc 385 (requirement service)))
80a67734
LC
386 vlist-null
387 services))
388
389 (lambda (service)
390 (vhash-foldq* cons '() service edges)))
391
7b44cae5
LC
392(define (shepherd-service-upgrade live target)
393 "Return two values: the subset of LIVE (a list of <live-service>) that needs
394to be unloaded, and the subset of TARGET (a list of <shepherd-service>) that
4245ddcb 395need to be restarted to complete their upgrade."
7b44cae5
LC
396 (define (essential? service)
397 (memq (first (live-service-provision service))
398 '(root shepherd)))
399
400 (define lookup-target
401 (shepherd-service-lookup-procedure target
402 shepherd-service-provision))
403
404 (define lookup-live
405 (shepherd-service-lookup-procedure live
406 live-service-provision))
407
408 (define (running? service)
409 (and=> (lookup-live (shepherd-service-canonical-name service))
410 live-service-running))
411
7b44cae5
LC
412 (define live-service-dependents
413 (shepherd-service-back-edges live
414 #:provision live-service-provision
415 #:requirement live-service-requirement))
416
417 (define (obsolete? service)
418 (match (lookup-target (first (live-service-provision service)))
419 (#f (every obsolete? (live-service-dependents service)))
420 (_ #f)))
421
4245ddcb
CZ
422 (define to-restart
423 ;; Restart services that are currently running.
424 (filter running? target))
7b44cae5
LC
425
426 (define to-unload
4245ddcb
CZ
427 ;; Unload services that are no longer required.
428 (remove essential? (filter obsolete? live)))
7b44cae5 429
4245ddcb 430 (values to-unload to-restart))
7b44cae5 431
10c41368
LC
432\f
433;;;
434;;; User processes.
435;;;
436
437(define %do-not-kill-file
438 ;; Name of the file listing PIDs of processes that must survive when halting
439 ;; the system. Typical example is user-space file systems.
440 "/etc/shepherd/do-not-kill")
441
442(define (user-processes-shepherd-service requirements)
443 "Return the 'user-processes' Shepherd service with dependencies on
444REQUIREMENTS (a list of service names).
445
446This is a synchronization point used to make sure user processes and daemons
447get started only after crucial initial services have been started---file
448system mounts, etc. This is similar to the 'sysvinit' target in systemd."
449 (define grace-delay
450 ;; Delay after sending SIGTERM and before sending SIGKILL.
451 4)
452
453 (list (shepherd-service
454 (documentation "When stopped, terminate all user processes.")
455 (provision '(user-processes))
456 (requirement requirements)
457 (start #~(const #t))
458 (stop #~(lambda _
459 (define (kill-except omit signal)
460 ;; Kill all the processes with SIGNAL except those listed
461 ;; in OMIT and the current process.
462 (let ((omit (cons (getpid) omit)))
463 (for-each (lambda (pid)
464 (unless (memv pid omit)
465 (false-if-exception
466 (kill pid signal))))
467 (processes))))
468
469 (define omitted-pids
470 ;; List of PIDs that must not be killed.
471 (if (file-exists? #$%do-not-kill-file)
472 (map string->number
473 (call-with-input-file #$%do-not-kill-file
474 (compose string-tokenize
475 (@ (ice-9 rdelim) read-string))))
476 '()))
477
478 (define (now)
479 (car (gettimeofday)))
480
481 (define (sleep* n)
482 ;; Really sleep N seconds.
483 ;; Work around <http://bugs.gnu.org/19581>.
484 (define start (now))
485 (let loop ((elapsed 0))
486 (when (> n elapsed)
487 (sleep (- n elapsed))
488 (loop (- (now) start)))))
489
490 (define lset= (@ (srfi srfi-1) lset=))
491
492 (display "sending all processes the TERM signal\n")
493
494 (if (null? omitted-pids)
495 (begin
496 ;; Easy: terminate all of them.
497 (kill -1 SIGTERM)
498 (sleep* #$grace-delay)
499 (kill -1 SIGKILL))
500 (begin
501 ;; Kill them all except OMITTED-PIDS. XXX: We would
502 ;; like to (kill -1 SIGSTOP) to get a fixed list of
503 ;; processes, like 'killall5' does, but that seems
504 ;; unreliable.
505 (kill-except omitted-pids SIGTERM)
506 (sleep* #$grace-delay)
507 (kill-except omitted-pids SIGKILL)
508 (delete-file #$%do-not-kill-file)))
509
510 (let wait ()
511 ;; Reap children, if any, so that we don't end up with
512 ;; zombies and enter an infinite loop.
513 (let reap-children ()
514 (define result
515 (false-if-exception
516 (waitpid WAIT_ANY (if (null? omitted-pids)
517 0
518 WNOHANG))))
519
520 (when (and (pair? result)
521 (not (zero? (car result))))
522 (reap-children)))
523
524 (let ((pids (processes)))
525 (unless (lset= = pids (cons 1 omitted-pids))
526 (format #t "waiting for process termination\
527 (processes left: ~s)~%"
528 pids)
529 (sleep* 2)
530 (wait))))
531
532 (display "all processes have been terminated\n")
533 #f))
534 (respawn? #f))))
535
536(define user-processes-service-type
537 (service-type
538 (name 'user-processes)
539 (extensions (list (service-extension shepherd-root-service-type
540 user-processes-shepherd-service)))
541 (compose concatenate)
542 (extend append)
543
544 ;; The value is the list of Shepherd services 'user-processes' depends on.
545 ;; Extensions can add new services to this list.
546 (default-value '())
547
548 (description "The @code{user-processes} service is responsible for
549terminating all the processes so that the root file system can be re-mounted
550read-only, just before rebooting/halting. Processes still running after a few
551seconds after @code{SIGTERM} has been sent are terminated with
552@code{SIGKILL}.")))
553
0190c1c0 554;;; shepherd.scm ends here