services: postgresql: Use "/tmp" host directory.
[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>
db170ee9 3;;; Copyright © 2015, 2016, 2017, 2018, 2019, 2020 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>
17881f94 15;;; Copyright © 2020 Arun Isaac <arunisaac@systemreboot.net>
00014f76 16;;; Copyright © 2020 Oleg Pykhalov <go.wigust@gmail.com>
2b5a81df 17;;; Copyright © 2020, 2021 Alexandru-Sergiu Marton <brown121407@posteo.ro>
58724c48
DT
18;;;
19;;; This file is part of GNU Guix.
20;;;
21;;; GNU Guix is free software; you can redistribute it and/or modify it
22;;; under the terms of the GNU General Public License as published by
23;;; the Free Software Foundation; either version 3 of the License, or (at
24;;; your option) any later version.
25;;;
26;;; GNU Guix is distributed in the hope that it will be useful, but
27;;; WITHOUT ANY WARRANTY; without even the implied warranty of
28;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29;;; GNU General Public License for more details.
30;;;
31;;; You should have received a copy of the GNU General Public License
32;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
33
34(define-module (gnu services web)
35 #:use-module (gnu services)
0190c1c0 36 #:use-module (gnu services shepherd)
81317071 37 #:use-module (gnu services admin)
2177d922
CB
38 #:use-module (gnu services getmail)
39 #:use-module (gnu services mail)
93b83eb3 40 #:use-module (gnu system pam)
58724c48
DT
41 #:use-module (gnu system shadow)
42 #:use-module (gnu packages admin)
06021185 43 #:use-module (gnu packages base)
2177d922 44 #:use-module (gnu packages databases)
58724c48 45 #:use-module (gnu packages web)
2177d922 46 #:use-module (gnu packages patchutils)
64bae723 47 #:use-module (gnu packages php)
2177d922
CB
48 #:use-module (gnu packages python)
49 #:use-module (gnu packages gnupg)
50 #:use-module (gnu packages guile)
19de8273 51 #:use-module (gnu packages logging)
6ee87461 52 #:use-module (gnu packages mail)
2b5a81df 53 #:use-module (gnu packages rust-apps)
2177d922 54 #:use-module (guix packages)
58724c48 55 #:use-module (guix records)
93b83eb3 56 #:use-module (guix modules)
2177d922 57 #:use-module (guix utils)
58724c48 58 #:use-module (guix gexp)
19de8273 59 #:use-module ((guix store) #:select (text-file))
64bae723 60 #:use-module ((guix utils) #:select (version-major))
61 #:use-module ((guix packages) #:select (package-version))
d338237d 62 #:use-module (srfi srfi-1)
d067e4ba 63 #:use-module (srfi srfi-9)
0adfe95a 64 #:use-module (ice-9 match)
db170ee9 65 #:use-module (ice-9 format)
a143e924 66 #:export (httpd-configuration
d067e4ba
CB
67 httpd-configuration?
68 httpd-configuration-package
69 httpd-configuration-pid-file
70 httpd-configuration-config
71
d067e4ba
CB
72 httpd-virtualhost
73 httpd-virtualhost?
74 httpd-virtualhost-addresses-and-ports
75 httpd-virtualhost-contents
76
d067e4ba
CB
77 httpd-config-file
78 httpd-config-file?
79 httpd-config-file-modules
80 httpd-config-file-server-root
81 httpd-config-file-server-name
82 httpd-config-file-listen
83 httpd-config-file-pid-file
84 httpd-config-file-error-log
85 httpd-config-file-user
86 httpd-config-file-group
87
abc98e3b
FP
88 httpd-module
89 httpd-module?
90 %default-httpd-modules
91
d067e4ba
CB
92 httpd-service-type
93
e4b729f8 94 nginx-configuration
24e96431 95 nginx-configuration?
5436b673 96 nginx-configuration-nginx
e4b729f8
CB
97 nginx-configuration-log-directory
98 nginx-configuration-run-directory
99 nginx-configuration-server-blocks
100 nginx-configuration-upstream-blocks
2881f852
CB
101 nginx-configuration-server-names-hash-bucket-size
102 nginx-configuration-server-names-hash-bucket-max-size
00e680a4 103 nginx-configuration-modules
85f09586 104 nginx-configuration-global-directives
25e071ea 105 nginx-configuration-extra-content
e4b729f8
CB
106 nginx-configuration-file
107
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 119
cb341293
CB
120 nginx-upstream-configuration
121 nginx-upstream-configuration?
e4b729f8
CB
122 nginx-upstream-configuration-name
123 nginx-upstream-configuration-servers
124
9c557a69
CB
125 nginx-location-configuration
126 nginx-location-configuration?
e4b729f8
CB
127 nginx-location-configuration-uri
128 nginx-location-configuration-body
129
9c557a69
CB
130 nginx-named-location-configuration
131 nginx-named-location-configuration?
e4b729f8
CB
132 nginx-named-location-configuration-name
133 nginx-named-location-configuration-body
134
24e96431 135 nginx-service
a5130d10
AW
136 nginx-service-type
137
138 fcgiwrap-configuration
139 fcgiwrap-configuration?
64bae723 140 fcgiwrap-service-type
141
64bae723 142 php-fpm-configuration
143 make-php-fpm-configuration
144 php-fpm-configuration?
145 php-fpm-configuration-php
146 php-fpm-configuration-socket
147 php-fpm-configuration-user
148 php-fpm-configuration-group
149 php-fpm-configuration-socket-user
150 php-fpm-configuration-socket-group
151 php-fpm-configuration-pid-file
152 php-fpm-configuration-log-file
153 php-fpm-configuration-process-manager
154 php-fpm-configuration-display-errors
e517161d 155 php-fpm-configuration-timezone
64bae723 156 php-fpm-configuration-workers-log-file
157 php-fpm-configuration-file
bba05331 158 php-fpm-configuration-php-ini-file
64bae723 159
64bae723 160 php-fpm-dynamic-process-manager-configuration
161 make-php-fpm-dynamic-process-manager-configuration
162 php-fpm-dynamic-process-manager-configuration?
163 php-fpm-dynamic-process-manager-configuration-max-children
164 php-fpm-dynamic-process-manager-configuration-start-servers
165 php-fpm-dynamic-process-manager-configuration-min-spare-servers
166 php-fpm-dynamic-process-manager-configuration-max-spare-servers
167
64bae723 168 php-fpm-static-process-manager-configuration
169 make-php-fpm-static-process-manager-configuration
170 php-fpm-static-process-manager-configuration?
171 php-fpm-static-process-manager-configuration-max-children
172
64bae723 173 php-fpm-on-demand-process-manager-configuration
174 make-php-fpm-on-demand-process-manager-configuration
175 php-fpm-on-demand-process-manager-configuration?
176 php-fpm-on-demand-process-manager-configuration-max-children
177 php-fpm-on-demand-process-manager-configuration-process-idle-timeout
178
179 php-fpm-service-type
08da664d
JL
180 nginx-php-location
181
93b83eb3
PAR
182 cat-avatar-generator-service
183
184 hpcguix-web-configuration
185 hpcguix-web-configuration?
19de8273
LC
186 hpcguix-web-service-type
187
19de8273
LC
188 tailon-configuration-file
189 tailon-configuration-file?
190 tailon-configuration-file-files
191 tailon-configuration-file-bind
192 tailon-configuration-file-relative-root
193 tailon-configuration-file-allow-transfers?
194 tailon-configuration-file-follow-names?
195 tailon-configuration-file-tail-lines
196 tailon-configuration-file-allowed-commands
197 tailon-configuration-file-debug?
198 tailon-configuration-file-http-auth
199 tailon-configuration-file-users
200
19de8273
LC
201 tailon-configuration
202 tailon-configuration?
203 tailon-configuration-config-file
204 tailon-configuration-package
205
3b97a177
MB
206 tailon-service-type
207
3b97a177
MB
208 varnish-configuration
209 varnish-configuration?
210 varnish-configuration-package
211 varnish-configuration-name
212 varnish-configuration-backend
213 varnish-configuration-vcl
214 varnish-configuration-listen
215 varnish-configuration-storage
216 varnish-configuration-parameters
217 varnish-configuration-extra-options
218
2177d922
CB
219 varnish-service-type
220
2177d922
CB
221 patchwork-database-configuration
222 patchwork-database-configuration?
223 patchwork-database-configuration-engine
224 patchwork-database-configuration-name
225 patchwork-database-configuration-user
226 patchwork-database-configuration-password
227 patchwork-database-configuration-host
228 patchwork-database-configuration-port
229
2177d922
CB
230 patchwork-settings-module
231 patchwork-settings-module?
232 patchwork-settings-module-database-configuration
233 patchwork-settings-module-secret-key
234 patchwork-settings-module-allowed-hosts
235 patchwork-settings-module-default-from-email
236 patchwork-settings-module-static-url
237 patchwork-settings-module-admins
238 patchwork-settings-module-debug?
239 patchwork-settings-module-enable-rest-api?
240 patchwork-settings-module-enable-xmlrpc?
241 patchwork-settings-module-force-https-links?
242 patchwork-settings-module-extra-settings
243
2177d922
CB
244 patchwork-configuration
245 patchwork-configuration?
246 patchwork-configuration-patchwork
247 patchwork-configuration-settings-module
248 patchwork-configuration-domain
249
250 patchwork-virtualhost
6ee87461
LC
251 patchwork-service-type
252
f00f52a1
RW
253 mumi-configuration
254 mumi-configuration?
255 mumi-configuration-mumi
256 mumi-configuration-mailer?
257 mumi-configuration-sender
258 mumi-configuration-smtp
259
149dd51d
ASM
260 mumi-service-type
261
262 gmnisrv-configuration
263 gmnisrv-configuration?
264 gmnisrv-configuration-package
265 gmnisrv-configuration-config-file
266
2b5a81df
ASM
267 gmnisrv-service-type
268
269 agate-configuration
270 agate-configuration?
271 agate-configuration-package
272 agate-configuration-content
273 agate-configuration-cert
274 agate-configuration-key
275 agate-configuration-addr
276 agate-configuration-hostname
277 agate-configuration-lang
278 agate-configuration-silent
279 agate-configuration-serve-secret
280 agate-configuration-log-ip
281 agate-configuration-user
282 agate-configuration-group
283 agate-configuration-log-file
284
285 agate-service-type))
58724c48
DT
286
287;;; Commentary:
288;;;
289;;; Web services.
290;;;
291;;; Code:
292
d067e4ba
CB
293(define-record-type* <httpd-module>
294 httpd-module make-httpd-module
295 httpd-module?
296 (name httpd-load-module-name)
297 (file httpd-load-module-file))
298
299;; Default modules for the httpd-service-type, taken from etc/httpd/httpd.conf
300;; file in the httpd package.
301(define %default-httpd-modules
302 (map (match-lambda
303 ((name file)
304 (httpd-module
305 (name name)
306 (file file))))
307 '(("authn_file_module" "modules/mod_authn_file.so")
308 ("authn_core_module" "modules/mod_authn_core.so")
309 ("authz_host_module" "modules/mod_authz_host.so")
310 ("authz_groupfile_module" "modules/mod_authz_groupfile.so")
311 ("authz_user_module" "modules/mod_authz_user.so")
312 ("authz_core_module" "modules/mod_authz_core.so")
313 ("access_compat_module" "modules/mod_access_compat.so")
314 ("auth_basic_module" "modules/mod_auth_basic.so")
315 ("reqtimeout_module" "modules/mod_reqtimeout.so")
316 ("filter_module" "modules/mod_filter.so")
317 ("mime_module" "modules/mod_mime.so")
318 ("log_config_module" "modules/mod_log_config.so")
319 ("env_module" "modules/mod_env.so")
320 ("headers_module" "modules/mod_headers.so")
321 ("setenvif_module" "modules/mod_setenvif.so")
322 ("version_module" "modules/mod_version.so")
323 ("unixd_module" "modules/mod_unixd.so")
324 ("status_module" "modules/mod_status.so")
325 ("autoindex_module" "modules/mod_autoindex.so")
326 ("dir_module" "modules/mod_dir.so")
327 ("alias_module" "modules/mod_alias.so"))))
328
329(define-record-type* <httpd-config-file>
330 httpd-config-file make-httpd-config-file
331 httpd-config-file?
332 (modules httpd-config-file-modules
333 (default %default-httpd-modules))
334 (server-root httpd-config-file-server-root
335 (default httpd))
336 (server-name httpd-config-file-server-name
337 (default #f))
338 (document-root httpd-config-file-document-root
339 (default "/srv/http"))
340 (listen httpd-config-file-listen
341 (default '("80")))
342 (pid-file httpd-config-file-pid-file
343 (default "/var/run/httpd"))
344 (error-log httpd-config-file-error-log
345 (default "/var/log/httpd/error_log"))
346 (user httpd-config-file-user
347 (default "httpd"))
348 (group httpd-config-file-group
349 (default "httpd"))
350 (extra-config httpd-config-file-extra-config
351 (default
352 (list "TypesConfig etc/httpd/mime.types"))))
353
354(define-gexp-compiler (httpd-config-file-compiler
355 (file <httpd-config-file>) system target)
356 (match file
357 (($ <httpd-config-file> load-modules server-root server-name
358 document-root listen pid-file error-log
359 user group extra-config)
360 (gexp->derivation
361 "httpd.conf"
362 #~(call-with-output-file (ungexp output "out")
363 (lambda (port)
364 (display
365 (string-append
366 (ungexp-splicing
367 `(,@(append-map
368 (match-lambda
369 (($ <httpd-module> name module)
370 `("LoadModule " ,name " " ,module "\n")))
371 load-modules)
372 ,@`("ServerRoot " ,server-root "\n")
373 ,@(if server-name
374 `("ServerName " ,server-name "\n")
375 '())
376 ,@`("DocumentRoot " ,document-root "\n")
377 ,@(append-map
378 (lambda (listen-value)
379 `("Listen " ,listen-value "\n"))
380 listen)
381 ,@(if pid-file
382 `("Pidfile " ,pid-file "\n")
383 '())
384 ,@(if error-log
385 `("ErrorLog " ,error-log "\n")
386 '())
387 ,@(if user
388 `("User " ,user "\n")
389 '())
390 ,@(if group
391 `("Group " ,group "\n")
392 '())
393 "\n\n"
394 ,@extra-config)))
395 port)))
396 #:local-build? #t))))
397
398(define-record-type <httpd-virtualhost>
399 (httpd-virtualhost addresses-and-ports contents)
400 httpd-virtualhost?
401 (addresses-and-ports httpd-virtualhost-addresses-and-ports)
402 (contents httpd-virtualhost-contents))
403
404(define-record-type* <httpd-configuration>
405 httpd-configuration make-httpd-configuration
406 httpd-configuration?
407 (package httpd-configuration-package
408 (default httpd))
409 (pid-file httpd-configuration-pid-file
410 (default "/var/run/httpd"))
411 (config httpd-configuration-config
412 (default (httpd-config-file))))
413
414(define %httpd-accounts
415 (list (user-group (name "httpd") (system? #t))
416 (user-account
417 (name "httpd")
418 (group "httpd")
419 (system? #t)
420 (comment "Apache HTTPD server user")
421 (home-directory "/var/empty")
422 (shell (file-append shadow "/sbin/nologin")))))
423
424(define httpd-shepherd-services
425 (match-lambda
426 (($ <httpd-configuration> package pid-file config)
427 (list (shepherd-service
428 (provision '(httpd))
429 (documentation "The Apache HTTP Server")
430 (requirement '(networking))
431 (start #~(make-forkexec-constructor
432 `(#$(file-append package "/bin/httpd")
433 #$@(if config
434 (list "-f" config)
435 '()))
436 #:pid-file #$pid-file))
437 (stop #~(make-kill-destructor)))))))
438
439(define httpd-activation
440 (match-lambda
441 (($ <httpd-configuration> package pid-file config)
442 (match-record
443 config
444 <httpd-config-file>
445 (error-log document-root)
446 #~(begin
447 (use-modules (guix build utils))
448
449 (mkdir-p #$(dirname error-log))
450 (mkdir-p #$document-root))))))
451
452(define (httpd-process-extensions original-config extension-configs)
453 (let ((config (httpd-configuration-config
454 original-config)))
455 (if (httpd-config-file? config)
456 (httpd-configuration
457 (inherit original-config)
458 (config
459 (httpd-config-file
460 (inherit config)
461 (extra-config
462 (append (httpd-config-file-extra-config config)
463 (append-map
464 (match-lambda
465 (($ <httpd-virtualhost>
466 addresses-and-ports
467 contents)
468 `(,(string-append
3a69dd5c 469 "\n<VirtualHost " addresses-and-ports ">\n")
d067e4ba
CB
470 ,@contents
471 "\n</VirtualHost>\n"))
472 ((? string? x)
473 `("\n" ,x "\n"))
474 ((? list? x)
475 `("\n" ,@x "\n")))
476 extension-configs)))))))))
477
478(define httpd-service-type
479 (service-type (name 'httpd)
480 (extensions
481 (list (service-extension shepherd-root-service-type
482 httpd-shepherd-services)
483 (service-extension activation-service-type
484 httpd-activation)
485 (service-extension account-service-type
486 (const %httpd-accounts))))
487 (compose concatenate)
488 (extend httpd-process-extensions)
489 (default-value
490 (httpd-configuration))))
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?
dc72a7f7
LC
539 (nginx nginx-configuration-nginx ;<package>
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 . ()))))
00014f76
OP
556 (lua-package-path nginx-lua-package-path ;list of <package>
557 (default #f))
558 (lua-package-cpath nginx-lua-package-cpath ;list of <package>
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?
807 (package fcgiwrap-configuration-package ;<package>
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)))
a5130d10 871 (default-value (fcgiwrap-configuration))))
64bae723 872
873(define-record-type* <php-fpm-configuration> php-fpm-configuration
874 make-php-fpm-configuration
875 php-fpm-configuration?
876 (php php-fpm-configuration-php ;<package>
877 (default php))
878 (socket php-fpm-configuration-socket
879 (default (string-append "/var/run/php"
880 (version-major (package-version php))
881 "-fpm.sock")))
882 (user php-fpm-configuration-user
883 (default "php-fpm"))
884 (group php-fpm-configuration-group
885 (default "php-fpm"))
886 (socket-user php-fpm-configuration-socket-user
887 (default "php-fpm"))
888 (socket-group php-fpm-configuration-socket-group
889 (default "nginx"))
890 (pid-file php-fpm-configuration-pid-file
891 (default (string-append "/var/run/php"
892 (version-major (package-version php))
893 "-fpm.pid")))
894 (log-file php-fpm-configuration-log-file
895 (default (string-append "/var/log/php"
896 (version-major (package-version php))
897 "-fpm.log")))
898 (process-manager php-fpm-configuration-process-manager
899 (default (php-fpm-dynamic-process-manager-configuration)))
900 (display-errors php-fpm-configuration-display-errors
901 (default #f))
e517161d
OP
902 (timezone php-fpm-configuration-timezone
903 (default #f))
64bae723 904 (workers-log-file php-fpm-configuration-workers-log-file
905 (default (string-append "/var/log/php"
906 (version-major (package-version php))
907 "-fpm.www.log")))
908 (file php-fpm-configuration-file ;#f | file-like
bba05331
JL
909 (default #f))
910 (php-ini-file php-fpm-configuration-php-ini-file ;#f | file-like
64bae723 911 (default #f)))
912
913(define-record-type* <php-fpm-dynamic-process-manager-configuration>
914 php-fpm-dynamic-process-manager-configuration
915 make-php-fpm-dynamic-process-manager-configuration
916 php-fpm-dynamic-process-manager-configuration?
917 (max-children php-fpm-dynamic-process-manager-configuration-max-children
918 (default 5))
919 (start-servers php-fpm-dynamic-process-manager-configuration-start-servers
920 (default 2))
921 (min-spare-servers php-fpm-dynamic-process-manager-configuration-min-spare-servers
922 (default 1))
923 (max-spare-servers php-fpm-dynamic-process-manager-configuration-max-spare-servers
924 (default 3)))
925
926(define-record-type* <php-fpm-static-process-manager-configuration>
927 php-fpm-static-process-manager-configuration
928 make-php-fpm-static-process-manager-configuration
929 php-fpm-static-process-manager-configuration?
930 (max-children php-fpm-static-process-manager-configuration-max-children
931 (default 5)))
932
933(define-record-type* <php-fpm-on-demand-process-manager-configuration>
934 php-fpm-on-demand-process-manager-configuration
935 make-php-fpm-on-demand-process-manager-configuration
936 php-fpm-on-demand-process-manager-configuration?
937 (max-children php-fpm-on-demand-process-manager-configuration-max-children
938 (default 5))
939 (process-idle-timeout php-fpm-on-demand-process-manager-configuration-process-idle-timeout
940 (default 10)))
941
942(define php-fpm-accounts
943 (match-lambda
944 (($ <php-fpm-configuration> php socket user group socket-user socket-group _ _ _ _ _ _)
e82a713c
JL
945 `(,@(if (equal? group "php-fpm")
946 '()
947 (list (user-group (name "php-fpm") (system? #t))))
948 ,(user-group
949 (name group)
950 (system? #t))
951 ,(user-account
952 (name user)
953 (group group)
954 (supplementary-groups '("php-fpm"))
955 (system? #t)
956 (comment "php-fpm daemon user")
957 (home-directory "/var/empty")
958 (shell (file-append shadow "/sbin/nologin")))))))
64bae723 959
960(define (default-php-fpm-config socket user group socket-user socket-group
e517161d 961 pid-file log-file pm display-errors timezone workers-log-file)
64bae723 962 (apply mixed-text-file "php-fpm.conf"
963 (flatten
964 "[global]\n"
965 "pid =" pid-file "\n"
966 "error_log =" log-file "\n"
967 "[www]\n"
968 "user =" user "\n"
969 "group =" group "\n"
970 "listen =" socket "\n"
971 "listen.owner =" socket-user "\n"
972 "listen.group =" socket-group "\n"
973
e517161d
OP
974 (if timezone
975 (string-append "php_admin_value[date.timezone] = \"" timezone "\"\n")
976 "")
977
64bae723 978 (match pm
979 (($ <php-fpm-dynamic-process-manager-configuration>
980 pm.max-children
981 pm.start-servers
982 pm.min-spare-servers
983 pm.max-spare-servers)
984 (list
985 "pm = dynamic\n"
986 "pm.max_children =" (number->string pm.max-children) "\n"
987 "pm.start_servers =" (number->string pm.start-servers) "\n"
988 "pm.min_spare_servers =" (number->string pm.min-spare-servers) "\n"
989 "pm.max_spare_servers =" (number->string pm.max-spare-servers) "\n"))
990
991 (($ <php-fpm-static-process-manager-configuration>
992 pm.max-children)
993 (list
994 "pm = static\n"
995 "pm.max_children =" (number->string pm.max-children) "\n"))
996
997 (($ <php-fpm-on-demand-process-manager-configuration>
998 pm.max-children
999 pm.process-idle-timeout)
1000 (list
1001 "pm = ondemand\n"
1002 "pm.max_children =" (number->string pm.max-children) "\n"
1003 "pm.process_idle_timeout =" (number->string pm.process-idle-timeout) "s\n")))
1004
1005
1006 "php_flag[display_errors] = " (if display-errors "on" "off") "\n"
1007
1008 (if workers-log-file
1009 (list "catch_workers_output = yes\n"
1010 "php_admin_value[error_log] =" workers-log-file "\n"
1011 "php_admin_flag[log_errors] = on\n")
1012 (list "catch_workers_output = no\n")))))
1013
1014(define php-fpm-shepherd-service
1015 (match-lambda
1016 (($ <php-fpm-configuration> php socket user group socket-user socket-group
e517161d 1017 pid-file log-file pm display-errors
bba05331 1018 timezone workers-log-file file php-ini-file)
64bae723 1019 (list (shepherd-service
1020 (provision '(php-fpm))
1021 (documentation "Run the php-fpm daemon.")
1022 (requirement '(networking))
1023 (start #~(make-forkexec-constructor
1024 '(#$(file-append php "/sbin/php-fpm")
1025 "--fpm-config"
1026 #$(or file
1027 (default-php-fpm-config socket user group
1028 socket-user socket-group pid-file log-file
bba05331
JL
1029 pm display-errors timezone workers-log-file))
1030 #$@(if php-ini-file
1031 `("-c" ,php-ini-file)
1032 '()))
64bae723 1033 #:pid-file #$pid-file))
1034 (stop #~(make-kill-destructor)))))))
1035
e517161d
OP
1036(define (php-fpm-activation config)
1037 #~(begin
1038 (use-modules (guix build utils))
1039 (let* ((user (getpwnam #$(php-fpm-configuration-user config)))
1040 (touch (lambda (file-name)
1041 (call-with-output-file file-name (const #t))))
1042 (workers-log-file
1043 #$(php-fpm-configuration-workers-log-file config))
1044 (init-log-file
1045 (lambda (file-name)
1046 (when workers-log-file
1047 (when (not (file-exists? file-name))
1048 (touch file-name))
1049 (chown file-name (passwd:uid user) (passwd:gid user))
1050 (chmod file-name #o660)))))
1051 (init-log-file #$(php-fpm-configuration-log-file config))
1052 (init-log-file workers-log-file))))
64bae723 1053
1054
1055(define php-fpm-service-type
1056 (service-type
1057 (name 'php-fpm)
1058 (description
1059 "Run @command{php-fpm} to provide a fastcgi socket for calling php through
1060a webserver.")
1061 (extensions
1062 (list (service-extension shepherd-root-service-type
1063 php-fpm-shepherd-service)
1064 (service-extension activation-service-type
1065 php-fpm-activation)
1066 (service-extension account-service-type
1067 php-fpm-accounts)))
1068 (default-value (php-fpm-configuration))))
1069
1070(define* (nginx-php-location
1071 #:key
1072 (nginx-package nginx)
1073 (socket (string-append "/var/run/php"
1074 (version-major (package-version php))
1075 "-fpm.sock")))
1076 "Return a nginx-location-configuration that makes nginx run .php files."
1077 (nginx-location-configuration
1078 (uri "~ \\.php$")
1079 (body (list
1080 "fastcgi_split_path_info ^(.+\\.php)(/.+)$;"
1081 (string-append "fastcgi_pass unix:" socket ";")
1082 "fastcgi_index index.php;"
1083 (list "include " nginx-package "/share/nginx/conf/fastcgi.conf;")))))
08da664d
JL
1084
1085(define* (cat-avatar-generator-service
1086 #:key
1087 (cache-dir "/var/cache/cat-avatar-generator")
1088 (package cat-avatar-generator)
1089 (configuration (nginx-server-configuration)))
1090 (simple-service
1091 'cat-http-server nginx-service-type
1092 (list (nginx-server-configuration
1093 (inherit configuration)
1094 (locations
1095 (cons
1096 (let ((base (nginx-php-location)))
1097 (nginx-location-configuration
1098 (inherit base)
1099 (body (list (string-append "fastcgi_param CACHE_DIR \""
1100 cache-dir "\";")
1101 (nginx-location-configuration-body base)))))
1102 (nginx-server-configuration-locations configuration)))
1103 (root #~(string-append #$package
1104 "/share/web/cat-avatar-generator"))))))
93b83eb3
PAR
1105
1106\f
1107(define-record-type* <hpcguix-web-configuration>
1108 hpcguix-web-configuration make-hpcguix-web-configuration
1109 hpcguix-web-configuration?
1110
1111 (package hpcguix-web-package (default hpcguix-web)) ;<package>
1112
1113 ;; Specs is gexp of hpcguix-web configuration file
1114 (specs hpcguix-web-configuration-specs))
1115
1116(define %hpcguix-web-accounts
1117 (list (user-group
1118 (name "hpcguix-web")
1119 (system? #t))
1120 (user-account
1121 (name "hpcguix-web")
1122 (group "hpcguix-web")
1123 (system? #t)
1124 (comment "hpcguix-web")
1125 (home-directory "/var/empty")
1126 (shell (file-append shadow "/sbin/nologin")))))
1127
1128(define %hpcguix-web-activation
1ce0d7e1
LC
1129 (with-imported-modules '((guix build utils))
1130 #~(begin
7c34c62c
LC
1131 (use-modules (guix build utils)
1132 (ice-9 ftw))
1ce0d7e1
LC
1133
1134 (let ((home-dir "/var/cache/guix/web")
1135 (user (getpwnam "hpcguix-web")))
1136 (mkdir-p home-dir)
1137 (chown home-dir (passwd:uid user) (passwd:gid user))
7c34c62c
LC
1138 (chmod home-dir #o755)
1139
1140 ;; Remove stale 'packages.json.lock' file (and other lock files, if
1141 ;; any) since that would prevent 'packages.json' from being updated.
1142 (for-each (lambda (lock)
1143 (delete-file (string-append home-dir "/" lock)))
1144 (scandir home-dir
1145 (lambda (file)
1146 (string-suffix? ".lock" file))))))))
93b83eb3 1147
81317071
LC
1148(define %hpcguix-web-log-file
1149 "/var/log/hpcguix-web.log")
1150
1151(define %hpcguix-web-log-rotations
1152 (list (log-rotation
1153 (files (list %hpcguix-web-log-file))
1154 (frequency 'weekly))))
1155
93b83eb3
PAR
1156(define (hpcguix-web-shepherd-service config)
1157 (let ((specs (hpcguix-web-configuration-specs config))
1158 (hpcguix-web (hpcguix-web-package config)))
1159 (with-imported-modules (source-module-closure
1160 '((gnu build shepherd)))
1161 (shepherd-service
1162 (documentation "hpcguix-web daemon")
1163 (provision '(hpcguix-web))
1164 (requirement '(networking))
1165 (start #~(make-forkexec-constructor
1166 (list #$(file-append hpcguix-web "/bin/run")
1167 (string-append "--config="
1168 #$(scheme-file "hpcguix-web.scm" specs)))
1169 #:user "hpcguix-web"
1170 #:group "hpcguix-web"
1171 #:environment-variables
e86c2f05 1172 (list "XDG_CACHE_HOME=/var/cache/guix/web"
81317071
LC
1173 "SSL_CERT_DIR=/etc/ssl/certs")
1174 #:log-file #$%hpcguix-web-log-file))
93b83eb3
PAR
1175 (stop #~(make-kill-destructor))))))
1176
1177(define hpcguix-web-service-type
1178 (service-type
1179 (name 'hpcguix-web)
1180 (description "Run the hpcguix-web server.")
1181 (extensions
1182 (list (service-extension account-service-type
1183 (const %hpcguix-web-accounts))
1184 (service-extension activation-service-type
1185 (const %hpcguix-web-activation))
81317071
LC
1186 (service-extension rottlog-service-type
1187 (const %hpcguix-web-log-rotations))
93b83eb3
PAR
1188 (service-extension shepherd-root-service-type
1189 (compose list hpcguix-web-shepherd-service))))))
19de8273
LC
1190
1191\f
1192;;;
1193;;; Tailon
1194;;;
1195
1196(define-record-type* <tailon-configuration-file>
1197 tailon-configuration-file make-tailon-configuration-file
1198 tailon-configuration-file?
1199 (files tailon-configuration-file-files
1200 (default '("/var/log")))
1201 (bind tailon-configuration-file-bind
1202 (default "localhost:8080"))
1203 (relative-root tailon-configuration-file-relative-root
1204 (default #f))
1205 (allow-transfers? tailon-configuration-file-allow-transfers?
1206 (default #t))
1207 (follow-names? tailon-configuration-file-follow-names?
1208 (default #t))
1209 (tail-lines tailon-configuration-file-tail-lines
1210 (default 200))
1211 (allowed-commands tailon-configuration-file-allowed-commands
1212 (default '("tail" "grep" "awk")))
1213 (debug? tailon-configuration-file-debug?
1214 (default #f))
1215 (wrap-lines tailon-configuration-file-wrap-lines
1216 (default #t))
1217 (http-auth tailon-configuration-file-http-auth
1218 (default #f))
1219 (users tailon-configuration-file-users
1220 (default #f)))
1221
1222(define (tailon-configuration-files-string files)
1223 (string-append
1224 "\n"
1225 (string-join
1226 (map
1227 (lambda (x)
1228 (string-append
1229 " - "
1230 (cond
1231 ((string? x)
1232 (simple-format #f "'~A'" x))
1233 ((list? x)
1234 (string-join
1235 (cons (simple-format #f "'~A':" (car x))
1236 (map
1237 (lambda (x) (simple-format #f " - '~A'" x))
1238 (cdr x)))
1239 "\n"))
1240 (else (error x)))))
1241 files)
1242 "\n")))
1243
1244(define-gexp-compiler (tailon-configuration-file-compiler
1245 (file <tailon-configuration-file>) system target)
1246 (match file
1247 (($ <tailon-configuration-file> files bind relative-root
1248 allow-transfers? follow-names?
1249 tail-lines allowed-commands debug?
1250 wrap-lines http-auth users)
1251 (text-file
1252 "tailon-config.yaml"
1253 (string-concatenate
1254 (filter-map
1255 (match-lambda
1256 ((key . #f) #f)
1257 ((key . value) (string-append key ": " value "\n")))
1258
1259 `(("files" . ,(tailon-configuration-files-string files))
1260 ("bind" . ,bind)
1261 ("relative-root" . ,relative-root)
1262 ("allow-transfers" . ,(if allow-transfers? "true" "false"))
1263 ("follow-names" . ,(if follow-names? "true" "false"))
1264 ("tail-lines" . ,(number->string tail-lines))
1265 ("commands" . ,(string-append "["
1266 (string-join allowed-commands ", ")
1267 "]"))
1268 ("debug" . ,(if debug? "true" #f))
1269 ("wrap-lines" . ,(if wrap-lines "true" "false"))
1270 ("http-auth" . ,http-auth)
1271 ("users" . ,(if users
1272 (string-concatenate
1273 (cons "\n"
1274 (map (match-lambda
1275 ((user . pass)
1276 (string-append
1277 " " user ":" pass)))
1278 users)))
1279 #f)))))))))
1280
1281(define-record-type* <tailon-configuration>
1282 tailon-configuration make-tailon-configuration
1283 tailon-configuration?
1284 (config-file tailon-configuration-config-file
1285 (default (tailon-configuration-file)))
1286 (package tailon-configuration-package
1287 (default tailon)))
1288
1289(define tailon-shepherd-service
1290 (match-lambda
1291 (($ <tailon-configuration> config-file package)
1292 (list (shepherd-service
1293 (provision '(tailon))
1294 (documentation "Run the tailon daemon.")
1295 (start #~(make-forkexec-constructor
1296 `(,(string-append #$package "/bin/tailon")
1297 "-c" ,#$config-file)
1298 #:user "tailon"
1299 #:group "tailon"))
1300 (stop #~(make-kill-destructor)))))))
1301
1302(define %tailon-accounts
1303 (list (user-group (name "tailon") (system? #t))
1304 (user-account
1305 (name "tailon")
1306 (group "tailon")
1307 (system? #t)
1308 (comment "tailon")
1309 (home-directory "/var/empty")
1310 (shell (file-append shadow "/sbin/nologin")))))
1311
1312(define tailon-service-type
1313 (service-type
1314 (name 'tailon)
1315 (description
1316 "Run Tailon, a Web application for monitoring, viewing, and searching log
1317files.")
1318 (extensions
1319 (list (service-extension shepherd-root-service-type
1320 tailon-shepherd-service)
1321 (service-extension account-service-type
1322 (const %tailon-accounts))))
1323 (compose concatenate)
1324 (extend (lambda (parameter files)
1325 (tailon-configuration
1326 (inherit parameter)
1327 (config-file
1328 (let ((old-config-file
1329 (tailon-configuration-config-file parameter)))
1330 (tailon-configuration-file
1331 (inherit old-config-file)
1332 (files (append (tailon-configuration-file-files old-config-file)
1333 files))))))))
1334 (default-value (tailon-configuration))))
3b97a177
MB
1335
1336\f
1337;;;
1338;;; Varnish
1339;;;
1340
1341(define-record-type* <varnish-configuration>
1342 varnish-configuration make-varnish-configuration
1343 varnish-configuration?
1344 (package varnish-configuration-package ;<package>
1345 (default varnish))
1346 (name varnish-configuration-name ;string
1347 (default "default"))
1348 (backend varnish-configuration-backend ;string
1349 (default "localhost:8080"))
1350 (vcl varnish-configuration-vcl ;#f | <file-like>
1351 (default #f))
1352 (listen varnish-configuration-listen ;list of strings
1353 (default '("localhost:80")))
1354 (storage varnish-configuration-storage ;list of strings
1355 (default '("malloc,128m")))
1356 (parameters varnish-configuration-parameters ;list of string pairs
1357 (default '()))
1358 (extra-options varnish-configuration-extra-options ;list of strings
1359 (default '())))
1360
1361(define %varnish-accounts
1362 (list (user-group
1363 (name "varnish")
1364 (system? #t))
1365 (user-account
1366 (name "varnish")
1367 (group "varnish")
1368 (system? #t)
1369 (comment "Varnish Cache User")
1370 (home-directory "/var/varnish")
1371 (shell (file-append shadow "/sbin/nologin")))))
1372
1373(define varnish-shepherd-service
1374 (match-lambda
1375 (($ <varnish-configuration> package name backend vcl listen storage
1376 parameters extra-options)
1377 (list (shepherd-service
1378 (provision (list (symbol-append 'varnish- (string->symbol name))))
1379 (documentation (string-append "The Varnish Web Accelerator"
1380 " (" name ")"))
1381 (requirement '(networking))
1382 (start #~(make-forkexec-constructor
1383 (list #$(file-append package "/sbin/varnishd")
1384 "-n" #$name
1385 #$@(if vcl
1386 #~("-f" #$vcl)
1387 #~("-b" #$backend))
1388 #$@(append-map (lambda (a) (list "-a" a)) listen)
1389 #$@(append-map (lambda (s) (list "-s" s)) storage)
1390 #$@(append-map (lambda (p)
1391 (list "-p" (format #f "~a=~a"
1392 (car p) (cdr p))))
1393 parameters)
1394 #$@extra-options)
1395 ;; Varnish will drop privileges to the "varnish" user when
1396 ;; it exists. Not passing #:user here allows the service
1397 ;; to bind to ports < 1024.
1398 #:pid-file (if (string-prefix? "/" #$name)
1399 (string-append #$name "/_.pid")
1400 (string-append "/var/varnish/" #$name "/_.pid"))))
1401 (stop #~(make-kill-destructor)))))))
1402
1403(define varnish-service-type
1404 (service-type
1405 (name 'varnish)
1406 (description "Run the Varnish cache server.")
1407 (extensions
1408 (list (service-extension account-service-type
1409 (const %varnish-accounts))
1410 (service-extension shepherd-root-service-type
1411 varnish-shepherd-service)))
1412 (default-value
1413 (varnish-configuration))))
2177d922
CB
1414
1415\f
1416;;;
1417;;; Patchwork
1418;;;
1419
1420(define-record-type* <patchwork-database-configuration>
1421 patchwork-database-configuration make-patchwork-database-configuration
1422 patchwork-database-configuration?
1423 (engine patchwork-database-configuration-engine
1424 (default "django.db.backends.postgresql_psycopg2"))
1425 (name patchwork-database-configuration-name
1426 (default "patchwork"))
1427 (user patchwork-database-configuration-user
1428 (default "httpd"))
1429 (password patchwork-database-configuration-password
1430 (default ""))
1431 (host patchwork-database-configuration-host
1432 (default ""))
1433 (port patchwork-database-configuration-port
1434 (default "")))
1435
1436(define-record-type* <patchwork-settings-module>
1437 patchwork-settings-module make-patchwork-settings-module
1438 patchwork-settings-module?
1439 (database-configuration patchwork-settings-module-database-configuration
1440 (default (patchwork-database-configuration)))
1441 (secret-key-file patchwork-settings-module-secret-key-file
1442 (default "/etc/patchwork/django-secret-key"))
1443 (allowed-hosts patchwork-settings-module-allowed-hosts)
1444 (default-from-email patchwork-settings-module-default-from-email)
1445 (static-url patchwork-settings-module-static-url
1446 (default "/static/"))
1447 (admins patchwork-settings-module-admins
1448 (default '()))
1449 (debug? patchwork-settings-module-debug?
1450 (default #f))
1451 (enable-rest-api? patchwork-settings-module-enable-rest-api?
1452 (default #t))
1453 (enable-xmlrpc? patchwork-settings-module-enable-xmlrpc?
1454 (default #t))
1455 (force-https-links? patchwork-settings-module-force-https-links?
1456 (default #t))
1457 (extra-settings patchwork-settings-module-extra-settings
1458 (default "")))
1459
1460(define-record-type* <patchwork-configuration>
1461 patchwork-configuration make-patchwork-configuration
1462 patchwork-configuration?
1463 (patchwork patchwork-configuration-patchwork
1464 (default patchwork))
1465 (domain patchwork-configuration-domain)
1466 (settings-module patchwork-configuration-settings-module)
1467 (static-path patchwork-configuration-static-url
1468 (default "/static/"))
1469 (getmail-retriever-config getmail-retriever-config))
1470
1471;; Django uses a Python module for configuration, so this compiler generates a
1472;; Python module from the configuration record.
1473(define-gexp-compiler (patchwork-settings-module-compiler
1474 (file <patchwork-settings-module>) system target)
1475 (match file
1476 (($ <patchwork-settings-module> database-configuration secret-key-file
1477 allowed-hosts default-from-email
1478 static-url admins debug? enable-rest-api?
1479 enable-xmlrpc? force-https-links?
1480 extra-configuration)
1481 (gexp->derivation
1482 "patchwork-settings"
1483 (with-imported-modules '((guix build utils))
1484 #~(let ((output #$output))
1485 (define (create-__init__.py filename)
1486 (call-with-output-file filename
1487 (lambda (port) (display "" port))))
1488
1489 (use-modules (guix build utils)
1490 (srfi srfi-1))
1491
1492 (mkdir-p (string-append output "/guix/patchwork"))
1493 (create-__init__.py
1494 (string-append output "/guix/__init__.py"))
1495 (create-__init__.py
1496 (string-append output "/guix/patchwork/__init__.py"))
1497
1498 (call-with-output-file
1499 (string-append output "/guix/patchwork/settings.py")
1500 (lambda (port)
1501 (display
1502 (string-append "from patchwork.settings.base import *
1503
1504# Configuration from Guix
1505with open('" #$secret-key-file "') as f:
1506 SECRET_KEY = f.read().strip()
1507
1508ALLOWED_HOSTS = [
1509" #$(string-concatenate
1510 (map (lambda (allowed-host)
1511 (string-append " '" allowed-host "'\n"))
1512 allowed-hosts))
1513"]
1514
f325a33e
CB
1515DEFAULT_FROM_EMAIL = '" #$default-from-email "'
1516SERVER_EMAIL = DEFAULT_FROM_EMAIL
1517NOTIFICATION_FROM_EMAIL = DEFAULT_FROM_EMAIL
1518
2177d922
CB
1519ADMINS = [
1520" #$(string-concatenate
1521 (map (match-lambda
1522 ((name email-address)
1523 (string-append
1524 "('" name "','" email-address "'),")))
1525 admins))
1526"]
1527
1528DEBUG = " #$(if debug? "True" "False") "
1529
548efa8b 1530ENABLE_REST_API = " #$(if enable-rest-api? "True" "False") "
2177d922
CB
1531ENABLE_XMLRPC = " #$(if enable-xmlrpc? "True" "False") "
1532
1533FORCE_HTTPS_LINKS = " #$(if force-https-links? "True" "False") "
1534
1535DATABASES = {
1536 'default': {
1537" #$(match database-configuration
1538 (($ <patchwork-database-configuration>
1539 engine name user password host port)
1540 (string-append
1541 " 'ENGINE': '" engine "',\n"
1542 " 'NAME': '" name "',\n"
1543 " 'USER': '" user "',\n"
1544 " 'PASSWORD': '" password "',\n"
1545 " 'HOST': '" host "',\n"
1546 " 'PORT': '" port "',\n"))) "
1547 },
1548}
1549
1550" #$(if debug?
1551 #~(string-append "STATIC_ROOT = '"
1552 #$(file-append patchwork "/share/patchwork/htdocs")
1553 "'")
1554 #~(string-append "STATIC_URL = '" #$static-url "'")) "
1555
1556STATICFILES_STORAGE = (
1557 'django.contrib.staticfiles.storage.StaticFilesStorage'
1558)
1559
1560# Guix Extra Configuration
1561" #$extra-configuration "
1562") port)))
1563 #t))
1564 #:local-build? #t))))
1565
1566(define patchwork-virtualhost
1567 (match-lambda
1568 (($ <patchwork-configuration> patchwork domain
1569 settings-module static-path
1570 getmail-retriever-config)
1571 (define wsgi.py
1572 (file-append patchwork
1573 (string-append
1574 "/lib/python"
1575 (version-major+minor
1576 (package-version python))
1577 "/site-packages/patchwork/wsgi.py")))
1578
1579 (httpd-virtualhost
1580 "*:8080"
1581 `("ServerAdmin admin@example.com`
1582ServerName " ,domain "
1583
1584LogFormat \"%v %h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\"\" customformat
1585LogLevel info
1586CustomLog \"/var/log/httpd/" ,domain "-access_log\" customformat
1587
1588ErrorLog /var/log/httpd/error.log
1589
1590WSGIScriptAlias / " ,wsgi.py "
1591WSGIDaemonProcess " ,(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 "
1592WSGIProcessGroup " ,(package-name patchwork) "
1593WSGIPassAuthorization On
1594
1595<Files " ,wsgi.py ">
1596 Require all granted
1597</Files>
1598
1599" ,@(if static-path
1600 `("Alias " ,static-path " " ,patchwork "/share/patchwork/htdocs/")
1601 '())
1602"
1603<Directory \"/srv/http/" ,domain "/\">
1604 AllowOverride None
1605 Options MultiViews Indexes SymlinksIfOwnerMatch IncludesNoExec
1606 Require method GET POST OPTIONS
1607</Directory>")))))
1608
1609(define (patchwork-httpd-configuration patchwork-configuration)
1610 (list "WSGISocketPrefix /var/run/mod_wsgi"
1611 (list "LoadModule wsgi_module "
1612 (file-append mod-wsgi "/modules/mod_wsgi.so"))
1613 (patchwork-virtualhost patchwork-configuration)))
1614
1615(define (patchwork-django-admin-gexp patchwork settings-module)
1616 #~(lambda command
1617 (let ((pid (primitive-fork))
1618 (user (getpwnam "httpd")))
1619 (if (eq? pid 0)
1620 (dynamic-wind
1621 (const #t)
1622 (lambda ()
1623 (setgid (passwd:gid user))
1624 (setuid (passwd:uid user))
1625
1626 (setenv "DJANGO_SETTINGS_MODULE" "guix.patchwork.settings")
1627 (setenv "PYTHONPATH" #$settings-module)
1628 (primitive-exit
1629 (if (zero?
1630 (apply system*
1631 #$(file-append patchwork "/bin/patchwork-admin")
1632 command))
1633 0
1634 1)))
1635 (lambda ()
1636 (primitive-exit 1)))
1637 (zero? (cdr (waitpid pid)))))))
1638
1639(define (patchwork-django-admin-action patchwork settings-module)
1640 (shepherd-action
1641 (name 'django-admin)
1642 (documentation
1643 "Run a django admin command for patchwork")
1644 (procedure (patchwork-django-admin-gexp patchwork settings-module))))
1645
1646(define patchwork-shepherd-services
1647 (match-lambda
1648 (($ <patchwork-configuration> patchwork domain
1649 settings-module static-path
1650 getmail-retriever-config)
1651 (define secret-key-file-creation-gexp
1652 (if (patchwork-settings-module? settings-module)
1653 (with-extensions (list guile-gcrypt)
1654 #~(let ((secret-key-file
1655 #$(patchwork-settings-module-secret-key-file
1656 settings-module)))
1657 (use-modules (guix build utils)
1658 (gcrypt random))
1659
1660 (unless (file-exists? secret-key-file)
1661 (mkdir-p (dirname secret-key-file))
1662 (call-with-output-file secret-key-file
1663 (lambda (port)
1664 (display (random-token 30 'very-strong) port)))
1665 (let* ((pw (getpwnam "httpd"))
1666 (uid (passwd:uid pw))
1667 (gid (passwd:gid pw)))
1668 (chown secret-key-file uid gid)
1669 (chmod secret-key-file #o400)))))
1670 #~()))
1671
1672 (list (shepherd-service
1673 (requirement '(postgres))
1674 (provision (list (string->symbol
1675 (string-append (package-name patchwork)
1676 "-setup"))))
1677 (start
1678 #~(lambda ()
1679 (define run-django-admin-command
1680 #$(patchwork-django-admin-gexp patchwork
1681 settings-module))
1682
1683 #$secret-key-file-creation-gexp
1684
1685 (run-django-admin-command "migrate")))
1686 (stop #~(const #f))
1687 (actions
1688 (list (patchwork-django-admin-action patchwork
1689 settings-module)))
1690 (respawn? #f)
1691 (documentation "Setup Patchwork."))))))
1692
1693(define patchwork-getmail-configs
1694 (match-lambda
1695 (($ <patchwork-configuration> patchwork domain
1696 settings-module static-path
1697 getmail-retriever-config)
1698 (list
1699 (getmail-configuration
1700 (name (string->symbol (package-name patchwork)))
1701 (user "httpd")
1702 (directory (string-append
1703 "/var/lib/getmail/" (package-name patchwork)))
1704 (rcfile
1705 (getmail-configuration-file
1706 (retriever getmail-retriever-config)
1707 (destination
1708 (getmail-destination-configuration
1709 (type "MDA_external")
1710 (path (file-append patchwork "/bin/patchwork-admin"))
1711 (extra-parameters
1712 '((arguments . ("parsemail"))))))
1713 (options
1714 (getmail-options-configuration
1715 (read-all #f)
1716 (delivered-to #f)
1717 (received #f)))))
1718 (idle (assq-ref
1719 (getmail-retriever-configuration-extra-parameters
1720 getmail-retriever-config)
1721 'mailboxes))
1722 (environment-variables
1723 (list "DJANGO_SETTINGS_MODULE=guix.patchwork.settings"
1724 #~(string-append "PYTHONPATH=" #$settings-module))))))))
1725
1726(define patchwork-service-type
1727 (service-type
1728 (name 'patchwork-setup)
1729 (extensions
1730 (list (service-extension httpd-service-type
1731 patchwork-httpd-configuration)
1732 (service-extension shepherd-root-service-type
1733 patchwork-shepherd-services)
1734 (service-extension getmail-service-type
1735 patchwork-getmail-configs)))
1736 (description
1737 "Patchwork patch tracking system.")))
6ee87461
LC
1738
1739\f
1740;;;
1741;;; Mumi.
1742;;;
1743
f00f52a1
RW
1744(define-record-type* <mumi-configuration>
1745 mumi-configuration make-mumi-configuration
1746 mumi-configuration?
1747 (mumi mumi-configuration-mumi (default mumi))
1748 (mailer? mumi-configuration-mailer? (default #t))
6ef1fc8d
RW
1749 (sender mumi-configuration-sender (default #f))
1750 (smtp mumi-configuration-smtp (default #f)))
f00f52a1 1751
6ee87461
LC
1752(define %mumi-activation
1753 (with-imported-modules '((guix build utils))
1754 #~(begin
1755 (use-modules (guix build utils))
1756
a5953992 1757 (mkdir-p "/var/mumi/db")
6ee87461
LC
1758 (mkdir-p "/var/mumi/mails")
1759 (let* ((pw (getpwnam "mumi"))
1760 (uid (passwd:uid pw))
1761 (gid (passwd:gid pw)))
1762 (chown "/var/mumi" uid gid)
a5953992
RW
1763 (chown "/var/mumi/mails" uid gid)
1764 (chown "/var/mumi/db" uid gid)))))
6ee87461
LC
1765
1766(define %mumi-accounts
1767 (list (user-group (name "mumi") (system? #t))
1768 (user-account
1769 (name "mumi")
1770 (group "mumi")
1771 (system? #t)
1772 (comment "Mumi web server")
1773 (home-directory "/var/empty")
1774 (shell (file-append shadow "/sbin/nologin")))))
1775
f00f52a1 1776(define (mumi-shepherd-services config)
06021185
LC
1777 (define environment
1778 #~(list "LC_ALL=en_US.utf8"
1779 (string-append "GUIX_LOCPATH=" #$glibc-utf8-locales
1780 "/lib/locale")))
1781
f00f52a1
RW
1782 (match config
1783 (($ <mumi-configuration> mumi mailer? sender smtp)
1784 (list (shepherd-service
1785 (provision '(mumi))
1786 (documentation "Mumi bug-tracking web interface.")
1787 (requirement '(networking))
1788 (start #~(make-forkexec-constructor
1789 `(#$(file-append mumi "/bin/mumi") "web"
0e8564f8 1790 ,@(if #$mailer? '() '("--disable-mailer")))
06021185 1791 #:environment-variables #$environment
f00f52a1
RW
1792 #:user "mumi" #:group "mumi"
1793 #:log-file "/var/log/mumi.log"))
1794 (stop #~(make-kill-destructor)))
1795 (shepherd-service
1796 (provision '(mumi-worker))
1797 (documentation "Mumi bug-tracking web interface database worker.")
1798 (requirement '(networking))
1799 (start #~(make-forkexec-constructor
1800 '(#$(file-append mumi "/bin/mumi") "worker")
06021185 1801 #:environment-variables #$environment
f00f52a1
RW
1802 #:user "mumi" #:group "mumi"
1803 #:log-file "/var/log/mumi.worker.log"))
1804 (stop #~(make-kill-destructor)))
1805 (shepherd-service
1806 (provision '(mumi-mailer))
1807 (documentation "Mumi bug-tracking web interface mailer.")
1808 (requirement '(networking))
1809 (start #~(make-forkexec-constructor
1810 `(#$(file-append mumi "/bin/mumi") "mailer"
0e8564f8
RW
1811 ,@(if #$sender
1812 (list (string-append "--sender=" #$sender))
f00f52a1 1813 '())
0e8564f8
RW
1814 ,@(if #$smtp
1815 (list (string-append "--smtp=" #$smtp))
f00f52a1 1816 '()))
06021185 1817 #:environment-variables #$environment
f00f52a1
RW
1818 #:user "mumi" #:group "mumi"
1819 #:log-file "/var/log/mumi.mailer.log"))
1820 (stop #~(make-kill-destructor)))))))
6ee87461
LC
1821
1822(define mumi-service-type
1823 (service-type
1824 (name 'mumi)
1825 (extensions
1826 (list (service-extension activation-service-type
1827 (const %mumi-activation))
1828 (service-extension account-service-type
1829 (const %mumi-accounts))
1830 (service-extension shepherd-root-service-type
1831 mumi-shepherd-services)))
1832 (description
1833 "Run Mumi, a Web interface to the Debbugs bug-tracking server.")
f00f52a1
RW
1834 (default-value
1835 (mumi-configuration))))
2ade5bde
ASM
1836
1837(define %default-gmnisrv-config-file
1838 (plain-file "gmnisrv.ini" "
1839listen=0.0.0.0:1965 [::]:1965
1840
1841[:tls]
1842store=/var/lib/gemini/certs
1843
1844organization=gmnisrv on Guix user
1845
1846[localhost]
1847root=/srv/gemini
1848"))
1849
1850(define-record-type* <gmnisrv-configuration>
1851 gmnisrv-configuration make-gmnisrv-configuration
1852 gmnisrv-configuration?
1853 (package gmnisrv-configuration-package
1854 (default gmnisrv))
1855 (config-file gmnisrv-configuration-config-file
1856 (default %default-gmnisrv-config-file)))
1857
1858(define gmnisrv-shepherd-service
1859 (match-lambda
1860 (($ <gmnisrv-configuration> package config-file)
1861 (list (shepherd-service
1862 (provision '(gmnisrv))
1863 (requirement '(networking))
1864 (documentation "Run the gmnisrv Gemini server.")
1865 (start (let ((gmnisrv (file-append package "/bin/gmnisrv")))
1866 #~(make-forkexec-constructor
1867 (list #$gmnisrv "-C" #$config-file)
1868 #:user "gmnisrv" #:group "gmnisrv"
1869 #:log-file "/var/log/gmnisrv.log")))
1870 (stop #~(make-kill-destructor)))))))
1871
1872(define %gmnisrv-accounts
1873 (list (user-group (name "gmnisrv") (system? #t))
1874 (user-account
1875 (name "gmnisrv")
1876 (group "gmnisrv")
1877 (system? #t)
1878 (comment "gmnisrv Gemini server")
1879 (home-directory "/var/empty")
1880 (shell (file-append shadow "/sbin/nologin")))))
1881
1882(define %gmnisrv-activation
1883 (with-imported-modules '((guix build utils))
1884 #~(begin
1885 (use-modules (guix build utils))
1886
1887 (mkdir-p "/var/lib/gemini/certs")
1888 (let* ((pw (getpwnam "gmnisrv"))
1889 (uid (passwd:uid pw))
1890 (gid (passwd:gid pw)))
1891 (chown "/var/lib/gemini" uid gid)
1892 (chown "/var/lib/gemini/certs" uid gid)))))
1893
1894(define gmnisrv-service-type
1895 (service-type
1896 (name 'guix)
1897 (extensions
1898 (list (service-extension activation-service-type
1899 (const %gmnisrv-activation))
1900 (service-extension account-service-type
1901 (const %gmnisrv-accounts))
1902 (service-extension shepherd-root-service-type
1903 gmnisrv-shepherd-service)))
1904 (description
1905 "Run the gmnisrv Gemini server.")
1906 (default-value
1907 (gmnisrv-configuration))))
2b5a81df
ASM
1908
1909(define-record-type* <agate-configuration>
1910 agate-configuration make-agate-configuration
1911 agate-configuration?
1912 (package agate-configuration-package
1913 (default agate))
1914 (content agate-configuration-content
1915 (default "/srv/gemini"))
1916 (cert agate-configuration-cert
1917 (default #f))
1918 (key agate-configuration-key
1919 (default #f))
1920 (addr agate-configuration-addr
1921 (default '("0.0.0.0:1965" "[::]:1965")))
1922 (hostname agate-configuration-hostname
1923 (default #f))
1924 (lang agate-configuration-lang
1925 (default #f))
1926 (silent? agate-configuration-silent
1927 (default #f))
1928 (serve-secret? agate-configuration-serve-secret
1929 (default #f))
1930 (log-ip? agate-configuration-log-ip
1931 (default #t))
1932 (user agate-configuration-user
1933 (default "agate"))
1934 (group agate-configuration-group
1935 (default "agate"))
1936 (log-file agate-configuration-log
1937 (default "/var/log/agate.log")))
1938
1939(define agate-shepherd-service
1940 (match-lambda
1941 (($ <agate-configuration> package content cert key addr
1942 hostname lang silent? serve-secret?
1943 log-ip? user group log-file)
1944 (list (shepherd-service
1945 (provision '(agate))
1946 (requirement '(networking))
1947 (documentation "Run the agate Gemini server.")
1948 (start (let ((agate (file-append package "/bin/agate")))
1949 #~(make-forkexec-constructor
190912cb
CB
1950 (list #$agate
1951 "--content" #$content
1952 "--cert" #$cert
1953 "--key" #$key
1954 "--addr" #$@addr
2b5a81df
ASM
1955 #$@(if lang
1956 (list "--lang" lang)
1957 '())
190912cb
CB
1958 #$@(if hostname
1959 (list "--hostname" hostname)
1960 '())
1961 #$@(if silent? '("--silent") '())
1962 #$@(if serve-secret? '("--serve-secret") '())
1963 #$@(if log-ip? '("--log-ip") '()))
1964 #:user #$user #:group #$group
1965 #:log-file #$log-file)))
2b5a81df 1966 (stop #~(make-kill-destructor)))))))
190912cb 1967
2b5a81df
ASM
1968(define agate-accounts
1969 (match-lambda
1970 (($ <agate-configuration> _ _ _ _ _
1971 _ _ _ _
1972 _ user group _)
1973 `(,@(if (equal? group "agate")
1974 '()
1975 (list (user-group (name "agate") (system? #t))))
1976 ,(user-group
1977 (name group)
1978 (system? #t))
1979 ,(user-account
1980 (name user)
1981 (group group)
1982 (supplementary-groups '("agate"))
1983 (system? #t)
1984 (comment "agate server user")
1985 (home-directory "/var/empty")
1986 (shell (file-append shadow "/sbin/nologin")))))))
1987
1988(define agate-service-type
1989 (service-type
1990 (name 'guix)
1991 (extensions
1992 (list (service-extension account-service-type
1993 agate-accounts)
1994 (service-extension shepherd-root-service-type
1995 agate-shepherd-service)))
1996 (default-value (agate-configuration))))