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