services: networking: Remove unbound variable reference in 'stop'.
[jackhill/guix/guix.git] / gnu / services / web.scm
1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2015 David Thompson <davet@gnu.org>
3 ;;; Copyright © 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
4 ;;; Copyright © 2016 Nils Gillmann <ng0@n0.is>
5 ;;; Copyright © 2016, 2017, 2018 Julien Lepiller <julien@lepiller.eu>
6 ;;; Copyright © 2017 Christopher Baines <mail@cbaines.net>
7 ;;; Copyright © 2017 nee <nee-git@hidamari.blue>
8 ;;; Copyright © 2017, 2018 Clément Lassieur <clement@lassieur.org>
9 ;;; Copyright © 2018 Pierre-Antoine Rouby <pierre-antoine.rouby@inria.fr>
10 ;;; Copyright © 2017 Christopher Baines <mail@cbaines.net>
11 ;;;
12 ;;; This file is part of GNU Guix.
13 ;;;
14 ;;; GNU Guix is free software; you can redistribute it and/or modify it
15 ;;; under the terms of the GNU General Public License as published by
16 ;;; the Free Software Foundation; either version 3 of the License, or (at
17 ;;; your option) any later version.
18 ;;;
19 ;;; GNU Guix is distributed in the hope that it will be useful, but
20 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;;; GNU General Public License for more details.
23 ;;;
24 ;;; You should have received a copy of the GNU General Public License
25 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
26
27 (define-module (gnu services web)
28 #:use-module (gnu services)
29 #:use-module (gnu services shepherd)
30 #:use-module (gnu services admin)
31 #:use-module (gnu system pam)
32 #:use-module (gnu system shadow)
33 #:use-module (gnu packages admin)
34 #:use-module (gnu packages web)
35 #:use-module (gnu packages php)
36 #:use-module (gnu packages guile)
37 #:use-module (gnu packages logging)
38 #:use-module (guix records)
39 #:use-module (guix modules)
40 #:use-module (guix gexp)
41 #:use-module ((guix store) #:select (text-file))
42 #:use-module ((guix utils) #:select (version-major))
43 #:use-module ((guix packages) #:select (package-version))
44 #:use-module (srfi srfi-1)
45 #:use-module (srfi srfi-9)
46 #:use-module (ice-9 match)
47 #:export (<httpd-configuration>
48 httpd-configuration
49 httpd-configuration?
50 httpd-configuration-package
51 httpd-configuration-pid-file
52 httpd-configuration-config
53
54 <httpd-virtualhost>
55 httpd-virtualhost
56 httpd-virtualhost?
57 httpd-virtualhost-addresses-and-ports
58 httpd-virtualhost-contents
59
60 <httpd-config-file>
61 httpd-config-file
62 httpd-config-file?
63 httpd-config-file-modules
64 httpd-config-file-server-root
65 httpd-config-file-server-name
66 httpd-config-file-listen
67 httpd-config-file-pid-file
68 httpd-config-file-error-log
69 httpd-config-file-user
70 httpd-config-file-group
71
72 httpd-service-type
73
74 <nginx-configuration>
75 nginx-configuration
76 nginx-configuration?
77 nginx-configuartion-nginx
78 nginx-configuration-log-directory
79 nginx-configuration-run-directory
80 nginx-configuration-server-blocks
81 nginx-configuration-upstream-blocks
82 nginx-configuration-server-names-hash-bucket-size
83 nginx-configuration-server-names-hash-bucket-max-size
84 nginx-configuration-extra-content
85 nginx-configuration-file
86
87 <nginx-server-configuration>
88 nginx-server-configuration
89 nginx-server-configuration?
90 nginx-server-configuration-listen
91 nginx-server-configuration-server-name
92 nginx-server-configuration-root
93 nginx-server-configuration-locations
94 nginx-server-configuration-index
95 nginx-server-configuration-ssl-certificate
96 nginx-server-configuration-ssl-certificate-key
97 nginx-server-configuration-server-tokens?
98 nginx-server-configuration-raw-content
99
100 <nginx-upstream-configuration>
101 nginx-upstream-configuration
102 nginx-upstream-configuration?
103 nginx-upstream-configuration-name
104 nginx-upstream-configuration-servers
105
106 <nginx-location-configuration>
107 nginx-location-configuration
108 nginx-location-configuration?
109 nginx-location-configuration-uri
110 nginx-location-configuration-body
111
112 <nginx-named-location-configuration>
113 nginx-named-location-configuration
114 nginx-named-location-configuration?
115 nginx-named-location-configuration-name
116 nginx-named-location-configuration-body
117
118 nginx-service
119 nginx-service-type
120
121 fcgiwrap-configuration
122 fcgiwrap-configuration?
123 fcgiwrap-service-type
124
125 <php-fpm-configuration>
126 php-fpm-configuration
127 make-php-fpm-configuration
128 php-fpm-configuration?
129 php-fpm-configuration-php
130 php-fpm-configuration-socket
131 php-fpm-configuration-user
132 php-fpm-configuration-group
133 php-fpm-configuration-socket-user
134 php-fpm-configuration-socket-group
135 php-fpm-configuration-pid-file
136 php-fpm-configuration-log-file
137 php-fpm-configuration-process-manager
138 php-fpm-configuration-display-errors
139 php-fpm-configuration-workers-log-file
140 php-fpm-configuration-file
141
142 <php-fpm-dynamic-process-manager-configuration>
143 php-fpm-dynamic-process-manager-configuration
144 make-php-fpm-dynamic-process-manager-configuration
145 php-fpm-dynamic-process-manager-configuration?
146 php-fpm-dynamic-process-manager-configuration-max-children
147 php-fpm-dynamic-process-manager-configuration-start-servers
148 php-fpm-dynamic-process-manager-configuration-min-spare-servers
149 php-fpm-dynamic-process-manager-configuration-max-spare-servers
150
151 <php-fpm-static-process-manager-configuration>
152 php-fpm-static-process-manager-configuration
153 make-php-fpm-static-process-manager-configuration
154 php-fpm-static-process-manager-configuration?
155 php-fpm-static-process-manager-configuration-max-children
156
157 <php-fpm-on-demand-process-manager-configuration>
158 php-fpm-on-demand-process-manager-configuration
159 make-php-fpm-on-demand-process-manager-configuration
160 php-fpm-on-demand-process-manager-configuration?
161 php-fpm-on-demand-process-manager-configuration-max-children
162 php-fpm-on-demand-process-manager-configuration-process-idle-timeout
163
164 php-fpm-service-type
165 nginx-php-location
166
167 cat-avatar-generator-service
168
169 hpcguix-web-configuration
170 hpcguix-web-configuration?
171 hpcguix-web-service-type
172
173 <tailon-configuration-file>
174 tailon-configuration-file
175 tailon-configuration-file?
176 tailon-configuration-file-files
177 tailon-configuration-file-bind
178 tailon-configuration-file-relative-root
179 tailon-configuration-file-allow-transfers?
180 tailon-configuration-file-follow-names?
181 tailon-configuration-file-tail-lines
182 tailon-configuration-file-allowed-commands
183 tailon-configuration-file-debug?
184 tailon-configuration-file-http-auth
185 tailon-configuration-file-users
186
187 <tailon-configuration>
188 tailon-configuration
189 tailon-configuration?
190 tailon-configuration-config-file
191 tailon-configuration-package
192
193 tailon-service-type))
194
195 ;;; Commentary:
196 ;;;
197 ;;; Web services.
198 ;;;
199 ;;; Code:
200
201 (define-record-type* <httpd-module>
202 httpd-module make-httpd-module
203 httpd-module?
204 (name httpd-load-module-name)
205 (file httpd-load-module-file))
206
207 ;; Default modules for the httpd-service-type, taken from etc/httpd/httpd.conf
208 ;; file in the httpd package.
209 (define %default-httpd-modules
210 (map (match-lambda
211 ((name file)
212 (httpd-module
213 (name name)
214 (file file))))
215 '(("authn_file_module" "modules/mod_authn_file.so")
216 ("authn_core_module" "modules/mod_authn_core.so")
217 ("authz_host_module" "modules/mod_authz_host.so")
218 ("authz_groupfile_module" "modules/mod_authz_groupfile.so")
219 ("authz_user_module" "modules/mod_authz_user.so")
220 ("authz_core_module" "modules/mod_authz_core.so")
221 ("access_compat_module" "modules/mod_access_compat.so")
222 ("auth_basic_module" "modules/mod_auth_basic.so")
223 ("reqtimeout_module" "modules/mod_reqtimeout.so")
224 ("filter_module" "modules/mod_filter.so")
225 ("mime_module" "modules/mod_mime.so")
226 ("log_config_module" "modules/mod_log_config.so")
227 ("env_module" "modules/mod_env.so")
228 ("headers_module" "modules/mod_headers.so")
229 ("setenvif_module" "modules/mod_setenvif.so")
230 ("version_module" "modules/mod_version.so")
231 ("unixd_module" "modules/mod_unixd.so")
232 ("status_module" "modules/mod_status.so")
233 ("autoindex_module" "modules/mod_autoindex.so")
234 ("dir_module" "modules/mod_dir.so")
235 ("alias_module" "modules/mod_alias.so"))))
236
237 (define-record-type* <httpd-config-file>
238 httpd-config-file make-httpd-config-file
239 httpd-config-file?
240 (modules httpd-config-file-modules
241 (default %default-httpd-modules))
242 (server-root httpd-config-file-server-root
243 (default httpd))
244 (server-name httpd-config-file-server-name
245 (default #f))
246 (document-root httpd-config-file-document-root
247 (default "/srv/http"))
248 (listen httpd-config-file-listen
249 (default '("80")))
250 (pid-file httpd-config-file-pid-file
251 (default "/var/run/httpd"))
252 (error-log httpd-config-file-error-log
253 (default "/var/log/httpd/error_log"))
254 (user httpd-config-file-user
255 (default "httpd"))
256 (group httpd-config-file-group
257 (default "httpd"))
258 (extra-config httpd-config-file-extra-config
259 (default
260 (list "TypesConfig etc/httpd/mime.types"))))
261
262 (define-gexp-compiler (httpd-config-file-compiler
263 (file <httpd-config-file>) system target)
264 (match file
265 (($ <httpd-config-file> load-modules server-root server-name
266 document-root listen pid-file error-log
267 user group extra-config)
268 (gexp->derivation
269 "httpd.conf"
270 #~(call-with-output-file (ungexp output "out")
271 (lambda (port)
272 (display
273 (string-append
274 (ungexp-splicing
275 `(,@(append-map
276 (match-lambda
277 (($ <httpd-module> name module)
278 `("LoadModule " ,name " " ,module "\n")))
279 load-modules)
280 ,@`("ServerRoot " ,server-root "\n")
281 ,@(if server-name
282 `("ServerName " ,server-name "\n")
283 '())
284 ,@`("DocumentRoot " ,document-root "\n")
285 ,@(append-map
286 (lambda (listen-value)
287 `("Listen " ,listen-value "\n"))
288 listen)
289 ,@(if pid-file
290 `("Pidfile " ,pid-file "\n")
291 '())
292 ,@(if error-log
293 `("ErrorLog " ,error-log "\n")
294 '())
295 ,@(if user
296 `("User " ,user "\n")
297 '())
298 ,@(if group
299 `("Group " ,group "\n")
300 '())
301 "\n\n"
302 ,@extra-config)))
303 port)))
304 #:local-build? #t))))
305
306 (define-record-type <httpd-virtualhost>
307 (httpd-virtualhost addresses-and-ports contents)
308 httpd-virtualhost?
309 (addresses-and-ports httpd-virtualhost-addresses-and-ports)
310 (contents httpd-virtualhost-contents))
311
312 (define-record-type* <httpd-configuration>
313 httpd-configuration make-httpd-configuration
314 httpd-configuration?
315 (package httpd-configuration-package
316 (default httpd))
317 (pid-file httpd-configuration-pid-file
318 (default "/var/run/httpd"))
319 (config httpd-configuration-config
320 (default (httpd-config-file))))
321
322 (define %httpd-accounts
323 (list (user-group (name "httpd") (system? #t))
324 (user-account
325 (name "httpd")
326 (group "httpd")
327 (system? #t)
328 (comment "Apache HTTPD server user")
329 (home-directory "/var/empty")
330 (shell (file-append shadow "/sbin/nologin")))))
331
332 (define httpd-shepherd-services
333 (match-lambda
334 (($ <httpd-configuration> package pid-file config)
335 (list (shepherd-service
336 (provision '(httpd))
337 (documentation "The Apache HTTP Server")
338 (requirement '(networking))
339 (start #~(make-forkexec-constructor
340 `(#$(file-append package "/bin/httpd")
341 #$@(if config
342 (list "-f" config)
343 '()))
344 #:pid-file #$pid-file))
345 (stop #~(make-kill-destructor)))))))
346
347 (define httpd-activation
348 (match-lambda
349 (($ <httpd-configuration> package pid-file config)
350 (match-record
351 config
352 <httpd-config-file>
353 (error-log document-root)
354 #~(begin
355 (use-modules (guix build utils))
356
357 (mkdir-p #$(dirname error-log))
358 (mkdir-p #$document-root))))))
359
360 (define (httpd-process-extensions original-config extension-configs)
361 (let ((config (httpd-configuration-config
362 original-config)))
363 (if (httpd-config-file? config)
364 (httpd-configuration
365 (inherit original-config)
366 (config
367 (httpd-config-file
368 (inherit config)
369 (extra-config
370 (append (httpd-config-file-extra-config config)
371 (append-map
372 (match-lambda
373 (($ <httpd-virtualhost>
374 addresses-and-ports
375 contents)
376 `(,(string-append
377 "<VirtualHost " addresses-and-ports ">\n")
378 ,@contents
379 "\n</VirtualHost>\n"))
380 ((? string? x)
381 `("\n" ,x "\n"))
382 ((? list? x)
383 `("\n" ,@x "\n")))
384 extension-configs)))))))))
385
386 (define httpd-service-type
387 (service-type (name 'httpd)
388 (extensions
389 (list (service-extension shepherd-root-service-type
390 httpd-shepherd-services)
391 (service-extension activation-service-type
392 httpd-activation)
393 (service-extension account-service-type
394 (const %httpd-accounts))))
395 (compose concatenate)
396 (extend httpd-process-extensions)
397 (default-value
398 (httpd-configuration))))
399
400 (define-record-type* <nginx-server-configuration>
401 nginx-server-configuration make-nginx-server-configuration
402 nginx-server-configuration?
403 (listen nginx-server-configuration-listen
404 (default '("80" "443 ssl")))
405 (server-name nginx-server-configuration-server-name
406 (default (list 'default)))
407 (root nginx-server-configuration-root
408 (default "/srv/http"))
409 (locations nginx-server-configuration-locations
410 (default '()))
411 (index nginx-server-configuration-index
412 (default (list "index.html")))
413 (try-files nginx-server-configuration-try-files
414 (default '()))
415 (ssl-certificate nginx-server-configuration-ssl-certificate
416 (default #f))
417 (ssl-certificate-key nginx-server-configuration-ssl-certificate-key
418 (default #f))
419 (server-tokens? nginx-server-configuration-server-tokens?
420 (default #f))
421 (raw-content nginx-server-configuration-raw-content
422 (default '())))
423
424 (define-record-type* <nginx-upstream-configuration>
425 nginx-upstream-configuration make-nginx-upstream-configuration
426 nginx-upstream-configuration?
427 (name nginx-upstream-configuration-name)
428 (servers nginx-upstream-configuration-servers))
429
430 (define-record-type* <nginx-location-configuration>
431 nginx-location-configuration make-nginx-location-configuration
432 nginx-location-configuration?
433 (uri nginx-location-configuration-uri
434 (default #f))
435 (body nginx-location-configuration-body))
436
437 (define-record-type* <nginx-named-location-configuration>
438 nginx-named-location-configuration make-nginx-named-location-configuration
439 nginx-named-location-configuration?
440 (name nginx-named-location-configuration-name
441 (default #f))
442 (body nginx-named-location-configuration-body))
443
444 (define-record-type* <nginx-configuration>
445 nginx-configuration make-nginx-configuration
446 nginx-configuration?
447 (nginx nginx-configuration-nginx ;<package>
448 (default nginx))
449 (log-directory nginx-configuration-log-directory ;string
450 (default "/var/log/nginx"))
451 (run-directory nginx-configuration-run-directory ;string
452 (default "/var/run/nginx"))
453 (server-blocks nginx-configuration-server-blocks
454 (default '())) ;list of <nginx-server-configuration>
455 (upstream-blocks nginx-configuration-upstream-blocks
456 (default '())) ;list of <nginx-upstream-configuration>
457 (server-names-hash-bucket-size nginx-configuration-server-names-hash-bucket-size
458 (default #f))
459 (server-names-hash-bucket-max-size nginx-configuration-server-names-hash-bucket-max-size
460 (default #f))
461 (extra-content nginx-configuration-extra-content
462 (default ""))
463 (file nginx-configuration-file ;#f | string | file-like
464 (default #f)))
465
466 (define (config-domain-strings names)
467 "Return a string denoting the nginx config representation of NAMES, a list
468 of domain names."
469 (map (match-lambda
470 ('default "_ ")
471 ((? string? str) (list str " ")))
472 names))
473
474 (define (config-index-strings names)
475 "Return a string denoting the nginx config representation of NAMES, a list
476 of index files."
477 (map (match-lambda
478 ((? string? str) (list str " ")))
479 names))
480
481 (define emit-nginx-location-config
482 (match-lambda
483 (($ <nginx-location-configuration> uri body)
484 (list
485 " location " uri " {\n"
486 (map (lambda (x) (list " " x "\n")) body)
487 " }\n"))
488 (($ <nginx-named-location-configuration> name body)
489 (list
490 " location @" name " {\n"
491 (map (lambda (x) (list " " x "\n")) body)
492 " }\n"))))
493
494 (define (emit-nginx-server-config server)
495 (let ((listen (nginx-server-configuration-listen server))
496 (server-name (nginx-server-configuration-server-name server))
497 (ssl-certificate (nginx-server-configuration-ssl-certificate server))
498 (ssl-certificate-key
499 (nginx-server-configuration-ssl-certificate-key server))
500 (root (nginx-server-configuration-root server))
501 (index (nginx-server-configuration-index server))
502 (try-files (nginx-server-configuration-try-files server))
503 (server-tokens? (nginx-server-configuration-server-tokens? server))
504 (locations (nginx-server-configuration-locations server))
505 (raw-content (nginx-server-configuration-raw-content server)))
506 (define-syntax-parameter <> (syntax-rules ()))
507 (define-syntax-rule (and/l x tail ...)
508 (let ((x* x))
509 (if x*
510 (syntax-parameterize ((<> (identifier-syntax x*)))
511 (list tail ...))
512 '())))
513 (list
514 " server {\n"
515 (map (lambda (directive) (list " listen " directive ";\n")) listen)
516 " server_name " (config-domain-strings server-name) ";\n"
517 (and/l ssl-certificate " ssl_certificate " <> ";\n")
518 (and/l ssl-certificate-key " ssl_certificate_key " <> ";\n")
519 " root " root ";\n"
520 " index " (config-index-strings index) ";\n"
521 (if (not (nil? try-files))
522 (and/l (config-index-strings try-files) " try_files " <> ";\n")
523 "")
524 " server_tokens " (if server-tokens? "on" "off") ";\n"
525 "\n"
526 (map emit-nginx-location-config locations)
527 "\n"
528 (map (lambda (x) (list " " x "\n")) raw-content)
529 " }\n")))
530
531 (define (emit-nginx-upstream-config upstream)
532 (list
533 " upstream " (nginx-upstream-configuration-name upstream) " {\n"
534 (map (lambda (server)
535 (simple-format #f " server ~A;\n" server))
536 (nginx-upstream-configuration-servers upstream))
537 " }\n"))
538
539 (define (flatten . lst)
540 "Return a list that recursively concatenates all sub-lists of LST."
541 (define (flatten1 head out)
542 (if (list? head)
543 (fold-right flatten1 out head)
544 (cons head out)))
545 (fold-right flatten1 '() lst))
546
547 (define (default-nginx-config config)
548 (match-record config
549 <nginx-configuration>
550 (nginx log-directory run-directory
551 server-blocks upstream-blocks
552 server-names-hash-bucket-size
553 server-names-hash-bucket-max-size
554 extra-content)
555 (apply mixed-text-file "nginx.conf"
556 (flatten
557 "user nginx nginx;\n"
558 "pid " run-directory "/pid;\n"
559 "error_log " log-directory "/error.log info;\n"
560 "http {\n"
561 " client_body_temp_path " run-directory "/client_body_temp;\n"
562 " proxy_temp_path " run-directory "/proxy_temp;\n"
563 " fastcgi_temp_path " run-directory "/fastcgi_temp;\n"
564 " uwsgi_temp_path " run-directory "/uwsgi_temp;\n"
565 " scgi_temp_path " run-directory "/scgi_temp;\n"
566 " access_log " log-directory "/access.log;\n"
567 " include " nginx "/share/nginx/conf/mime.types;\n"
568 (if server-names-hash-bucket-size
569 (string-append
570 " server_names_hash_bucket_size "
571 (number->string server-names-hash-bucket-size)
572 ";\n")
573 "")
574 (if server-names-hash-bucket-max-size
575 (string-append
576 " server_names_hash_bucket_max_size "
577 (number->string server-names-hash-bucket-max-size)
578 ";\n")
579 "")
580 "\n"
581 (map emit-nginx-upstream-config upstream-blocks)
582 (map emit-nginx-server-config server-blocks)
583 extra-content
584 "\n}\n"
585 "events {}\n"))))
586
587 (define %nginx-accounts
588 (list (user-group (name "nginx") (system? #t))
589 (user-account
590 (name "nginx")
591 (group "nginx")
592 (system? #t)
593 (comment "nginx server user")
594 (home-directory "/var/empty")
595 (shell (file-append shadow "/sbin/nologin")))))
596
597 (define (nginx-activation config)
598 (match-record config
599 <nginx-configuration>
600 (nginx log-directory run-directory file)
601 #~(begin
602 (use-modules (guix build utils))
603
604 (format #t "creating nginx log directory '~a'~%" #$log-directory)
605 (mkdir-p #$log-directory)
606 (format #t "creating nginx run directory '~a'~%" #$run-directory)
607 (mkdir-p #$run-directory)
608 (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory)
609 (mkdir-p (string-append #$run-directory "/client_body_temp"))
610 (mkdir-p (string-append #$run-directory "/proxy_temp"))
611 (mkdir-p (string-append #$run-directory "/fastcgi_temp"))
612 (mkdir-p (string-append #$run-directory "/uwsgi_temp"))
613 (mkdir-p (string-append #$run-directory "/scgi_temp"))
614 ;; Start-up logs. Once configuration is loaded, nginx switches to
615 ;; log-directory.
616 (mkdir-p (string-append #$run-directory "/logs"))
617 ;; Check configuration file syntax.
618 (system* (string-append #$nginx "/sbin/nginx")
619 "-c" #$(or file
620 (default-nginx-config config))
621 "-t"))))
622
623 (define (nginx-shepherd-service config)
624 (match-record config
625 <nginx-configuration>
626 (nginx file run-directory)
627 (let* ((nginx-binary (file-append nginx "/sbin/nginx"))
628 (pid-file (in-vicinity run-directory "pid"))
629 (nginx-action
630 (lambda args
631 #~(lambda _
632 (invoke #$nginx-binary "-c"
633 #$(or file
634 (default-nginx-config config))
635 #$@args)
636 (match '#$args
637 (("-s" . _) #f)
638 (_
639 ;; When FILE is true, we cannot be sure that PID-FILE will
640 ;; be created, so assume it won't show up. When FILE is
641 ;; false, read PID-FILE.
642 #$(if file
643 #~#t
644 #~(read-pid-file #$pid-file))))))))
645
646 ;; TODO: Add 'reload' action.
647 (list (shepherd-service
648 (provision '(nginx))
649 (documentation "Run the nginx daemon.")
650 (requirement '(user-processes loopback))
651 (modules `((ice-9 match)
652 ,@%default-modules))
653 (start (nginx-action "-p" run-directory))
654 (stop (nginx-action "-s" "stop")))))))
655
656 (define nginx-service-type
657 (service-type (name 'nginx)
658 (extensions
659 (list (service-extension shepherd-root-service-type
660 nginx-shepherd-service)
661 (service-extension activation-service-type
662 nginx-activation)
663 (service-extension account-service-type
664 (const %nginx-accounts))))
665 (compose concatenate)
666 (extend (lambda (config servers)
667 (nginx-configuration
668 (inherit config)
669 (server-blocks
670 (append (nginx-configuration-server-blocks config)
671 servers)))))
672 (default-value
673 (nginx-configuration))))
674
675 (define-record-type* <fcgiwrap-configuration> fcgiwrap-configuration
676 make-fcgiwrap-configuration
677 fcgiwrap-configuration?
678 (package fcgiwrap-configuration-package ;<package>
679 (default fcgiwrap))
680 (socket fcgiwrap-configuration-socket
681 (default "tcp:127.0.0.1:9000"))
682 (user fcgiwrap-configuration-user
683 (default "fcgiwrap"))
684 (group fcgiwrap-configuration-group
685 (default "fcgiwrap")))
686
687 (define fcgiwrap-accounts
688 (match-lambda
689 (($ <fcgiwrap-configuration> package socket user group)
690 (filter identity
691 (list
692 (and (equal? group "fcgiwrap")
693 (user-group
694 (name "fcgiwrap")
695 (system? #t)))
696 (and (equal? user "fcgiwrap")
697 (user-account
698 (name "fcgiwrap")
699 (group group)
700 (system? #t)
701 (comment "Fcgiwrap Daemon")
702 (home-directory "/var/empty")
703 (shell (file-append shadow "/sbin/nologin")))))))))
704
705 (define fcgiwrap-shepherd-service
706 (match-lambda
707 (($ <fcgiwrap-configuration> package socket user group)
708 (list (shepherd-service
709 (provision '(fcgiwrap))
710 (documentation "Run the fcgiwrap daemon.")
711 (requirement '(networking))
712 (start #~(make-forkexec-constructor
713 '(#$(file-append package "/sbin/fcgiwrap")
714 "-s" #$socket)
715 #:user #$user #:group #$group))
716 (stop #~(make-kill-destructor)))))))
717
718 (define fcgiwrap-service-type
719 (service-type (name 'fcgiwrap)
720 (extensions
721 (list (service-extension shepherd-root-service-type
722 fcgiwrap-shepherd-service)
723 (service-extension account-service-type
724 fcgiwrap-accounts)))
725 (default-value (fcgiwrap-configuration))))
726
727 (define-record-type* <php-fpm-configuration> php-fpm-configuration
728 make-php-fpm-configuration
729 php-fpm-configuration?
730 (php php-fpm-configuration-php ;<package>
731 (default php))
732 (socket php-fpm-configuration-socket
733 (default (string-append "/var/run/php"
734 (version-major (package-version php))
735 "-fpm.sock")))
736 (user php-fpm-configuration-user
737 (default "php-fpm"))
738 (group php-fpm-configuration-group
739 (default "php-fpm"))
740 (socket-user php-fpm-configuration-socket-user
741 (default "php-fpm"))
742 (socket-group php-fpm-configuration-socket-group
743 (default "nginx"))
744 (pid-file php-fpm-configuration-pid-file
745 (default (string-append "/var/run/php"
746 (version-major (package-version php))
747 "-fpm.pid")))
748 (log-file php-fpm-configuration-log-file
749 (default (string-append "/var/log/php"
750 (version-major (package-version php))
751 "-fpm.log")))
752 (process-manager php-fpm-configuration-process-manager
753 (default (php-fpm-dynamic-process-manager-configuration)))
754 (display-errors php-fpm-configuration-display-errors
755 (default #f))
756 (workers-log-file php-fpm-configuration-workers-log-file
757 (default (string-append "/var/log/php"
758 (version-major (package-version php))
759 "-fpm.www.log")))
760 (file php-fpm-configuration-file ;#f | file-like
761 (default #f)))
762
763 (define-record-type* <php-fpm-dynamic-process-manager-configuration>
764 php-fpm-dynamic-process-manager-configuration
765 make-php-fpm-dynamic-process-manager-configuration
766 php-fpm-dynamic-process-manager-configuration?
767 (max-children php-fpm-dynamic-process-manager-configuration-max-children
768 (default 5))
769 (start-servers php-fpm-dynamic-process-manager-configuration-start-servers
770 (default 2))
771 (min-spare-servers php-fpm-dynamic-process-manager-configuration-min-spare-servers
772 (default 1))
773 (max-spare-servers php-fpm-dynamic-process-manager-configuration-max-spare-servers
774 (default 3)))
775
776 (define-record-type* <php-fpm-static-process-manager-configuration>
777 php-fpm-static-process-manager-configuration
778 make-php-fpm-static-process-manager-configuration
779 php-fpm-static-process-manager-configuration?
780 (max-children php-fpm-static-process-manager-configuration-max-children
781 (default 5)))
782
783 (define-record-type* <php-fpm-on-demand-process-manager-configuration>
784 php-fpm-on-demand-process-manager-configuration
785 make-php-fpm-on-demand-process-manager-configuration
786 php-fpm-on-demand-process-manager-configuration?
787 (max-children php-fpm-on-demand-process-manager-configuration-max-children
788 (default 5))
789 (process-idle-timeout php-fpm-on-demand-process-manager-configuration-process-idle-timeout
790 (default 10)))
791
792 (define php-fpm-accounts
793 (match-lambda
794 (($ <php-fpm-configuration> php socket user group socket-user socket-group _ _ _ _ _ _)
795 (list
796 (user-group (name "php-fpm") (system? #t))
797 (user-group
798 (name group)
799 (system? #t))
800 (user-account
801 (name user)
802 (group group)
803 (supplementary-groups '("php-fpm"))
804 (system? #t)
805 (comment "php-fpm daemon user")
806 (home-directory "/var/empty")
807 (shell (file-append shadow "/sbin/nologin")))))))
808
809 (define (default-php-fpm-config socket user group socket-user socket-group
810 pid-file log-file pm display-errors workers-log-file)
811 (apply mixed-text-file "php-fpm.conf"
812 (flatten
813 "[global]\n"
814 "pid =" pid-file "\n"
815 "error_log =" log-file "\n"
816 "[www]\n"
817 "user =" user "\n"
818 "group =" group "\n"
819 "listen =" socket "\n"
820 "listen.owner =" socket-user "\n"
821 "listen.group =" socket-group "\n"
822
823 (match pm
824 (($ <php-fpm-dynamic-process-manager-configuration>
825 pm.max-children
826 pm.start-servers
827 pm.min-spare-servers
828 pm.max-spare-servers)
829 (list
830 "pm = dynamic\n"
831 "pm.max_children =" (number->string pm.max-children) "\n"
832 "pm.start_servers =" (number->string pm.start-servers) "\n"
833 "pm.min_spare_servers =" (number->string pm.min-spare-servers) "\n"
834 "pm.max_spare_servers =" (number->string pm.max-spare-servers) "\n"))
835
836 (($ <php-fpm-static-process-manager-configuration>
837 pm.max-children)
838 (list
839 "pm = static\n"
840 "pm.max_children =" (number->string pm.max-children) "\n"))
841
842 (($ <php-fpm-on-demand-process-manager-configuration>
843 pm.max-children
844 pm.process-idle-timeout)
845 (list
846 "pm = ondemand\n"
847 "pm.max_children =" (number->string pm.max-children) "\n"
848 "pm.process_idle_timeout =" (number->string pm.process-idle-timeout) "s\n")))
849
850
851 "php_flag[display_errors] = " (if display-errors "on" "off") "\n"
852
853 (if workers-log-file
854 (list "catch_workers_output = yes\n"
855 "php_admin_value[error_log] =" workers-log-file "\n"
856 "php_admin_flag[log_errors] = on\n")
857 (list "catch_workers_output = no\n")))))
858
859 (define php-fpm-shepherd-service
860 (match-lambda
861 (($ <php-fpm-configuration> php socket user group socket-user socket-group
862 pid-file log-file pm display-errors workers-log-file file)
863 (list (shepherd-service
864 (provision '(php-fpm))
865 (documentation "Run the php-fpm daemon.")
866 (requirement '(networking))
867 (start #~(make-forkexec-constructor
868 '(#$(file-append php "/sbin/php-fpm")
869 "--fpm-config"
870 #$(or file
871 (default-php-fpm-config socket user group
872 socket-user socket-group pid-file log-file
873 pm display-errors workers-log-file)))
874 #:pid-file #$pid-file))
875 (stop #~(make-kill-destructor)))))))
876
877 (define php-fpm-activation
878 (match-lambda
879 (($ <php-fpm-configuration> _ _ user _ _ _ _ log-file _ _ workers-log-file _)
880 #~(begin
881 (use-modules (guix build utils))
882 (let* ((user (getpwnam #$user))
883 (touch (lambda (file-name)
884 (call-with-output-file file-name (const #t))))
885 (init-log-file
886 (lambda (file-name)
887 (when #$workers-log-file
888 (when (not (file-exists? file-name))
889 (touch file-name))
890 (chown file-name (passwd:uid user) (passwd:gid user))
891 (chmod file-name #o660)))))
892 (init-log-file #$log-file)
893 (init-log-file #$workers-log-file))))))
894
895
896 (define php-fpm-service-type
897 (service-type
898 (name 'php-fpm)
899 (description
900 "Run @command{php-fpm} to provide a fastcgi socket for calling php through
901 a webserver.")
902 (extensions
903 (list (service-extension shepherd-root-service-type
904 php-fpm-shepherd-service)
905 (service-extension activation-service-type
906 php-fpm-activation)
907 (service-extension account-service-type
908 php-fpm-accounts)))
909 (default-value (php-fpm-configuration))))
910
911 (define* (nginx-php-location
912 #:key
913 (nginx-package nginx)
914 (socket (string-append "/var/run/php"
915 (version-major (package-version php))
916 "-fpm.sock")))
917 "Return a nginx-location-configuration that makes nginx run .php files."
918 (nginx-location-configuration
919 (uri "~ \\.php$")
920 (body (list
921 "fastcgi_split_path_info ^(.+\\.php)(/.+)$;"
922 (string-append "fastcgi_pass unix:" socket ";")
923 "fastcgi_index index.php;"
924 (list "include " nginx-package "/share/nginx/conf/fastcgi.conf;")))))
925
926 (define* (cat-avatar-generator-service
927 #:key
928 (cache-dir "/var/cache/cat-avatar-generator")
929 (package cat-avatar-generator)
930 (configuration (nginx-server-configuration)))
931 (simple-service
932 'cat-http-server nginx-service-type
933 (list (nginx-server-configuration
934 (inherit configuration)
935 (locations
936 (cons
937 (let ((base (nginx-php-location)))
938 (nginx-location-configuration
939 (inherit base)
940 (body (list (string-append "fastcgi_param CACHE_DIR \""
941 cache-dir "\";")
942 (nginx-location-configuration-body base)))))
943 (nginx-server-configuration-locations configuration)))
944 (root #~(string-append #$package
945 "/share/web/cat-avatar-generator"))))))
946
947 \f
948 (define-record-type* <hpcguix-web-configuration>
949 hpcguix-web-configuration make-hpcguix-web-configuration
950 hpcguix-web-configuration?
951
952 (package hpcguix-web-package (default hpcguix-web)) ;<package>
953
954 ;; Specs is gexp of hpcguix-web configuration file
955 (specs hpcguix-web-configuration-specs))
956
957 (define %hpcguix-web-accounts
958 (list (user-group
959 (name "hpcguix-web")
960 (system? #t))
961 (user-account
962 (name "hpcguix-web")
963 (group "hpcguix-web")
964 (system? #t)
965 (comment "hpcguix-web")
966 (home-directory "/var/empty")
967 (shell (file-append shadow "/sbin/nologin")))))
968
969 (define %hpcguix-web-activation
970 #~(begin
971 (use-modules (guix build utils))
972 (let ((home-dir "/var/cache/guix/web")
973 (user (getpwnam "hpcguix-web")))
974 (mkdir-p home-dir)
975 (chown home-dir (passwd:uid user) (passwd:gid user))
976 (chmod home-dir #o755))))
977
978 (define %hpcguix-web-log-file
979 "/var/log/hpcguix-web.log")
980
981 (define %hpcguix-web-log-rotations
982 (list (log-rotation
983 (files (list %hpcguix-web-log-file))
984 (frequency 'weekly))))
985
986 (define (hpcguix-web-shepherd-service config)
987 (let ((specs (hpcguix-web-configuration-specs config))
988 (hpcguix-web (hpcguix-web-package config)))
989 (with-imported-modules (source-module-closure
990 '((gnu build shepherd)))
991 (shepherd-service
992 (documentation "hpcguix-web daemon")
993 (provision '(hpcguix-web))
994 (requirement '(networking))
995 (start #~(make-forkexec-constructor
996 (list #$(file-append hpcguix-web "/bin/run")
997 (string-append "--config="
998 #$(scheme-file "hpcguix-web.scm" specs)))
999 #:user "hpcguix-web"
1000 #:group "hpcguix-web"
1001 #:environment-variables
1002 (list "XDG_CACHE_HOME=/var/cache"
1003 "SSL_CERT_DIR=/etc/ssl/certs")
1004 #:log-file #$%hpcguix-web-log-file))
1005 (stop #~(make-kill-destructor))))))
1006
1007 (define hpcguix-web-service-type
1008 (service-type
1009 (name 'hpcguix-web)
1010 (description "Run the hpcguix-web server.")
1011 (extensions
1012 (list (service-extension account-service-type
1013 (const %hpcguix-web-accounts))
1014 (service-extension activation-service-type
1015 (const %hpcguix-web-activation))
1016 (service-extension rottlog-service-type
1017 (const %hpcguix-web-log-rotations))
1018 (service-extension shepherd-root-service-type
1019 (compose list hpcguix-web-shepherd-service))))))
1020
1021 \f
1022 ;;;
1023 ;;; Tailon
1024 ;;;
1025
1026 (define-record-type* <tailon-configuration-file>
1027 tailon-configuration-file make-tailon-configuration-file
1028 tailon-configuration-file?
1029 (files tailon-configuration-file-files
1030 (default '("/var/log")))
1031 (bind tailon-configuration-file-bind
1032 (default "localhost:8080"))
1033 (relative-root tailon-configuration-file-relative-root
1034 (default #f))
1035 (allow-transfers? tailon-configuration-file-allow-transfers?
1036 (default #t))
1037 (follow-names? tailon-configuration-file-follow-names?
1038 (default #t))
1039 (tail-lines tailon-configuration-file-tail-lines
1040 (default 200))
1041 (allowed-commands tailon-configuration-file-allowed-commands
1042 (default '("tail" "grep" "awk")))
1043 (debug? tailon-configuration-file-debug?
1044 (default #f))
1045 (wrap-lines tailon-configuration-file-wrap-lines
1046 (default #t))
1047 (http-auth tailon-configuration-file-http-auth
1048 (default #f))
1049 (users tailon-configuration-file-users
1050 (default #f)))
1051
1052 (define (tailon-configuration-files-string files)
1053 (string-append
1054 "\n"
1055 (string-join
1056 (map
1057 (lambda (x)
1058 (string-append
1059 " - "
1060 (cond
1061 ((string? x)
1062 (simple-format #f "'~A'" x))
1063 ((list? x)
1064 (string-join
1065 (cons (simple-format #f "'~A':" (car x))
1066 (map
1067 (lambda (x) (simple-format #f " - '~A'" x))
1068 (cdr x)))
1069 "\n"))
1070 (else (error x)))))
1071 files)
1072 "\n")))
1073
1074 (define-gexp-compiler (tailon-configuration-file-compiler
1075 (file <tailon-configuration-file>) system target)
1076 (match file
1077 (($ <tailon-configuration-file> files bind relative-root
1078 allow-transfers? follow-names?
1079 tail-lines allowed-commands debug?
1080 wrap-lines http-auth users)
1081 (text-file
1082 "tailon-config.yaml"
1083 (string-concatenate
1084 (filter-map
1085 (match-lambda
1086 ((key . #f) #f)
1087 ((key . value) (string-append key ": " value "\n")))
1088
1089 `(("files" . ,(tailon-configuration-files-string files))
1090 ("bind" . ,bind)
1091 ("relative-root" . ,relative-root)
1092 ("allow-transfers" . ,(if allow-transfers? "true" "false"))
1093 ("follow-names" . ,(if follow-names? "true" "false"))
1094 ("tail-lines" . ,(number->string tail-lines))
1095 ("commands" . ,(string-append "["
1096 (string-join allowed-commands ", ")
1097 "]"))
1098 ("debug" . ,(if debug? "true" #f))
1099 ("wrap-lines" . ,(if wrap-lines "true" "false"))
1100 ("http-auth" . ,http-auth)
1101 ("users" . ,(if users
1102 (string-concatenate
1103 (cons "\n"
1104 (map (match-lambda
1105 ((user . pass)
1106 (string-append
1107 " " user ":" pass)))
1108 users)))
1109 #f)))))))))
1110
1111 (define-record-type* <tailon-configuration>
1112 tailon-configuration make-tailon-configuration
1113 tailon-configuration?
1114 (config-file tailon-configuration-config-file
1115 (default (tailon-configuration-file)))
1116 (package tailon-configuration-package
1117 (default tailon)))
1118
1119 (define tailon-shepherd-service
1120 (match-lambda
1121 (($ <tailon-configuration> config-file package)
1122 (list (shepherd-service
1123 (provision '(tailon))
1124 (documentation "Run the tailon daemon.")
1125 (start #~(make-forkexec-constructor
1126 `(,(string-append #$package "/bin/tailon")
1127 "-c" ,#$config-file)
1128 #:user "tailon"
1129 #:group "tailon"))
1130 (stop #~(make-kill-destructor)))))))
1131
1132 (define %tailon-accounts
1133 (list (user-group (name "tailon") (system? #t))
1134 (user-account
1135 (name "tailon")
1136 (group "tailon")
1137 (system? #t)
1138 (comment "tailon")
1139 (home-directory "/var/empty")
1140 (shell (file-append shadow "/sbin/nologin")))))
1141
1142 (define tailon-service-type
1143 (service-type
1144 (name 'tailon)
1145 (description
1146 "Run Tailon, a Web application for monitoring, viewing, and searching log
1147 files.")
1148 (extensions
1149 (list (service-extension shepherd-root-service-type
1150 tailon-shepherd-service)
1151 (service-extension account-service-type
1152 (const %tailon-accounts))))
1153 (compose concatenate)
1154 (extend (lambda (parameter files)
1155 (tailon-configuration
1156 (inherit parameter)
1157 (config-file
1158 (let ((old-config-file
1159 (tailon-configuration-config-file parameter)))
1160 (tailon-configuration-file
1161 (inherit old-config-file)
1162 (files (append (tailon-configuration-file-files old-config-file)
1163 files))))))))
1164 (default-value (tailon-configuration))))