services: 'references-file' depends on Guile-Gcrypt.
[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, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
4 ;;; Copyright © 2016 Nikita <nikita@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, 2018, 2019 Christopher Baines <mail@cbaines.net>
11 ;;; Copyright © 2018 Marius Bakke <mbakke@fastmail.com>
12 ;;; Copyright © 2019, 2020 Florian Pelz <pelzflorian@pelzflorian.de>
13 ;;; Copyright © 2020 Ricardo Wurmus <rekado@elephly.net>
14 ;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
15 ;;; Copyright © 2020 Arun Isaac <arunisaac@systemreboot.net>
16 ;;; Copyright © 2020 Oleg Pykhalov <go.wigust@gmail.com>
17 ;;; Copyright © 2020 Alexandru-Sergiu Marton <brown121407@posteo.ro>
18 ;;;
19 ;;; This file is part of GNU Guix.
20 ;;;
21 ;;; GNU Guix is free software; you can redistribute it and/or modify it
22 ;;; under the terms of the GNU General Public License as published by
23 ;;; the Free Software Foundation; either version 3 of the License, or (at
24 ;;; your option) any later version.
25 ;;;
26 ;;; GNU Guix is distributed in the hope that it will be useful, but
27 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
28 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 ;;; GNU General Public License for more details.
30 ;;;
31 ;;; You should have received a copy of the GNU General Public License
32 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
33
34 (define-module (gnu services web)
35 #:use-module (gnu services)
36 #:use-module (gnu services shepherd)
37 #:use-module (gnu services admin)
38 #:use-module (gnu services getmail)
39 #:use-module (gnu services mail)
40 #:use-module (gnu system pam)
41 #:use-module (gnu system shadow)
42 #:use-module (gnu packages admin)
43 #:use-module (gnu packages base)
44 #:use-module (gnu packages databases)
45 #:use-module (gnu packages web)
46 #:use-module (gnu packages patchutils)
47 #:use-module (gnu packages php)
48 #:use-module (gnu packages python)
49 #:use-module (gnu packages gnupg)
50 #:use-module (gnu packages guile)
51 #:use-module (gnu packages logging)
52 #:use-module (gnu packages mail)
53 #:use-module (guix packages)
54 #:use-module (guix records)
55 #:use-module (guix modules)
56 #:use-module (guix utils)
57 #:use-module (guix gexp)
58 #:use-module ((guix store) #:select (text-file))
59 #:use-module ((guix utils) #:select (version-major))
60 #:use-module ((guix packages) #:select (package-version))
61 #:use-module (srfi srfi-1)
62 #:use-module (srfi srfi-9)
63 #:use-module (ice-9 match)
64 #:use-module (ice-9 format)
65 #:export (httpd-configuration
66 httpd-configuration?
67 httpd-configuration-package
68 httpd-configuration-pid-file
69 httpd-configuration-config
70
71 httpd-virtualhost
72 httpd-virtualhost?
73 httpd-virtualhost-addresses-and-ports
74 httpd-virtualhost-contents
75
76 httpd-config-file
77 httpd-config-file?
78 httpd-config-file-modules
79 httpd-config-file-server-root
80 httpd-config-file-server-name
81 httpd-config-file-listen
82 httpd-config-file-pid-file
83 httpd-config-file-error-log
84 httpd-config-file-user
85 httpd-config-file-group
86
87 httpd-module
88 httpd-module?
89 %default-httpd-modules
90
91 httpd-service-type
92
93 nginx-configuration
94 nginx-configuration?
95 nginx-configuration-nginx
96 nginx-configuration-log-directory
97 nginx-configuration-run-directory
98 nginx-configuration-server-blocks
99 nginx-configuration-upstream-blocks
100 nginx-configuration-server-names-hash-bucket-size
101 nginx-configuration-server-names-hash-bucket-max-size
102 nginx-configuration-modules
103 nginx-configuration-global-directives
104 nginx-configuration-extra-content
105 nginx-configuration-file
106
107 nginx-server-configuration
108 nginx-server-configuration?
109 nginx-server-configuration-listen
110 nginx-server-configuration-server-name
111 nginx-server-configuration-root
112 nginx-server-configuration-locations
113 nginx-server-configuration-index
114 nginx-server-configuration-ssl-certificate
115 nginx-server-configuration-ssl-certificate-key
116 nginx-server-configuration-server-tokens?
117 nginx-server-configuration-raw-content
118
119 nginx-upstream-configuration
120 nginx-upstream-configuration?
121 nginx-upstream-configuration-name
122 nginx-upstream-configuration-servers
123
124 nginx-location-configuration
125 nginx-location-configuration?
126 nginx-location-configuration-uri
127 nginx-location-configuration-body
128
129 nginx-named-location-configuration
130 nginx-named-location-configuration?
131 nginx-named-location-configuration-name
132 nginx-named-location-configuration-body
133
134 nginx-service
135 nginx-service-type
136
137 fcgiwrap-configuration
138 fcgiwrap-configuration?
139 fcgiwrap-service-type
140
141 php-fpm-configuration
142 make-php-fpm-configuration
143 php-fpm-configuration?
144 php-fpm-configuration-php
145 php-fpm-configuration-socket
146 php-fpm-configuration-user
147 php-fpm-configuration-group
148 php-fpm-configuration-socket-user
149 php-fpm-configuration-socket-group
150 php-fpm-configuration-pid-file
151 php-fpm-configuration-log-file
152 php-fpm-configuration-process-manager
153 php-fpm-configuration-display-errors
154 php-fpm-configuration-timezone
155 php-fpm-configuration-workers-log-file
156 php-fpm-configuration-file
157 php-fpm-configuration-php-ini-file
158
159 php-fpm-dynamic-process-manager-configuration
160 make-php-fpm-dynamic-process-manager-configuration
161 php-fpm-dynamic-process-manager-configuration?
162 php-fpm-dynamic-process-manager-configuration-max-children
163 php-fpm-dynamic-process-manager-configuration-start-servers
164 php-fpm-dynamic-process-manager-configuration-min-spare-servers
165 php-fpm-dynamic-process-manager-configuration-max-spare-servers
166
167 php-fpm-static-process-manager-configuration
168 make-php-fpm-static-process-manager-configuration
169 php-fpm-static-process-manager-configuration?
170 php-fpm-static-process-manager-configuration-max-children
171
172 php-fpm-on-demand-process-manager-configuration
173 make-php-fpm-on-demand-process-manager-configuration
174 php-fpm-on-demand-process-manager-configuration?
175 php-fpm-on-demand-process-manager-configuration-max-children
176 php-fpm-on-demand-process-manager-configuration-process-idle-timeout
177
178 php-fpm-service-type
179 nginx-php-location
180
181 cat-avatar-generator-service
182
183 hpcguix-web-configuration
184 hpcguix-web-configuration?
185 hpcguix-web-service-type
186
187 tailon-configuration-file
188 tailon-configuration-file?
189 tailon-configuration-file-files
190 tailon-configuration-file-bind
191 tailon-configuration-file-relative-root
192 tailon-configuration-file-allow-transfers?
193 tailon-configuration-file-follow-names?
194 tailon-configuration-file-tail-lines
195 tailon-configuration-file-allowed-commands
196 tailon-configuration-file-debug?
197 tailon-configuration-file-http-auth
198 tailon-configuration-file-users
199
200 tailon-configuration
201 tailon-configuration?
202 tailon-configuration-config-file
203 tailon-configuration-package
204
205 tailon-service-type
206
207 varnish-configuration
208 varnish-configuration?
209 varnish-configuration-package
210 varnish-configuration-name
211 varnish-configuration-backend
212 varnish-configuration-vcl
213 varnish-configuration-listen
214 varnish-configuration-storage
215 varnish-configuration-parameters
216 varnish-configuration-extra-options
217
218 varnish-service-type
219
220 patchwork-database-configuration
221 patchwork-database-configuration?
222 patchwork-database-configuration-engine
223 patchwork-database-configuration-name
224 patchwork-database-configuration-user
225 patchwork-database-configuration-password
226 patchwork-database-configuration-host
227 patchwork-database-configuration-port
228
229 patchwork-settings-module
230 patchwork-settings-module?
231 patchwork-settings-module-database-configuration
232 patchwork-settings-module-secret-key
233 patchwork-settings-module-allowed-hosts
234 patchwork-settings-module-default-from-email
235 patchwork-settings-module-static-url
236 patchwork-settings-module-admins
237 patchwork-settings-module-debug?
238 patchwork-settings-module-enable-rest-api?
239 patchwork-settings-module-enable-xmlrpc?
240 patchwork-settings-module-force-https-links?
241 patchwork-settings-module-extra-settings
242
243 patchwork-configuration
244 patchwork-configuration?
245 patchwork-configuration-patchwork
246 patchwork-configuration-settings-module
247 patchwork-configuration-domain
248
249 patchwork-virtualhost
250 patchwork-service-type
251
252 mumi-configuration
253 mumi-configuration?
254 mumi-configuration-mumi
255 mumi-configuration-mailer?
256 mumi-configuration-sender
257 mumi-configuration-smtp
258
259 mumi-service-type
260
261 gmnisrv-configuration
262 gmnisrv-configuration?
263 gmnisrv-configuration-package
264 gmnisrv-configuration-config-file
265
266 gmnisrv-service-type))
267
268 ;;; Commentary:
269 ;;;
270 ;;; Web services.
271 ;;;
272 ;;; Code:
273
274 (define-record-type* <httpd-module>
275 httpd-module make-httpd-module
276 httpd-module?
277 (name httpd-load-module-name)
278 (file httpd-load-module-file))
279
280 ;; Default modules for the httpd-service-type, taken from etc/httpd/httpd.conf
281 ;; file in the httpd package.
282 (define %default-httpd-modules
283 (map (match-lambda
284 ((name file)
285 (httpd-module
286 (name name)
287 (file file))))
288 '(("authn_file_module" "modules/mod_authn_file.so")
289 ("authn_core_module" "modules/mod_authn_core.so")
290 ("authz_host_module" "modules/mod_authz_host.so")
291 ("authz_groupfile_module" "modules/mod_authz_groupfile.so")
292 ("authz_user_module" "modules/mod_authz_user.so")
293 ("authz_core_module" "modules/mod_authz_core.so")
294 ("access_compat_module" "modules/mod_access_compat.so")
295 ("auth_basic_module" "modules/mod_auth_basic.so")
296 ("reqtimeout_module" "modules/mod_reqtimeout.so")
297 ("filter_module" "modules/mod_filter.so")
298 ("mime_module" "modules/mod_mime.so")
299 ("log_config_module" "modules/mod_log_config.so")
300 ("env_module" "modules/mod_env.so")
301 ("headers_module" "modules/mod_headers.so")
302 ("setenvif_module" "modules/mod_setenvif.so")
303 ("version_module" "modules/mod_version.so")
304 ("unixd_module" "modules/mod_unixd.so")
305 ("status_module" "modules/mod_status.so")
306 ("autoindex_module" "modules/mod_autoindex.so")
307 ("dir_module" "modules/mod_dir.so")
308 ("alias_module" "modules/mod_alias.so"))))
309
310 (define-record-type* <httpd-config-file>
311 httpd-config-file make-httpd-config-file
312 httpd-config-file?
313 (modules httpd-config-file-modules
314 (default %default-httpd-modules))
315 (server-root httpd-config-file-server-root
316 (default httpd))
317 (server-name httpd-config-file-server-name
318 (default #f))
319 (document-root httpd-config-file-document-root
320 (default "/srv/http"))
321 (listen httpd-config-file-listen
322 (default '("80")))
323 (pid-file httpd-config-file-pid-file
324 (default "/var/run/httpd"))
325 (error-log httpd-config-file-error-log
326 (default "/var/log/httpd/error_log"))
327 (user httpd-config-file-user
328 (default "httpd"))
329 (group httpd-config-file-group
330 (default "httpd"))
331 (extra-config httpd-config-file-extra-config
332 (default
333 (list "TypesConfig etc/httpd/mime.types"))))
334
335 (define-gexp-compiler (httpd-config-file-compiler
336 (file <httpd-config-file>) system target)
337 (match file
338 (($ <httpd-config-file> load-modules server-root server-name
339 document-root listen pid-file error-log
340 user group extra-config)
341 (gexp->derivation
342 "httpd.conf"
343 #~(call-with-output-file (ungexp output "out")
344 (lambda (port)
345 (display
346 (string-append
347 (ungexp-splicing
348 `(,@(append-map
349 (match-lambda
350 (($ <httpd-module> name module)
351 `("LoadModule " ,name " " ,module "\n")))
352 load-modules)
353 ,@`("ServerRoot " ,server-root "\n")
354 ,@(if server-name
355 `("ServerName " ,server-name "\n")
356 '())
357 ,@`("DocumentRoot " ,document-root "\n")
358 ,@(append-map
359 (lambda (listen-value)
360 `("Listen " ,listen-value "\n"))
361 listen)
362 ,@(if pid-file
363 `("Pidfile " ,pid-file "\n")
364 '())
365 ,@(if error-log
366 `("ErrorLog " ,error-log "\n")
367 '())
368 ,@(if user
369 `("User " ,user "\n")
370 '())
371 ,@(if group
372 `("Group " ,group "\n")
373 '())
374 "\n\n"
375 ,@extra-config)))
376 port)))
377 #:local-build? #t))))
378
379 (define-record-type <httpd-virtualhost>
380 (httpd-virtualhost addresses-and-ports contents)
381 httpd-virtualhost?
382 (addresses-and-ports httpd-virtualhost-addresses-and-ports)
383 (contents httpd-virtualhost-contents))
384
385 (define-record-type* <httpd-configuration>
386 httpd-configuration make-httpd-configuration
387 httpd-configuration?
388 (package httpd-configuration-package
389 (default httpd))
390 (pid-file httpd-configuration-pid-file
391 (default "/var/run/httpd"))
392 (config httpd-configuration-config
393 (default (httpd-config-file))))
394
395 (define %httpd-accounts
396 (list (user-group (name "httpd") (system? #t))
397 (user-account
398 (name "httpd")
399 (group "httpd")
400 (system? #t)
401 (comment "Apache HTTPD server user")
402 (home-directory "/var/empty")
403 (shell (file-append shadow "/sbin/nologin")))))
404
405 (define httpd-shepherd-services
406 (match-lambda
407 (($ <httpd-configuration> package pid-file config)
408 (list (shepherd-service
409 (provision '(httpd))
410 (documentation "The Apache HTTP Server")
411 (requirement '(networking))
412 (start #~(make-forkexec-constructor
413 `(#$(file-append package "/bin/httpd")
414 #$@(if config
415 (list "-f" config)
416 '()))
417 #:pid-file #$pid-file))
418 (stop #~(make-kill-destructor)))))))
419
420 (define httpd-activation
421 (match-lambda
422 (($ <httpd-configuration> package pid-file config)
423 (match-record
424 config
425 <httpd-config-file>
426 (error-log document-root)
427 #~(begin
428 (use-modules (guix build utils))
429
430 (mkdir-p #$(dirname error-log))
431 (mkdir-p #$document-root))))))
432
433 (define (httpd-process-extensions original-config extension-configs)
434 (let ((config (httpd-configuration-config
435 original-config)))
436 (if (httpd-config-file? config)
437 (httpd-configuration
438 (inherit original-config)
439 (config
440 (httpd-config-file
441 (inherit config)
442 (extra-config
443 (append (httpd-config-file-extra-config config)
444 (append-map
445 (match-lambda
446 (($ <httpd-virtualhost>
447 addresses-and-ports
448 contents)
449 `(,(string-append
450 "\n<VirtualHost " addresses-and-ports ">\n")
451 ,@contents
452 "\n</VirtualHost>\n"))
453 ((? string? x)
454 `("\n" ,x "\n"))
455 ((? list? x)
456 `("\n" ,@x "\n")))
457 extension-configs)))))))))
458
459 (define httpd-service-type
460 (service-type (name 'httpd)
461 (extensions
462 (list (service-extension shepherd-root-service-type
463 httpd-shepherd-services)
464 (service-extension activation-service-type
465 httpd-activation)
466 (service-extension account-service-type
467 (const %httpd-accounts))))
468 (compose concatenate)
469 (extend httpd-process-extensions)
470 (default-value
471 (httpd-configuration))))
472
473 (define-record-type* <nginx-server-configuration>
474 nginx-server-configuration make-nginx-server-configuration
475 nginx-server-configuration?
476 (listen nginx-server-configuration-listen
477 (default '("80" "443 ssl")))
478 (server-name nginx-server-configuration-server-name
479 (default (list 'default)))
480 (root nginx-server-configuration-root
481 (default "/srv/http"))
482 (locations nginx-server-configuration-locations
483 (default '()))
484 (index nginx-server-configuration-index
485 (default (list "index.html")))
486 (try-files nginx-server-configuration-try-files
487 (default '()))
488 (ssl-certificate nginx-server-configuration-ssl-certificate
489 (default #f))
490 (ssl-certificate-key nginx-server-configuration-ssl-certificate-key
491 (default #f))
492 (server-tokens? nginx-server-configuration-server-tokens?
493 (default #f))
494 (raw-content nginx-server-configuration-raw-content
495 (default '())))
496
497 (define-record-type* <nginx-upstream-configuration>
498 nginx-upstream-configuration make-nginx-upstream-configuration
499 nginx-upstream-configuration?
500 (name nginx-upstream-configuration-name)
501 (servers nginx-upstream-configuration-servers))
502
503 (define-record-type* <nginx-location-configuration>
504 nginx-location-configuration make-nginx-location-configuration
505 nginx-location-configuration?
506 (uri nginx-location-configuration-uri
507 (default #f))
508 (body nginx-location-configuration-body))
509
510 (define-record-type* <nginx-named-location-configuration>
511 nginx-named-location-configuration make-nginx-named-location-configuration
512 nginx-named-location-configuration?
513 (name nginx-named-location-configuration-name
514 (default #f))
515 (body nginx-named-location-configuration-body))
516
517 (define-record-type* <nginx-configuration>
518 nginx-configuration make-nginx-configuration
519 nginx-configuration?
520 (nginx nginx-configuration-nginx ;<package>
521 (default nginx))
522 (log-directory nginx-configuration-log-directory ;string
523 (default "/var/log/nginx"))
524 (run-directory nginx-configuration-run-directory ;string
525 (default "/var/run/nginx"))
526 (server-blocks nginx-configuration-server-blocks
527 (default '())) ;list of <nginx-server-configuration>
528 (upstream-blocks nginx-configuration-upstream-blocks
529 (default '())) ;list of <nginx-upstream-configuration>
530 (server-names-hash-bucket-size nginx-configuration-server-names-hash-bucket-size
531 (default #f))
532 (server-names-hash-bucket-max-size nginx-configuration-server-names-hash-bucket-max-size
533 (default #f))
534 (modules nginx-configuration-modules (default '()))
535 (global-directives nginx-configuration-global-directives
536 (default '((events . ()))))
537 (lua-package-path nginx-lua-package-path ;list of <package>
538 (default #f))
539 (lua-package-cpath nginx-lua-package-cpath ;list of <package>
540 (default #f))
541 (extra-content nginx-configuration-extra-content
542 (default ""))
543 (file nginx-configuration-file ;#f | string | file-like
544 (default #f)))
545
546 (define (config-domain-strings names)
547 "Return a string denoting the nginx config representation of NAMES, a list
548 of domain names."
549 (map (match-lambda
550 ('default "_ ")
551 ((? string? str) (list str " ")))
552 names))
553
554 (define (config-index-strings names)
555 "Return a string denoting the nginx config representation of NAMES, a list
556 of index files."
557 (map (match-lambda
558 ((? string? str) (list str " ")))
559 names))
560
561 (define (emit-load-module module)
562 (list "load_module " module ";\n"))
563
564 (define emit-global-directive
565 (match-lambda
566 ((key . (? list? alist))
567 (format #f "~a { ~{~a~}}~%" key (map emit-global-directive alist)))
568 ((key . value)
569 (format #f "~a ~a;~%" key value))))
570
571 (define emit-nginx-location-config
572 (match-lambda
573 (($ <nginx-location-configuration> uri body)
574 (list
575 " location " uri " {\n"
576 (map (lambda (x) (list " " x "\n")) body)
577 " }\n"))
578 (($ <nginx-named-location-configuration> name body)
579 (list
580 " location @" name " {\n"
581 (map (lambda (x) (list " " x "\n")) body)
582 " }\n"))))
583
584 (define (emit-nginx-server-config server)
585 (let ((listen (nginx-server-configuration-listen server))
586 (server-name (nginx-server-configuration-server-name server))
587 (ssl-certificate (nginx-server-configuration-ssl-certificate server))
588 (ssl-certificate-key
589 (nginx-server-configuration-ssl-certificate-key server))
590 (root (nginx-server-configuration-root server))
591 (index (nginx-server-configuration-index server))
592 (try-files (nginx-server-configuration-try-files server))
593 (server-tokens? (nginx-server-configuration-server-tokens? server))
594 (locations (nginx-server-configuration-locations server))
595 (raw-content (nginx-server-configuration-raw-content server)))
596 (define-syntax-parameter <> (syntax-rules ()))
597 (define-syntax-rule (and/l x tail ...)
598 (let ((x* x))
599 (if x*
600 (syntax-parameterize ((<> (identifier-syntax x*)))
601 (list tail ...))
602 '())))
603 (list
604 " server {\n"
605 (map (lambda (directive) (list " listen " directive ";\n")) listen)
606 " server_name " (config-domain-strings server-name) ";\n"
607 (and/l ssl-certificate " ssl_certificate " <> ";\n")
608 (and/l ssl-certificate-key " ssl_certificate_key " <> ";\n")
609 " root " root ";\n"
610 " index " (config-index-strings index) ";\n"
611 (if (not (nil? try-files))
612 (and/l (config-index-strings try-files) " try_files " <> ";\n")
613 "")
614 " server_tokens " (if server-tokens? "on" "off") ";\n"
615 "\n"
616 (map emit-nginx-location-config locations)
617 "\n"
618 (map (lambda (x) (list " " x "\n")) raw-content)
619 " }\n")))
620
621 (define (emit-nginx-upstream-config upstream)
622 (list
623 " upstream " (nginx-upstream-configuration-name upstream) " {\n"
624 (map (lambda (server)
625 (simple-format #f " server ~A;\n" server))
626 (nginx-upstream-configuration-servers upstream))
627 " }\n"))
628
629 (define (flatten . lst)
630 "Return a list that recursively concatenates all sub-lists of LST."
631 (define (flatten1 head out)
632 (if (list? head)
633 (fold-right flatten1 out head)
634 (cons head out)))
635 (fold-right flatten1 '() lst))
636
637 (define (default-nginx-config config)
638 (match-record config
639 <nginx-configuration>
640 (nginx log-directory run-directory
641 server-blocks upstream-blocks
642 server-names-hash-bucket-size
643 server-names-hash-bucket-max-size
644 modules
645 global-directives
646 lua-package-path
647 lua-package-cpath
648 extra-content)
649 (apply mixed-text-file "nginx.conf"
650 (flatten
651 "user nginx nginx;\n"
652 "pid " run-directory "/pid;\n"
653 "error_log " log-directory "/error.log info;\n"
654 (map emit-load-module modules)
655 (map emit-global-directive global-directives)
656 "http {\n"
657 " client_body_temp_path " run-directory "/client_body_temp;\n"
658 " proxy_temp_path " run-directory "/proxy_temp;\n"
659 " fastcgi_temp_path " run-directory "/fastcgi_temp;\n"
660 " uwsgi_temp_path " run-directory "/uwsgi_temp;\n"
661 " scgi_temp_path " run-directory "/scgi_temp;\n"
662 " access_log " log-directory "/access.log;\n"
663 " include " nginx "/share/nginx/conf/mime.types;\n"
664 (if lua-package-path
665 #~(format #f " lua_package_path ~s;~%"
666 (string-join (map (lambda (path)
667 (string-append path "/lib/?.lua"))
668 '#$lua-package-path)
669 ";"))
670 "")
671 (if lua-package-cpath
672 #~(format #f " lua_package_cpath ~s;~%"
673 (string-join (map (lambda (cpath)
674 (string-append cpath "/lib/lua/?.lua"))
675 '#$lua-package-cpath)
676 ";"))
677 "")
678 (if server-names-hash-bucket-size
679 (string-append
680 " server_names_hash_bucket_size "
681 (number->string server-names-hash-bucket-size)
682 ";\n")
683 "")
684 (if server-names-hash-bucket-max-size
685 (string-append
686 " server_names_hash_bucket_max_size "
687 (number->string server-names-hash-bucket-max-size)
688 ";\n")
689 "")
690 "\n"
691 (map emit-nginx-upstream-config upstream-blocks)
692 (map emit-nginx-server-config server-blocks)
693 extra-content
694 "\n}\n"))))
695
696 (define %nginx-accounts
697 (list (user-group (name "nginx") (system? #t))
698 (user-account
699 (name "nginx")
700 (group "nginx")
701 (system? #t)
702 (comment "nginx server user")
703 (home-directory "/var/empty")
704 (shell (file-append shadow "/sbin/nologin")))))
705
706 (define (nginx-activation config)
707 (match-record config
708 <nginx-configuration>
709 (nginx log-directory run-directory file)
710 #~(begin
711 (use-modules (guix build utils))
712
713 (format #t "creating nginx log directory '~a'~%" #$log-directory)
714 (mkdir-p #$log-directory)
715 (format #t "creating nginx run directory '~a'~%" #$run-directory)
716 (mkdir-p #$run-directory)
717 (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory)
718 (mkdir-p (string-append #$run-directory "/client_body_temp"))
719 (mkdir-p (string-append #$run-directory "/proxy_temp"))
720 (mkdir-p (string-append #$run-directory "/fastcgi_temp"))
721 (mkdir-p (string-append #$run-directory "/uwsgi_temp"))
722 (mkdir-p (string-append #$run-directory "/scgi_temp"))
723 ;; Start-up logs. Once configuration is loaded, nginx switches to
724 ;; log-directory.
725 (mkdir-p (string-append #$run-directory "/logs"))
726 ;; Check configuration file syntax.
727 (system* (string-append #$nginx "/sbin/nginx")
728 "-c" #$(or file
729 (default-nginx-config config))
730 "-p" #$run-directory
731 "-t"))))
732
733 (define (nginx-shepherd-service config)
734 (match-record config
735 <nginx-configuration>
736 (nginx file run-directory)
737 (let* ((nginx-binary (file-append nginx "/sbin/nginx"))
738 (pid-file (in-vicinity run-directory "pid"))
739 (nginx-action
740 (lambda args
741 #~(lambda _
742 (invoke #$nginx-binary "-c"
743 #$(or file
744 (default-nginx-config config))
745 #$@args)
746 (match '#$args
747 (("-s" . _) #f)
748 (_
749 ;; When FILE is true, we cannot be sure that PID-FILE will
750 ;; be created, so assume it won't show up. When FILE is
751 ;; false, read PID-FILE.
752 #$(if file
753 #~#t
754 #~(read-pid-file #$pid-file))))))))
755
756 ;; TODO: Add 'reload' action.
757 (list (shepherd-service
758 (provision '(nginx))
759 (documentation "Run the nginx daemon.")
760 (requirement '(user-processes loopback))
761 (modules `((ice-9 match)
762 ,@%default-modules))
763 (start (nginx-action "-p" run-directory))
764 (stop (nginx-action "-s" "stop")))))))
765
766 (define nginx-service-type
767 (service-type (name 'nginx)
768 (extensions
769 (list (service-extension shepherd-root-service-type
770 nginx-shepherd-service)
771 (service-extension activation-service-type
772 nginx-activation)
773 (service-extension account-service-type
774 (const %nginx-accounts))))
775 (compose concatenate)
776 (extend (lambda (config servers)
777 (nginx-configuration
778 (inherit config)
779 (server-blocks
780 (append (nginx-configuration-server-blocks config)
781 servers)))))
782 (default-value (nginx-configuration))
783 (description "Run the nginx Web server.")))
784
785 (define-record-type* <fcgiwrap-configuration> fcgiwrap-configuration
786 make-fcgiwrap-configuration
787 fcgiwrap-configuration?
788 (package fcgiwrap-configuration-package ;<package>
789 (default fcgiwrap))
790 (socket fcgiwrap-configuration-socket
791 (default "tcp:127.0.0.1:9000"))
792 (user fcgiwrap-configuration-user
793 (default "fcgiwrap"))
794 (group fcgiwrap-configuration-group
795 (default "fcgiwrap")))
796
797 (define fcgiwrap-accounts
798 (match-lambda
799 (($ <fcgiwrap-configuration> package socket user group)
800 (filter identity
801 (list
802 (and (equal? group "fcgiwrap")
803 (user-group
804 (name "fcgiwrap")
805 (system? #t)))
806 (and (equal? user "fcgiwrap")
807 (user-account
808 (name "fcgiwrap")
809 (group group)
810 (system? #t)
811 (comment "Fcgiwrap Daemon")
812 (home-directory "/var/empty")
813 (shell (file-append shadow "/sbin/nologin")))))))))
814
815 (define fcgiwrap-shepherd-service
816 (match-lambda
817 (($ <fcgiwrap-configuration> package socket user group)
818 (list (shepherd-service
819 (provision '(fcgiwrap))
820 (documentation "Run the fcgiwrap daemon.")
821 (requirement '(networking))
822 (start #~(make-forkexec-constructor
823 '(#$(file-append package "/sbin/fcgiwrap")
824 "-s" #$socket)
825 #:user #$user #:group #$group))
826 (stop #~(make-kill-destructor)))))))
827
828 (define fcgiwrap-activation
829 (match-lambda
830 (($ <fcgiwrap-configuration> package socket user group)
831 #~(begin
832 ;; When listening on a unix socket, create a parent directory for the
833 ;; socket with the correct permissions.
834 (when (string-prefix? "unix:" #$socket)
835 (let ((run-directory
836 (dirname (substring #$socket (string-length "unix:")))))
837 (mkdir-p run-directory)
838 (chown run-directory
839 (passwd:uid (getpw #$user))
840 (group:gid (getgr #$group)))))))))
841
842 (define fcgiwrap-service-type
843 (service-type (name 'fcgiwrap)
844 (extensions
845 (list (service-extension shepherd-root-service-type
846 fcgiwrap-shepherd-service)
847 (service-extension account-service-type
848 fcgiwrap-accounts)
849 (service-extension activation-service-type
850 fcgiwrap-activation)))
851 (default-value (fcgiwrap-configuration))))
852
853 (define-record-type* <php-fpm-configuration> php-fpm-configuration
854 make-php-fpm-configuration
855 php-fpm-configuration?
856 (php php-fpm-configuration-php ;<package>
857 (default php))
858 (socket php-fpm-configuration-socket
859 (default (string-append "/var/run/php"
860 (version-major (package-version php))
861 "-fpm.sock")))
862 (user php-fpm-configuration-user
863 (default "php-fpm"))
864 (group php-fpm-configuration-group
865 (default "php-fpm"))
866 (socket-user php-fpm-configuration-socket-user
867 (default "php-fpm"))
868 (socket-group php-fpm-configuration-socket-group
869 (default "nginx"))
870 (pid-file php-fpm-configuration-pid-file
871 (default (string-append "/var/run/php"
872 (version-major (package-version php))
873 "-fpm.pid")))
874 (log-file php-fpm-configuration-log-file
875 (default (string-append "/var/log/php"
876 (version-major (package-version php))
877 "-fpm.log")))
878 (process-manager php-fpm-configuration-process-manager
879 (default (php-fpm-dynamic-process-manager-configuration)))
880 (display-errors php-fpm-configuration-display-errors
881 (default #f))
882 (timezone php-fpm-configuration-timezone
883 (default #f))
884 (workers-log-file php-fpm-configuration-workers-log-file
885 (default (string-append "/var/log/php"
886 (version-major (package-version php))
887 "-fpm.www.log")))
888 (file php-fpm-configuration-file ;#f | file-like
889 (default #f))
890 (php-ini-file php-fpm-configuration-php-ini-file ;#f | file-like
891 (default #f)))
892
893 (define-record-type* <php-fpm-dynamic-process-manager-configuration>
894 php-fpm-dynamic-process-manager-configuration
895 make-php-fpm-dynamic-process-manager-configuration
896 php-fpm-dynamic-process-manager-configuration?
897 (max-children php-fpm-dynamic-process-manager-configuration-max-children
898 (default 5))
899 (start-servers php-fpm-dynamic-process-manager-configuration-start-servers
900 (default 2))
901 (min-spare-servers php-fpm-dynamic-process-manager-configuration-min-spare-servers
902 (default 1))
903 (max-spare-servers php-fpm-dynamic-process-manager-configuration-max-spare-servers
904 (default 3)))
905
906 (define-record-type* <php-fpm-static-process-manager-configuration>
907 php-fpm-static-process-manager-configuration
908 make-php-fpm-static-process-manager-configuration
909 php-fpm-static-process-manager-configuration?
910 (max-children php-fpm-static-process-manager-configuration-max-children
911 (default 5)))
912
913 (define-record-type* <php-fpm-on-demand-process-manager-configuration>
914 php-fpm-on-demand-process-manager-configuration
915 make-php-fpm-on-demand-process-manager-configuration
916 php-fpm-on-demand-process-manager-configuration?
917 (max-children php-fpm-on-demand-process-manager-configuration-max-children
918 (default 5))
919 (process-idle-timeout php-fpm-on-demand-process-manager-configuration-process-idle-timeout
920 (default 10)))
921
922 (define php-fpm-accounts
923 (match-lambda
924 (($ <php-fpm-configuration> php socket user group socket-user socket-group _ _ _ _ _ _)
925 (list
926 (user-group (name "php-fpm") (system? #t))
927 (user-group
928 (name group)
929 (system? #t))
930 (user-account
931 (name user)
932 (group group)
933 (supplementary-groups '("php-fpm"))
934 (system? #t)
935 (comment "php-fpm daemon user")
936 (home-directory "/var/empty")
937 (shell (file-append shadow "/sbin/nologin")))))))
938
939 (define (default-php-fpm-config socket user group socket-user socket-group
940 pid-file log-file pm display-errors timezone workers-log-file)
941 (apply mixed-text-file "php-fpm.conf"
942 (flatten
943 "[global]\n"
944 "pid =" pid-file "\n"
945 "error_log =" log-file "\n"
946 "[www]\n"
947 "user =" user "\n"
948 "group =" group "\n"
949 "listen =" socket "\n"
950 "listen.owner =" socket-user "\n"
951 "listen.group =" socket-group "\n"
952
953 (if timezone
954 (string-append "php_admin_value[date.timezone] = \"" timezone "\"\n")
955 "")
956
957 (match pm
958 (($ <php-fpm-dynamic-process-manager-configuration>
959 pm.max-children
960 pm.start-servers
961 pm.min-spare-servers
962 pm.max-spare-servers)
963 (list
964 "pm = dynamic\n"
965 "pm.max_children =" (number->string pm.max-children) "\n"
966 "pm.start_servers =" (number->string pm.start-servers) "\n"
967 "pm.min_spare_servers =" (number->string pm.min-spare-servers) "\n"
968 "pm.max_spare_servers =" (number->string pm.max-spare-servers) "\n"))
969
970 (($ <php-fpm-static-process-manager-configuration>
971 pm.max-children)
972 (list
973 "pm = static\n"
974 "pm.max_children =" (number->string pm.max-children) "\n"))
975
976 (($ <php-fpm-on-demand-process-manager-configuration>
977 pm.max-children
978 pm.process-idle-timeout)
979 (list
980 "pm = ondemand\n"
981 "pm.max_children =" (number->string pm.max-children) "\n"
982 "pm.process_idle_timeout =" (number->string pm.process-idle-timeout) "s\n")))
983
984
985 "php_flag[display_errors] = " (if display-errors "on" "off") "\n"
986
987 (if workers-log-file
988 (list "catch_workers_output = yes\n"
989 "php_admin_value[error_log] =" workers-log-file "\n"
990 "php_admin_flag[log_errors] = on\n")
991 (list "catch_workers_output = no\n")))))
992
993 (define php-fpm-shepherd-service
994 (match-lambda
995 (($ <php-fpm-configuration> php socket user group socket-user socket-group
996 pid-file log-file pm display-errors
997 timezone workers-log-file file php-ini-file)
998 (list (shepherd-service
999 (provision '(php-fpm))
1000 (documentation "Run the php-fpm daemon.")
1001 (requirement '(networking))
1002 (start #~(make-forkexec-constructor
1003 '(#$(file-append php "/sbin/php-fpm")
1004 "--fpm-config"
1005 #$(or file
1006 (default-php-fpm-config socket user group
1007 socket-user socket-group pid-file log-file
1008 pm display-errors timezone workers-log-file))
1009 #$@(if php-ini-file
1010 `("-c" ,php-ini-file)
1011 '()))
1012 #:pid-file #$pid-file))
1013 (stop #~(make-kill-destructor)))))))
1014
1015 (define (php-fpm-activation config)
1016 #~(begin
1017 (use-modules (guix build utils))
1018 (let* ((user (getpwnam #$(php-fpm-configuration-user config)))
1019 (touch (lambda (file-name)
1020 (call-with-output-file file-name (const #t))))
1021 (workers-log-file
1022 #$(php-fpm-configuration-workers-log-file config))
1023 (init-log-file
1024 (lambda (file-name)
1025 (when workers-log-file
1026 (when (not (file-exists? file-name))
1027 (touch file-name))
1028 (chown file-name (passwd:uid user) (passwd:gid user))
1029 (chmod file-name #o660)))))
1030 (init-log-file #$(php-fpm-configuration-log-file config))
1031 (init-log-file workers-log-file))))
1032
1033
1034 (define php-fpm-service-type
1035 (service-type
1036 (name 'php-fpm)
1037 (description
1038 "Run @command{php-fpm} to provide a fastcgi socket for calling php through
1039 a webserver.")
1040 (extensions
1041 (list (service-extension shepherd-root-service-type
1042 php-fpm-shepherd-service)
1043 (service-extension activation-service-type
1044 php-fpm-activation)
1045 (service-extension account-service-type
1046 php-fpm-accounts)))
1047 (default-value (php-fpm-configuration))))
1048
1049 (define* (nginx-php-location
1050 #:key
1051 (nginx-package nginx)
1052 (socket (string-append "/var/run/php"
1053 (version-major (package-version php))
1054 "-fpm.sock")))
1055 "Return a nginx-location-configuration that makes nginx run .php files."
1056 (nginx-location-configuration
1057 (uri "~ \\.php$")
1058 (body (list
1059 "fastcgi_split_path_info ^(.+\\.php)(/.+)$;"
1060 (string-append "fastcgi_pass unix:" socket ";")
1061 "fastcgi_index index.php;"
1062 (list "include " nginx-package "/share/nginx/conf/fastcgi.conf;")))))
1063
1064 (define* (cat-avatar-generator-service
1065 #:key
1066 (cache-dir "/var/cache/cat-avatar-generator")
1067 (package cat-avatar-generator)
1068 (configuration (nginx-server-configuration)))
1069 (simple-service
1070 'cat-http-server nginx-service-type
1071 (list (nginx-server-configuration
1072 (inherit configuration)
1073 (locations
1074 (cons
1075 (let ((base (nginx-php-location)))
1076 (nginx-location-configuration
1077 (inherit base)
1078 (body (list (string-append "fastcgi_param CACHE_DIR \""
1079 cache-dir "\";")
1080 (nginx-location-configuration-body base)))))
1081 (nginx-server-configuration-locations configuration)))
1082 (root #~(string-append #$package
1083 "/share/web/cat-avatar-generator"))))))
1084
1085 \f
1086 (define-record-type* <hpcguix-web-configuration>
1087 hpcguix-web-configuration make-hpcguix-web-configuration
1088 hpcguix-web-configuration?
1089
1090 (package hpcguix-web-package (default hpcguix-web)) ;<package>
1091
1092 ;; Specs is gexp of hpcguix-web configuration file
1093 (specs hpcguix-web-configuration-specs))
1094
1095 (define %hpcguix-web-accounts
1096 (list (user-group
1097 (name "hpcguix-web")
1098 (system? #t))
1099 (user-account
1100 (name "hpcguix-web")
1101 (group "hpcguix-web")
1102 (system? #t)
1103 (comment "hpcguix-web")
1104 (home-directory "/var/empty")
1105 (shell (file-append shadow "/sbin/nologin")))))
1106
1107 (define %hpcguix-web-activation
1108 (with-imported-modules '((guix build utils))
1109 #~(begin
1110 (use-modules (guix build utils)
1111 (ice-9 ftw))
1112
1113 (let ((home-dir "/var/cache/guix/web")
1114 (user (getpwnam "hpcguix-web")))
1115 (mkdir-p home-dir)
1116 (chown home-dir (passwd:uid user) (passwd:gid user))
1117 (chmod home-dir #o755)
1118
1119 ;; Remove stale 'packages.json.lock' file (and other lock files, if
1120 ;; any) since that would prevent 'packages.json' from being updated.
1121 (for-each (lambda (lock)
1122 (delete-file (string-append home-dir "/" lock)))
1123 (scandir home-dir
1124 (lambda (file)
1125 (string-suffix? ".lock" file))))))))
1126
1127 (define %hpcguix-web-log-file
1128 "/var/log/hpcguix-web.log")
1129
1130 (define %hpcguix-web-log-rotations
1131 (list (log-rotation
1132 (files (list %hpcguix-web-log-file))
1133 (frequency 'weekly))))
1134
1135 (define (hpcguix-web-shepherd-service config)
1136 (let ((specs (hpcguix-web-configuration-specs config))
1137 (hpcguix-web (hpcguix-web-package config)))
1138 (with-imported-modules (source-module-closure
1139 '((gnu build shepherd)))
1140 (shepherd-service
1141 (documentation "hpcguix-web daemon")
1142 (provision '(hpcguix-web))
1143 (requirement '(networking))
1144 (start #~(make-forkexec-constructor
1145 (list #$(file-append hpcguix-web "/bin/run")
1146 (string-append "--config="
1147 #$(scheme-file "hpcguix-web.scm" specs)))
1148 #:user "hpcguix-web"
1149 #:group "hpcguix-web"
1150 #:environment-variables
1151 (list "XDG_CACHE_HOME=/var/cache/guix/web"
1152 "SSL_CERT_DIR=/etc/ssl/certs")
1153 #:log-file #$%hpcguix-web-log-file))
1154 (stop #~(make-kill-destructor))))))
1155
1156 (define hpcguix-web-service-type
1157 (service-type
1158 (name 'hpcguix-web)
1159 (description "Run the hpcguix-web server.")
1160 (extensions
1161 (list (service-extension account-service-type
1162 (const %hpcguix-web-accounts))
1163 (service-extension activation-service-type
1164 (const %hpcguix-web-activation))
1165 (service-extension rottlog-service-type
1166 (const %hpcguix-web-log-rotations))
1167 (service-extension shepherd-root-service-type
1168 (compose list hpcguix-web-shepherd-service))))))
1169
1170 \f
1171 ;;;
1172 ;;; Tailon
1173 ;;;
1174
1175 (define-record-type* <tailon-configuration-file>
1176 tailon-configuration-file make-tailon-configuration-file
1177 tailon-configuration-file?
1178 (files tailon-configuration-file-files
1179 (default '("/var/log")))
1180 (bind tailon-configuration-file-bind
1181 (default "localhost:8080"))
1182 (relative-root tailon-configuration-file-relative-root
1183 (default #f))
1184 (allow-transfers? tailon-configuration-file-allow-transfers?
1185 (default #t))
1186 (follow-names? tailon-configuration-file-follow-names?
1187 (default #t))
1188 (tail-lines tailon-configuration-file-tail-lines
1189 (default 200))
1190 (allowed-commands tailon-configuration-file-allowed-commands
1191 (default '("tail" "grep" "awk")))
1192 (debug? tailon-configuration-file-debug?
1193 (default #f))
1194 (wrap-lines tailon-configuration-file-wrap-lines
1195 (default #t))
1196 (http-auth tailon-configuration-file-http-auth
1197 (default #f))
1198 (users tailon-configuration-file-users
1199 (default #f)))
1200
1201 (define (tailon-configuration-files-string files)
1202 (string-append
1203 "\n"
1204 (string-join
1205 (map
1206 (lambda (x)
1207 (string-append
1208 " - "
1209 (cond
1210 ((string? x)
1211 (simple-format #f "'~A'" x))
1212 ((list? x)
1213 (string-join
1214 (cons (simple-format #f "'~A':" (car x))
1215 (map
1216 (lambda (x) (simple-format #f " - '~A'" x))
1217 (cdr x)))
1218 "\n"))
1219 (else (error x)))))
1220 files)
1221 "\n")))
1222
1223 (define-gexp-compiler (tailon-configuration-file-compiler
1224 (file <tailon-configuration-file>) system target)
1225 (match file
1226 (($ <tailon-configuration-file> files bind relative-root
1227 allow-transfers? follow-names?
1228 tail-lines allowed-commands debug?
1229 wrap-lines http-auth users)
1230 (text-file
1231 "tailon-config.yaml"
1232 (string-concatenate
1233 (filter-map
1234 (match-lambda
1235 ((key . #f) #f)
1236 ((key . value) (string-append key ": " value "\n")))
1237
1238 `(("files" . ,(tailon-configuration-files-string files))
1239 ("bind" . ,bind)
1240 ("relative-root" . ,relative-root)
1241 ("allow-transfers" . ,(if allow-transfers? "true" "false"))
1242 ("follow-names" . ,(if follow-names? "true" "false"))
1243 ("tail-lines" . ,(number->string tail-lines))
1244 ("commands" . ,(string-append "["
1245 (string-join allowed-commands ", ")
1246 "]"))
1247 ("debug" . ,(if debug? "true" #f))
1248 ("wrap-lines" . ,(if wrap-lines "true" "false"))
1249 ("http-auth" . ,http-auth)
1250 ("users" . ,(if users
1251 (string-concatenate
1252 (cons "\n"
1253 (map (match-lambda
1254 ((user . pass)
1255 (string-append
1256 " " user ":" pass)))
1257 users)))
1258 #f)))))))))
1259
1260 (define-record-type* <tailon-configuration>
1261 tailon-configuration make-tailon-configuration
1262 tailon-configuration?
1263 (config-file tailon-configuration-config-file
1264 (default (tailon-configuration-file)))
1265 (package tailon-configuration-package
1266 (default tailon)))
1267
1268 (define tailon-shepherd-service
1269 (match-lambda
1270 (($ <tailon-configuration> config-file package)
1271 (list (shepherd-service
1272 (provision '(tailon))
1273 (documentation "Run the tailon daemon.")
1274 (start #~(make-forkexec-constructor
1275 `(,(string-append #$package "/bin/tailon")
1276 "-c" ,#$config-file)
1277 #:user "tailon"
1278 #:group "tailon"))
1279 (stop #~(make-kill-destructor)))))))
1280
1281 (define %tailon-accounts
1282 (list (user-group (name "tailon") (system? #t))
1283 (user-account
1284 (name "tailon")
1285 (group "tailon")
1286 (system? #t)
1287 (comment "tailon")
1288 (home-directory "/var/empty")
1289 (shell (file-append shadow "/sbin/nologin")))))
1290
1291 (define tailon-service-type
1292 (service-type
1293 (name 'tailon)
1294 (description
1295 "Run Tailon, a Web application for monitoring, viewing, and searching log
1296 files.")
1297 (extensions
1298 (list (service-extension shepherd-root-service-type
1299 tailon-shepherd-service)
1300 (service-extension account-service-type
1301 (const %tailon-accounts))))
1302 (compose concatenate)
1303 (extend (lambda (parameter files)
1304 (tailon-configuration
1305 (inherit parameter)
1306 (config-file
1307 (let ((old-config-file
1308 (tailon-configuration-config-file parameter)))
1309 (tailon-configuration-file
1310 (inherit old-config-file)
1311 (files (append (tailon-configuration-file-files old-config-file)
1312 files))))))))
1313 (default-value (tailon-configuration))))
1314
1315 \f
1316 ;;;
1317 ;;; Varnish
1318 ;;;
1319
1320 (define-record-type* <varnish-configuration>
1321 varnish-configuration make-varnish-configuration
1322 varnish-configuration?
1323 (package varnish-configuration-package ;<package>
1324 (default varnish))
1325 (name varnish-configuration-name ;string
1326 (default "default"))
1327 (backend varnish-configuration-backend ;string
1328 (default "localhost:8080"))
1329 (vcl varnish-configuration-vcl ;#f | <file-like>
1330 (default #f))
1331 (listen varnish-configuration-listen ;list of strings
1332 (default '("localhost:80")))
1333 (storage varnish-configuration-storage ;list of strings
1334 (default '("malloc,128m")))
1335 (parameters varnish-configuration-parameters ;list of string pairs
1336 (default '()))
1337 (extra-options varnish-configuration-extra-options ;list of strings
1338 (default '())))
1339
1340 (define %varnish-accounts
1341 (list (user-group
1342 (name "varnish")
1343 (system? #t))
1344 (user-account
1345 (name "varnish")
1346 (group "varnish")
1347 (system? #t)
1348 (comment "Varnish Cache User")
1349 (home-directory "/var/varnish")
1350 (shell (file-append shadow "/sbin/nologin")))))
1351
1352 (define varnish-shepherd-service
1353 (match-lambda
1354 (($ <varnish-configuration> package name backend vcl listen storage
1355 parameters extra-options)
1356 (list (shepherd-service
1357 (provision (list (symbol-append 'varnish- (string->symbol name))))
1358 (documentation (string-append "The Varnish Web Accelerator"
1359 " (" name ")"))
1360 (requirement '(networking))
1361 (start #~(make-forkexec-constructor
1362 (list #$(file-append package "/sbin/varnishd")
1363 "-n" #$name
1364 #$@(if vcl
1365 #~("-f" #$vcl)
1366 #~("-b" #$backend))
1367 #$@(append-map (lambda (a) (list "-a" a)) listen)
1368 #$@(append-map (lambda (s) (list "-s" s)) storage)
1369 #$@(append-map (lambda (p)
1370 (list "-p" (format #f "~a=~a"
1371 (car p) (cdr p))))
1372 parameters)
1373 #$@extra-options)
1374 ;; Varnish will drop privileges to the "varnish" user when
1375 ;; it exists. Not passing #:user here allows the service
1376 ;; to bind to ports < 1024.
1377 #:pid-file (if (string-prefix? "/" #$name)
1378 (string-append #$name "/_.pid")
1379 (string-append "/var/varnish/" #$name "/_.pid"))))
1380 (stop #~(make-kill-destructor)))))))
1381
1382 (define varnish-service-type
1383 (service-type
1384 (name 'varnish)
1385 (description "Run the Varnish cache server.")
1386 (extensions
1387 (list (service-extension account-service-type
1388 (const %varnish-accounts))
1389 (service-extension shepherd-root-service-type
1390 varnish-shepherd-service)))
1391 (default-value
1392 (varnish-configuration))))
1393
1394 \f
1395 ;;;
1396 ;;; Patchwork
1397 ;;;
1398
1399 (define-record-type* <patchwork-database-configuration>
1400 patchwork-database-configuration make-patchwork-database-configuration
1401 patchwork-database-configuration?
1402 (engine patchwork-database-configuration-engine
1403 (default "django.db.backends.postgresql_psycopg2"))
1404 (name patchwork-database-configuration-name
1405 (default "patchwork"))
1406 (user patchwork-database-configuration-user
1407 (default "httpd"))
1408 (password patchwork-database-configuration-password
1409 (default ""))
1410 (host patchwork-database-configuration-host
1411 (default ""))
1412 (port patchwork-database-configuration-port
1413 (default "")))
1414
1415 (define-record-type* <patchwork-settings-module>
1416 patchwork-settings-module make-patchwork-settings-module
1417 patchwork-settings-module?
1418 (database-configuration patchwork-settings-module-database-configuration
1419 (default (patchwork-database-configuration)))
1420 (secret-key-file patchwork-settings-module-secret-key-file
1421 (default "/etc/patchwork/django-secret-key"))
1422 (allowed-hosts patchwork-settings-module-allowed-hosts)
1423 (default-from-email patchwork-settings-module-default-from-email)
1424 (static-url patchwork-settings-module-static-url
1425 (default "/static/"))
1426 (admins patchwork-settings-module-admins
1427 (default '()))
1428 (debug? patchwork-settings-module-debug?
1429 (default #f))
1430 (enable-rest-api? patchwork-settings-module-enable-rest-api?
1431 (default #t))
1432 (enable-xmlrpc? patchwork-settings-module-enable-xmlrpc?
1433 (default #t))
1434 (force-https-links? patchwork-settings-module-force-https-links?
1435 (default #t))
1436 (extra-settings patchwork-settings-module-extra-settings
1437 (default "")))
1438
1439 (define-record-type* <patchwork-configuration>
1440 patchwork-configuration make-patchwork-configuration
1441 patchwork-configuration?
1442 (patchwork patchwork-configuration-patchwork
1443 (default patchwork))
1444 (domain patchwork-configuration-domain)
1445 (settings-module patchwork-configuration-settings-module)
1446 (static-path patchwork-configuration-static-url
1447 (default "/static/"))
1448 (getmail-retriever-config getmail-retriever-config))
1449
1450 ;; Django uses a Python module for configuration, so this compiler generates a
1451 ;; Python module from the configuration record.
1452 (define-gexp-compiler (patchwork-settings-module-compiler
1453 (file <patchwork-settings-module>) system target)
1454 (match file
1455 (($ <patchwork-settings-module> database-configuration secret-key-file
1456 allowed-hosts default-from-email
1457 static-url admins debug? enable-rest-api?
1458 enable-xmlrpc? force-https-links?
1459 extra-configuration)
1460 (gexp->derivation
1461 "patchwork-settings"
1462 (with-imported-modules '((guix build utils))
1463 #~(let ((output #$output))
1464 (define (create-__init__.py filename)
1465 (call-with-output-file filename
1466 (lambda (port) (display "" port))))
1467
1468 (use-modules (guix build utils)
1469 (srfi srfi-1))
1470
1471 (mkdir-p (string-append output "/guix/patchwork"))
1472 (create-__init__.py
1473 (string-append output "/guix/__init__.py"))
1474 (create-__init__.py
1475 (string-append output "/guix/patchwork/__init__.py"))
1476
1477 (call-with-output-file
1478 (string-append output "/guix/patchwork/settings.py")
1479 (lambda (port)
1480 (display
1481 (string-append "from patchwork.settings.base import *
1482
1483 # Configuration from Guix
1484 with open('" #$secret-key-file "') as f:
1485 SECRET_KEY = f.read().strip()
1486
1487 ALLOWED_HOSTS = [
1488 " #$(string-concatenate
1489 (map (lambda (allowed-host)
1490 (string-append " '" allowed-host "'\n"))
1491 allowed-hosts))
1492 "]
1493
1494 DEFAULT_FROM_EMAIL = '" #$default-from-email "'
1495 SERVER_EMAIL = DEFAULT_FROM_EMAIL
1496 NOTIFICATION_FROM_EMAIL = DEFAULT_FROM_EMAIL
1497
1498 ADMINS = [
1499 " #$(string-concatenate
1500 (map (match-lambda
1501 ((name email-address)
1502 (string-append
1503 "('" name "','" email-address "'),")))
1504 admins))
1505 "]
1506
1507 DEBUG = " #$(if debug? "True" "False") "
1508
1509 ENABLE_REST_API = " #$(if enable-rest-api? "True" "False") "
1510 ENABLE_XMLRPC = " #$(if enable-xmlrpc? "True" "False") "
1511
1512 FORCE_HTTPS_LINKS = " #$(if force-https-links? "True" "False") "
1513
1514 DATABASES = {
1515 'default': {
1516 " #$(match database-configuration
1517 (($ <patchwork-database-configuration>
1518 engine name user password host port)
1519 (string-append
1520 " 'ENGINE': '" engine "',\n"
1521 " 'NAME': '" name "',\n"
1522 " 'USER': '" user "',\n"
1523 " 'PASSWORD': '" password "',\n"
1524 " 'HOST': '" host "',\n"
1525 " 'PORT': '" port "',\n"))) "
1526 },
1527 }
1528
1529 " #$(if debug?
1530 #~(string-append "STATIC_ROOT = '"
1531 #$(file-append patchwork "/share/patchwork/htdocs")
1532 "'")
1533 #~(string-append "STATIC_URL = '" #$static-url "'")) "
1534
1535 STATICFILES_STORAGE = (
1536 'django.contrib.staticfiles.storage.StaticFilesStorage'
1537 )
1538
1539 # Guix Extra Configuration
1540 " #$extra-configuration "
1541 ") port)))
1542 #t))
1543 #:local-build? #t))))
1544
1545 (define patchwork-virtualhost
1546 (match-lambda
1547 (($ <patchwork-configuration> patchwork domain
1548 settings-module static-path
1549 getmail-retriever-config)
1550 (define wsgi.py
1551 (file-append patchwork
1552 (string-append
1553 "/lib/python"
1554 (version-major+minor
1555 (package-version python))
1556 "/site-packages/patchwork/wsgi.py")))
1557
1558 (httpd-virtualhost
1559 "*:8080"
1560 `("ServerAdmin admin@example.com`
1561 ServerName " ,domain "
1562
1563 LogFormat \"%v %h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\"\" customformat
1564 LogLevel info
1565 CustomLog \"/var/log/httpd/" ,domain "-access_log\" customformat
1566
1567 ErrorLog /var/log/httpd/error.log
1568
1569 WSGIScriptAlias / " ,wsgi.py "
1570 WSGIDaemonProcess " ,(package-name patchwork) " user=httpd group=httpd processes=1 threads=2 display-name=%{GROUP} lang='en_US.UTF-8' locale='en_US.UTF-8' python-path=" ,settings-module "
1571 WSGIProcessGroup " ,(package-name patchwork) "
1572 WSGIPassAuthorization On
1573
1574 <Files " ,wsgi.py ">
1575 Require all granted
1576 </Files>
1577
1578 " ,@(if static-path
1579 `("Alias " ,static-path " " ,patchwork "/share/patchwork/htdocs/")
1580 '())
1581 "
1582 <Directory \"/srv/http/" ,domain "/\">
1583 AllowOverride None
1584 Options MultiViews Indexes SymlinksIfOwnerMatch IncludesNoExec
1585 Require method GET POST OPTIONS
1586 </Directory>")))))
1587
1588 (define (patchwork-httpd-configuration patchwork-configuration)
1589 (list "WSGISocketPrefix /var/run/mod_wsgi"
1590 (list "LoadModule wsgi_module "
1591 (file-append mod-wsgi "/modules/mod_wsgi.so"))
1592 (patchwork-virtualhost patchwork-configuration)))
1593
1594 (define (patchwork-django-admin-gexp patchwork settings-module)
1595 #~(lambda command
1596 (let ((pid (primitive-fork))
1597 (user (getpwnam "httpd")))
1598 (if (eq? pid 0)
1599 (dynamic-wind
1600 (const #t)
1601 (lambda ()
1602 (setgid (passwd:gid user))
1603 (setuid (passwd:uid user))
1604
1605 (setenv "DJANGO_SETTINGS_MODULE" "guix.patchwork.settings")
1606 (setenv "PYTHONPATH" #$settings-module)
1607 (primitive-exit
1608 (if (zero?
1609 (apply system*
1610 #$(file-append patchwork "/bin/patchwork-admin")
1611 command))
1612 0
1613 1)))
1614 (lambda ()
1615 (primitive-exit 1)))
1616 (zero? (cdr (waitpid pid)))))))
1617
1618 (define (patchwork-django-admin-action patchwork settings-module)
1619 (shepherd-action
1620 (name 'django-admin)
1621 (documentation
1622 "Run a django admin command for patchwork")
1623 (procedure (patchwork-django-admin-gexp patchwork settings-module))))
1624
1625 (define patchwork-shepherd-services
1626 (match-lambda
1627 (($ <patchwork-configuration> patchwork domain
1628 settings-module static-path
1629 getmail-retriever-config)
1630 (define secret-key-file-creation-gexp
1631 (if (patchwork-settings-module? settings-module)
1632 (with-extensions (list guile-gcrypt)
1633 #~(let ((secret-key-file
1634 #$(patchwork-settings-module-secret-key-file
1635 settings-module)))
1636 (use-modules (guix build utils)
1637 (gcrypt random))
1638
1639 (unless (file-exists? secret-key-file)
1640 (mkdir-p (dirname secret-key-file))
1641 (call-with-output-file secret-key-file
1642 (lambda (port)
1643 (display (random-token 30 'very-strong) port)))
1644 (let* ((pw (getpwnam "httpd"))
1645 (uid (passwd:uid pw))
1646 (gid (passwd:gid pw)))
1647 (chown secret-key-file uid gid)
1648 (chmod secret-key-file #o400)))))
1649 #~()))
1650
1651 (list (shepherd-service
1652 (requirement '(postgres))
1653 (provision (list (string->symbol
1654 (string-append (package-name patchwork)
1655 "-setup"))))
1656 (start
1657 #~(lambda ()
1658 (define run-django-admin-command
1659 #$(patchwork-django-admin-gexp patchwork
1660 settings-module))
1661
1662 #$secret-key-file-creation-gexp
1663
1664 (run-django-admin-command "migrate")))
1665 (stop #~(const #f))
1666 (actions
1667 (list (patchwork-django-admin-action patchwork
1668 settings-module)))
1669 (respawn? #f)
1670 (documentation "Setup Patchwork."))))))
1671
1672 (define patchwork-getmail-configs
1673 (match-lambda
1674 (($ <patchwork-configuration> patchwork domain
1675 settings-module static-path
1676 getmail-retriever-config)
1677 (list
1678 (getmail-configuration
1679 (name (string->symbol (package-name patchwork)))
1680 (user "httpd")
1681 (directory (string-append
1682 "/var/lib/getmail/" (package-name patchwork)))
1683 (rcfile
1684 (getmail-configuration-file
1685 (retriever getmail-retriever-config)
1686 (destination
1687 (getmail-destination-configuration
1688 (type "MDA_external")
1689 (path (file-append patchwork "/bin/patchwork-admin"))
1690 (extra-parameters
1691 '((arguments . ("parsemail"))))))
1692 (options
1693 (getmail-options-configuration
1694 (read-all #f)
1695 (delivered-to #f)
1696 (received #f)))))
1697 (idle (assq-ref
1698 (getmail-retriever-configuration-extra-parameters
1699 getmail-retriever-config)
1700 'mailboxes))
1701 (environment-variables
1702 (list "DJANGO_SETTINGS_MODULE=guix.patchwork.settings"
1703 #~(string-append "PYTHONPATH=" #$settings-module))))))))
1704
1705 (define patchwork-service-type
1706 (service-type
1707 (name 'patchwork-setup)
1708 (extensions
1709 (list (service-extension httpd-service-type
1710 patchwork-httpd-configuration)
1711 (service-extension shepherd-root-service-type
1712 patchwork-shepherd-services)
1713 (service-extension getmail-service-type
1714 patchwork-getmail-configs)))
1715 (description
1716 "Patchwork patch tracking system.")))
1717
1718 \f
1719 ;;;
1720 ;;; Mumi.
1721 ;;;
1722
1723 (define-record-type* <mumi-configuration>
1724 mumi-configuration make-mumi-configuration
1725 mumi-configuration?
1726 (mumi mumi-configuration-mumi (default mumi))
1727 (mailer? mumi-configuration-mailer? (default #t))
1728 (sender mumi-configuration-sender (default #f))
1729 (smtp mumi-configuration-smtp (default #f)))
1730
1731 (define %mumi-activation
1732 (with-imported-modules '((guix build utils))
1733 #~(begin
1734 (use-modules (guix build utils))
1735
1736 (mkdir-p "/var/mumi/db")
1737 (mkdir-p "/var/mumi/mails")
1738 (let* ((pw (getpwnam "mumi"))
1739 (uid (passwd:uid pw))
1740 (gid (passwd:gid pw)))
1741 (chown "/var/mumi" uid gid)
1742 (chown "/var/mumi/mails" uid gid)
1743 (chown "/var/mumi/db" uid gid)))))
1744
1745 (define %mumi-accounts
1746 (list (user-group (name "mumi") (system? #t))
1747 (user-account
1748 (name "mumi")
1749 (group "mumi")
1750 (system? #t)
1751 (comment "Mumi web server")
1752 (home-directory "/var/empty")
1753 (shell (file-append shadow "/sbin/nologin")))))
1754
1755 (define (mumi-shepherd-services config)
1756 (define environment
1757 #~(list "LC_ALL=en_US.utf8"
1758 (string-append "GUIX_LOCPATH=" #$glibc-utf8-locales
1759 "/lib/locale")))
1760
1761 (match config
1762 (($ <mumi-configuration> mumi mailer? sender smtp)
1763 (list (shepherd-service
1764 (provision '(mumi))
1765 (documentation "Mumi bug-tracking web interface.")
1766 (requirement '(networking))
1767 (start #~(make-forkexec-constructor
1768 `(#$(file-append mumi "/bin/mumi") "web"
1769 ,@(if #$mailer? '() '("--disable-mailer")))
1770 #:environment-variables #$environment
1771 #:user "mumi" #:group "mumi"
1772 #:log-file "/var/log/mumi.log"))
1773 (stop #~(make-kill-destructor)))
1774 (shepherd-service
1775 (provision '(mumi-worker))
1776 (documentation "Mumi bug-tracking web interface database worker.")
1777 (requirement '(networking))
1778 (start #~(make-forkexec-constructor
1779 '(#$(file-append mumi "/bin/mumi") "worker")
1780 #:environment-variables #$environment
1781 #:user "mumi" #:group "mumi"
1782 #:log-file "/var/log/mumi.worker.log"))
1783 (stop #~(make-kill-destructor)))
1784 (shepherd-service
1785 (provision '(mumi-mailer))
1786 (documentation "Mumi bug-tracking web interface mailer.")
1787 (requirement '(networking))
1788 (start #~(make-forkexec-constructor
1789 `(#$(file-append mumi "/bin/mumi") "mailer"
1790 ,@(if #$sender
1791 (list (string-append "--sender=" #$sender))
1792 '())
1793 ,@(if #$smtp
1794 (list (string-append "--smtp=" #$smtp))
1795 '()))
1796 #:environment-variables #$environment
1797 #:user "mumi" #:group "mumi"
1798 #:log-file "/var/log/mumi.mailer.log"))
1799 (stop #~(make-kill-destructor)))))))
1800
1801 (define mumi-service-type
1802 (service-type
1803 (name 'mumi)
1804 (extensions
1805 (list (service-extension activation-service-type
1806 (const %mumi-activation))
1807 (service-extension account-service-type
1808 (const %mumi-accounts))
1809 (service-extension shepherd-root-service-type
1810 mumi-shepherd-services)))
1811 (description
1812 "Run Mumi, a Web interface to the Debbugs bug-tracking server.")
1813 (default-value
1814 (mumi-configuration))))
1815
1816 (define %default-gmnisrv-config-file
1817 (plain-file "gmnisrv.ini" "
1818 listen=0.0.0.0:1965 [::]:1965
1819
1820 [:tls]
1821 store=/var/lib/gemini/certs
1822
1823 organization=gmnisrv on Guix user
1824
1825 [localhost]
1826 root=/srv/gemini
1827 "))
1828
1829 (define-record-type* <gmnisrv-configuration>
1830 gmnisrv-configuration make-gmnisrv-configuration
1831 gmnisrv-configuration?
1832 (package gmnisrv-configuration-package
1833 (default gmnisrv))
1834 (config-file gmnisrv-configuration-config-file
1835 (default %default-gmnisrv-config-file)))
1836
1837 (define gmnisrv-shepherd-service
1838 (match-lambda
1839 (($ <gmnisrv-configuration> package config-file)
1840 (list (shepherd-service
1841 (provision '(gmnisrv))
1842 (requirement '(networking))
1843 (documentation "Run the gmnisrv Gemini server.")
1844 (start (let ((gmnisrv (file-append package "/bin/gmnisrv")))
1845 #~(make-forkexec-constructor
1846 (list #$gmnisrv "-C" #$config-file)
1847 #:user "gmnisrv" #:group "gmnisrv"
1848 #:log-file "/var/log/gmnisrv.log")))
1849 (stop #~(make-kill-destructor)))))))
1850
1851 (define %gmnisrv-accounts
1852 (list (user-group (name "gmnisrv") (system? #t))
1853 (user-account
1854 (name "gmnisrv")
1855 (group "gmnisrv")
1856 (system? #t)
1857 (comment "gmnisrv Gemini server")
1858 (home-directory "/var/empty")
1859 (shell (file-append shadow "/sbin/nologin")))))
1860
1861 (define %gmnisrv-activation
1862 (with-imported-modules '((guix build utils))
1863 #~(begin
1864 (use-modules (guix build utils))
1865
1866 (mkdir-p "/var/lib/gemini/certs")
1867 (let* ((pw (getpwnam "gmnisrv"))
1868 (uid (passwd:uid pw))
1869 (gid (passwd:gid pw)))
1870 (chown "/var/lib/gemini" uid gid)
1871 (chown "/var/lib/gemini/certs" uid gid)))))
1872
1873 (define gmnisrv-service-type
1874 (service-type
1875 (name 'guix)
1876 (extensions
1877 (list (service-extension activation-service-type
1878 (const %gmnisrv-activation))
1879 (service-extension account-service-type
1880 (const %gmnisrv-accounts))
1881 (service-extension shepherd-root-service-type
1882 gmnisrv-shepherd-service)))
1883 (description
1884 "Run the gmnisrv Gemini server.")
1885 (default-value
1886 (gmnisrv-configuration))))