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