1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2015 David Thompson <davet@gnu.org>
3 ;;; Copyright © 2015-2022 Ludovic Courtès <ludo@gnu.org>
4 ;;; Copyright © 2016 Nikita <nikita@n0.is>
5 ;;; Copyright © 2016, 2017, 2018 Julien Lepiller <julien@lepiller.eu>
6 ;;; Copyright © 2017, 2018, 2019 Christopher Baines <mail@cbaines.net>
7 ;;; Copyright © 2017 nee <nee-git@hidamari.blue>
8 ;;; Copyright © 2017, 2018 Clément Lassieur <clement@lassieur.org>
9 ;;; Copyright © 2018 Pierre-Antoine Rouby <pierre-antoine.rouby@inria.fr>
10 ;;; Copyright © 2018 Marius Bakke <mbakke@fastmail.com>
11 ;;; Copyright © 2019, 2020 Florian Pelz <pelzflorian@pelzflorian.de>
12 ;;; Copyright © 2020, 2022 Ricardo Wurmus <rekado@elephly.net>
13 ;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
14 ;;; Copyright © 2020 Arun Isaac <arunisaac@systemreboot.net>
15 ;;; Copyright © 2020 Oleg Pykhalov <go.wigust@gmail.com>
16 ;;; Copyright © 2020, 2021 Alexandru-Sergiu Marton <brown121407@posteo.ro>
17 ;;; Copyright © 2022 Simen Endsjø <simendsjo@gmail.com>
19 ;;; This file is part of GNU Guix.
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.
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.
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/>.
34 (define-module (gnu services web)
35 #:use-module (gnu services)
36 #:use-module (gnu services shepherd)
37 #:use-module (gnu services admin)
38 #:use-module (gnu services getmail)
39 #:use-module (gnu services mail)
40 #:use-module (gnu system pam)
41 #:use-module (gnu system shadow)
42 #:use-module (gnu packages admin)
43 #:use-module (gnu packages base)
44 #:use-module (gnu packages databases)
45 #:use-module (gnu packages web)
46 #:use-module (gnu packages patchutils)
47 #:use-module (gnu packages php)
48 #:use-module (gnu packages python)
49 #:use-module (gnu packages gnupg)
50 #:use-module (gnu packages guile)
51 #:use-module (gnu packages logging)
52 #:use-module (gnu packages mail)
53 #:use-module (gnu packages rust-apps)
54 #:use-module (guix packages)
55 #:use-module (guix records)
56 #:use-module (guix modules)
57 #:use-module (guix utils)
58 #:use-module (guix gexp)
59 #:use-module ((guix store) #:select (text-file))
60 #:use-module ((guix utils) #:select (version-major))
61 #:use-module ((guix packages) #:select (package-version))
62 #:use-module (srfi srfi-1)
63 #:use-module (srfi srfi-9)
64 #:use-module (ice-9 match)
65 #:use-module (ice-9 format)
66 #:export (httpd-configuration
68 httpd-configuration-package
69 httpd-configuration-pid-file
70 httpd-configuration-config
74 httpd-virtualhost-addresses-and-ports
75 httpd-virtualhost-contents
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
90 %default-httpd-modules
96 nginx-configuration-nginx
97 nginx-configuration-shepherd-requirement
98 nginx-configuration-log-directory
99 nginx-configuration-run-directory
100 nginx-configuration-server-blocks
101 nginx-configuration-upstream-blocks
102 nginx-configuration-server-names-hash-bucket-size
103 nginx-configuration-server-names-hash-bucket-max-size
104 nginx-configuration-modules
105 nginx-configuration-global-directives
106 nginx-configuration-extra-content
107 nginx-configuration-file
109 nginx-server-configuration
110 nginx-server-configuration?
111 nginx-server-configuration-listen
112 nginx-server-configuration-server-name
113 nginx-server-configuration-root
114 nginx-server-configuration-locations
115 nginx-server-configuration-index
116 nginx-server-configuration-ssl-certificate
117 nginx-server-configuration-ssl-certificate-key
118 nginx-server-configuration-server-tokens?
119 nginx-server-configuration-raw-content
121 nginx-upstream-configuration
122 nginx-upstream-configuration?
123 nginx-upstream-configuration-name
124 nginx-upstream-configuration-servers
125 nginx-upstream-configuration-extra-content
127 nginx-location-configuration
128 nginx-location-configuration?
129 nginx-location-configuration-uri
130 nginx-location-configuration-body
132 nginx-named-location-configuration
133 nginx-named-location-configuration?
134 nginx-named-location-configuration-name
135 nginx-named-location-configuration-body
140 fcgiwrap-configuration
141 fcgiwrap-configuration?
142 fcgiwrap-service-type
144 php-fpm-configuration
145 make-php-fpm-configuration
146 php-fpm-configuration?
147 php-fpm-configuration-php
148 php-fpm-configuration-socket
149 php-fpm-configuration-user
150 php-fpm-configuration-group
151 php-fpm-configuration-socket-user
152 php-fpm-configuration-socket-group
153 php-fpm-configuration-pid-file
154 php-fpm-configuration-log-file
155 php-fpm-configuration-process-manager
156 php-fpm-configuration-display-errors
157 php-fpm-configuration-timezone
158 php-fpm-configuration-workers-log-file
159 php-fpm-configuration-file
160 php-fpm-configuration-php-ini-file
162 php-fpm-dynamic-process-manager-configuration
163 make-php-fpm-dynamic-process-manager-configuration
164 php-fpm-dynamic-process-manager-configuration?
165 php-fpm-dynamic-process-manager-configuration-max-children
166 php-fpm-dynamic-process-manager-configuration-start-servers
167 php-fpm-dynamic-process-manager-configuration-min-spare-servers
168 php-fpm-dynamic-process-manager-configuration-max-spare-servers
170 php-fpm-static-process-manager-configuration
171 make-php-fpm-static-process-manager-configuration
172 php-fpm-static-process-manager-configuration?
173 php-fpm-static-process-manager-configuration-max-children
175 php-fpm-on-demand-process-manager-configuration
176 make-php-fpm-on-demand-process-manager-configuration
177 php-fpm-on-demand-process-manager-configuration?
178 php-fpm-on-demand-process-manager-configuration-max-children
179 php-fpm-on-demand-process-manager-configuration-process-idle-timeout
184 cat-avatar-generator-service
186 hpcguix-web-configuration
187 hpcguix-web-configuration?
188 hpcguix-web-service-type
190 tailon-configuration-file
191 tailon-configuration-file?
192 tailon-configuration-file-files
193 tailon-configuration-file-bind
194 tailon-configuration-file-relative-root
195 tailon-configuration-file-allow-transfers?
196 tailon-configuration-file-follow-names?
197 tailon-configuration-file-tail-lines
198 tailon-configuration-file-allowed-commands
199 tailon-configuration-file-debug?
200 tailon-configuration-file-http-auth
201 tailon-configuration-file-users
204 tailon-configuration?
205 tailon-configuration-config-file
206 tailon-configuration-package
211 anonip-configuration?
212 anonip-configuration-anonip
213 anonip-configuration-input
214 anonip-configuration-output
215 anonip-configuration-skip-private?
216 anonip-configuration-column
217 anonip-configuration-replacement
218 anonip-configuration-ipv4mask
219 anonip-configuration-ipv6mask
220 anonip-configuration-increment
221 anonip-configuration-delimiter
222 anonip-configuration-regex
225 varnish-configuration
226 varnish-configuration?
227 varnish-configuration-package
228 varnish-configuration-name
229 varnish-configuration-backend
230 varnish-configuration-vcl
231 varnish-configuration-listen
232 varnish-configuration-storage
233 varnish-configuration-parameters
234 varnish-configuration-extra-options
238 patchwork-database-configuration
239 patchwork-database-configuration?
240 patchwork-database-configuration-engine
241 patchwork-database-configuration-name
242 patchwork-database-configuration-user
243 patchwork-database-configuration-password
244 patchwork-database-configuration-host
245 patchwork-database-configuration-port
247 patchwork-settings-module
248 patchwork-settings-module?
249 patchwork-settings-module-database-configuration
250 patchwork-settings-module-secret-key
251 patchwork-settings-module-allowed-hosts
252 patchwork-settings-module-default-from-email
253 patchwork-settings-module-static-url
254 patchwork-settings-module-admins
255 patchwork-settings-module-debug?
256 patchwork-settings-module-enable-rest-api?
257 patchwork-settings-module-enable-xmlrpc?
258 patchwork-settings-module-force-https-links?
259 patchwork-settings-module-extra-settings
261 patchwork-configuration
262 patchwork-configuration?
263 patchwork-configuration-patchwork
264 patchwork-configuration-settings-module
265 patchwork-configuration-domain
267 patchwork-virtualhost
268 patchwork-service-type
272 mumi-configuration-mumi
273 mumi-configuration-mailer?
274 mumi-configuration-sender
275 mumi-configuration-smtp
279 gmnisrv-configuration
280 gmnisrv-configuration?
281 gmnisrv-configuration-package
282 gmnisrv-configuration-config-file
288 agate-configuration-package
289 agate-configuration-content
290 agate-configuration-cert
291 agate-configuration-key
292 agate-configuration-addr
293 agate-configuration-hostname
294 agate-configuration-lang
295 agate-configuration-silent
296 agate-configuration-serve-secret
297 agate-configuration-log-ip
298 agate-configuration-user
299 agate-configuration-group
300 agate-configuration-log-file
310 (define-record-type* <httpd-module>
311 httpd-module make-httpd-module
313 (name httpd-load-module-name)
314 (file httpd-load-module-file))
316 ;; Default modules for the httpd-service-type, taken from etc/httpd/httpd.conf
317 ;; file in the httpd package.
318 (define %default-httpd-modules
324 '(("authn_file_module" "modules/mod_authn_file.so")
325 ("authn_core_module" "modules/mod_authn_core.so")
326 ("authz_host_module" "modules/mod_authz_host.so")
327 ("authz_groupfile_module" "modules/mod_authz_groupfile.so")
328 ("authz_user_module" "modules/mod_authz_user.so")
329 ("authz_core_module" "modules/mod_authz_core.so")
330 ("access_compat_module" "modules/mod_access_compat.so")
331 ("auth_basic_module" "modules/mod_auth_basic.so")
332 ("reqtimeout_module" "modules/mod_reqtimeout.so")
333 ("filter_module" "modules/mod_filter.so")
334 ("mime_module" "modules/mod_mime.so")
335 ("log_config_module" "modules/mod_log_config.so")
336 ("env_module" "modules/mod_env.so")
337 ("headers_module" "modules/mod_headers.so")
338 ("setenvif_module" "modules/mod_setenvif.so")
339 ("version_module" "modules/mod_version.so")
340 ("unixd_module" "modules/mod_unixd.so")
341 ("status_module" "modules/mod_status.so")
342 ("autoindex_module" "modules/mod_autoindex.so")
343 ("dir_module" "modules/mod_dir.so")
344 ("alias_module" "modules/mod_alias.so"))))
346 (define-record-type* <httpd-config-file>
347 httpd-config-file make-httpd-config-file
349 (modules httpd-config-file-modules
350 (default %default-httpd-modules))
351 (server-root httpd-config-file-server-root
353 (server-name httpd-config-file-server-name
355 (document-root httpd-config-file-document-root
356 (default "/srv/http"))
357 (listen httpd-config-file-listen
359 (pid-file httpd-config-file-pid-file
360 (default "/var/run/httpd"))
361 (error-log httpd-config-file-error-log
362 (default "/var/log/httpd/error_log"))
363 (user httpd-config-file-user
365 (group httpd-config-file-group
367 (extra-config httpd-config-file-extra-config
369 (list "TypesConfig etc/httpd/mime.types"))))
371 (define-gexp-compiler (httpd-config-file-compiler
372 (file <httpd-config-file>) system target)
374 (($ <httpd-config-file> load-modules server-root server-name
375 document-root listen pid-file error-log
376 user group extra-config)
379 #~(call-with-output-file (ungexp output "out")
386 (($ <httpd-module> name module)
387 `("LoadModule " ,name " " ,module "\n")))
389 ,@`("ServerRoot " ,server-root "\n")
391 `("ServerName " ,server-name "\n")
393 ,@`("DocumentRoot " ,document-root "\n")
395 (lambda (listen-value)
396 `("Listen " ,listen-value "\n"))
399 `("Pidfile " ,pid-file "\n")
402 `("ErrorLog " ,error-log "\n")
405 `("User " ,user "\n")
408 `("Group " ,group "\n")
413 #:local-build? #t))))
415 (define-record-type <httpd-virtualhost>
416 (httpd-virtualhost addresses-and-ports contents)
418 (addresses-and-ports httpd-virtualhost-addresses-and-ports)
419 (contents httpd-virtualhost-contents))
421 (define-record-type* <httpd-configuration>
422 httpd-configuration make-httpd-configuration
424 (package httpd-configuration-package
426 (pid-file httpd-configuration-pid-file
427 (default "/var/run/httpd"))
428 (config httpd-configuration-config
429 (default (httpd-config-file))))
431 (define %httpd-accounts
432 (list (user-group (name "httpd") (system? #t))
437 (comment "Apache HTTPD server user")
438 (home-directory "/var/empty")
439 (shell (file-append shadow "/sbin/nologin")))))
441 (define httpd-shepherd-services
443 (($ <httpd-configuration> package pid-file config)
444 (list (shepherd-service
446 (documentation "The Apache HTTP Server")
447 (requirement '(networking))
448 (start #~(make-forkexec-constructor
449 `(#$(file-append package "/bin/httpd")
453 #:pid-file #$pid-file))
454 (stop #~(make-kill-destructor)))))))
456 (define httpd-activation
458 (($ <httpd-configuration> package pid-file config)
462 (error-log document-root)
464 (use-modules (guix build utils))
466 (mkdir-p #$(dirname error-log))
467 (mkdir-p #$document-root))))))
469 (define (httpd-process-extensions original-config extension-configs)
470 (let ((config (httpd-configuration-config
472 (if (httpd-config-file? config)
474 (inherit original-config)
479 (append (httpd-config-file-extra-config config)
482 (($ <httpd-virtualhost>
486 "\n<VirtualHost " addresses-and-ports ">\n")
488 "\n</VirtualHost>\n"))
493 extension-configs)))))))))
495 (define httpd-service-type
496 (service-type (name 'httpd)
498 (list (service-extension shepherd-root-service-type
499 httpd-shepherd-services)
500 (service-extension activation-service-type
502 (service-extension account-service-type
503 (const %httpd-accounts))))
504 (compose concatenate)
505 (extend httpd-process-extensions)
507 (httpd-configuration))
508 (description "Run the Apache httpd Web server.")))
510 (define-record-type* <nginx-server-configuration>
511 nginx-server-configuration make-nginx-server-configuration
512 nginx-server-configuration?
513 (listen nginx-server-configuration-listen
514 (default '("80" "443 ssl")))
515 (server-name nginx-server-configuration-server-name
516 (default (list 'default)))
517 (root nginx-server-configuration-root
518 (default "/srv/http"))
519 (locations nginx-server-configuration-locations
521 (index nginx-server-configuration-index
522 (default (list "index.html")))
523 (try-files nginx-server-configuration-try-files
525 (ssl-certificate nginx-server-configuration-ssl-certificate
527 (ssl-certificate-key nginx-server-configuration-ssl-certificate-key
529 (server-tokens? nginx-server-configuration-server-tokens?
531 (raw-content nginx-server-configuration-raw-content
534 (define-record-type* <nginx-upstream-configuration>
535 nginx-upstream-configuration make-nginx-upstream-configuration
536 nginx-upstream-configuration?
537 (name nginx-upstream-configuration-name)
538 (servers nginx-upstream-configuration-servers)
539 (extra-content nginx-upstream-configuration-extra-content
542 (define-record-type* <nginx-location-configuration>
543 nginx-location-configuration make-nginx-location-configuration
544 nginx-location-configuration?
545 (uri nginx-location-configuration-uri
547 (body nginx-location-configuration-body))
549 (define-record-type* <nginx-named-location-configuration>
550 nginx-named-location-configuration make-nginx-named-location-configuration
551 nginx-named-location-configuration?
552 (name nginx-named-location-configuration-name
554 (body nginx-named-location-configuration-body))
556 (define-record-type* <nginx-configuration>
557 nginx-configuration make-nginx-configuration
559 (nginx nginx-configuration-nginx ;file-like
561 (shepherd-requirement nginx-configuration-shepherd-requirement
562 (default '())) ;list of symbols
563 (log-directory nginx-configuration-log-directory ;string
564 (default "/var/log/nginx"))
565 (run-directory nginx-configuration-run-directory ;string
566 (default "/var/run/nginx"))
567 (server-blocks nginx-configuration-server-blocks
568 (default '())) ;list of <nginx-server-configuration>
569 (upstream-blocks nginx-configuration-upstream-blocks
570 (default '())) ;list of <nginx-upstream-configuration>
571 (server-names-hash-bucket-size nginx-configuration-server-names-hash-bucket-size
573 (server-names-hash-bucket-max-size nginx-configuration-server-names-hash-bucket-max-size
575 (modules nginx-configuration-modules (default '()))
576 (global-directives nginx-configuration-global-directives
577 (default '((events . ()))))
578 (lua-package-path nginx-lua-package-path ;list of file-like
580 (lua-package-cpath nginx-lua-package-cpath ;list of file-like
582 (extra-content nginx-configuration-extra-content
584 (file nginx-configuration-file ;#f | string | file-like
587 (define (config-domain-strings names)
588 "Return a string denoting the nginx config representation of NAMES, a list
592 ((? string? str) (list str " ")))
595 (define (config-index-strings names)
596 "Return a string denoting the nginx config representation of NAMES, a list
599 ((? string? str) (list str " ")))
602 (define (emit-load-module module)
603 (list "load_module " module ";\n"))
605 (define emit-global-directive
607 ((key . (? list? alist))
608 (format #f "~a { ~{~a~}}~%" key (map emit-global-directive alist)))
610 (format #f "~a ~a;~%" key value))))
612 (define emit-nginx-location-config
614 (($ <nginx-location-configuration> uri body)
616 " location " uri " {\n"
617 (map (lambda (x) (list " " x "\n")) body)
619 (($ <nginx-named-location-configuration> name body)
621 " location @" name " {\n"
622 (map (lambda (x) (list " " x "\n")) body)
625 (define (emit-nginx-server-config server)
626 (let ((listen (nginx-server-configuration-listen server))
627 (server-name (nginx-server-configuration-server-name server))
628 (ssl-certificate (nginx-server-configuration-ssl-certificate server))
630 (nginx-server-configuration-ssl-certificate-key server))
631 (root (nginx-server-configuration-root server))
632 (index (nginx-server-configuration-index server))
633 (try-files (nginx-server-configuration-try-files server))
634 (server-tokens? (nginx-server-configuration-server-tokens? server))
635 (locations (nginx-server-configuration-locations server))
636 (raw-content (nginx-server-configuration-raw-content server)))
637 (define-syntax-parameter <> (syntax-rules ()))
638 (define-syntax-rule (and/l x tail ...)
641 (syntax-parameterize ((<> (identifier-syntax x*)))
646 (map (lambda (directive) (list " listen " directive ";\n")) listen)
647 " server_name " (config-domain-strings server-name) ";\n"
648 (and/l ssl-certificate " ssl_certificate " <> ";\n")
649 (and/l ssl-certificate-key " ssl_certificate_key " <> ";\n")
650 (if (not (equal? "" root))
651 (list " root " root ";\n")
653 (if (not (null? index))
654 (list " index " (config-index-strings index) ";\n")
656 (if (not (nil? try-files))
657 (and/l (config-index-strings try-files) " try_files " <> ";\n")
659 " server_tokens " (if server-tokens? "on" "off") ";\n"
661 (map emit-nginx-location-config locations)
663 (map (lambda (x) (list " " x "\n")) raw-content)
666 (define (emit-nginx-upstream-config upstream)
668 " upstream " (nginx-upstream-configuration-name upstream) " {\n"
669 (map (lambda (server)
670 (simple-format #f " server ~A;\n" server))
671 (nginx-upstream-configuration-servers upstream))
673 (nginx-upstream-configuration-extra-content upstream)))
674 (if (and extra-content (not (null? extra-content)))
678 (simple-format #f " ~A\n" line))
679 (flatten extra-content)))
683 (define (flatten . lst)
684 "Return a list that recursively concatenates all sub-lists of LST."
685 (define (flatten1 head out)
687 (fold-right flatten1 out head)
689 (fold-right flatten1 '() lst))
691 (define (default-nginx-config config)
693 <nginx-configuration>
694 (nginx log-directory run-directory
695 server-blocks upstream-blocks
696 server-names-hash-bucket-size
697 server-names-hash-bucket-max-size
703 (apply mixed-text-file "nginx.conf"
705 "user nginx nginx;\n"
706 "pid " run-directory "/pid;\n"
707 "error_log " log-directory "/error.log info;\n"
708 (map emit-load-module modules)
709 (map emit-global-directive global-directives)
711 " client_body_temp_path " run-directory "/client_body_temp;\n"
712 " proxy_temp_path " run-directory "/proxy_temp;\n"
713 " fastcgi_temp_path " run-directory "/fastcgi_temp;\n"
714 " uwsgi_temp_path " run-directory "/uwsgi_temp;\n"
715 " scgi_temp_path " run-directory "/scgi_temp;\n"
716 " access_log " log-directory "/access.log;\n"
717 " include " nginx "/share/nginx/conf/mime.types;\n"
719 #~(format #f " lua_package_path ~s;~%"
720 (string-join (map (lambda (path)
721 (string-append path "/lib/?.lua"))
725 (if lua-package-cpath
726 #~(format #f " lua_package_cpath ~s;~%"
727 (string-join (map (lambda (cpath)
728 (string-append cpath "/lib/lua/?.lua"))
729 '#$lua-package-cpath)
732 (if server-names-hash-bucket-size
734 " server_names_hash_bucket_size "
735 (number->string server-names-hash-bucket-size)
738 (if server-names-hash-bucket-max-size
740 " server_names_hash_bucket_max_size "
741 (number->string server-names-hash-bucket-max-size)
745 (map emit-nginx-upstream-config upstream-blocks)
746 (map emit-nginx-server-config server-blocks)
750 (define %nginx-accounts
751 (list (user-group (name "nginx") (system? #t))
756 (comment "nginx server user")
757 (home-directory "/var/empty")
758 (shell (file-append shadow "/sbin/nologin")))))
760 (define (nginx-activation config)
762 <nginx-configuration>
763 (nginx log-directory run-directory file)
765 (use-modules (guix build utils))
767 (format #t "creating nginx log directory '~a'~%" #$log-directory)
768 (mkdir-p #$log-directory)
769 (format #t "creating nginx run directory '~a'~%" #$run-directory)
770 (mkdir-p #$run-directory)
771 (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory)
772 (mkdir-p (string-append #$run-directory "/client_body_temp"))
773 (mkdir-p (string-append #$run-directory "/proxy_temp"))
774 (mkdir-p (string-append #$run-directory "/fastcgi_temp"))
775 (mkdir-p (string-append #$run-directory "/uwsgi_temp"))
776 (mkdir-p (string-append #$run-directory "/scgi_temp"))
777 ;; Start-up logs. Once configuration is loaded, nginx switches to
779 (mkdir-p (string-append #$run-directory "/logs"))
780 ;; Check configuration file syntax.
781 (system* (string-append #$nginx "/sbin/nginx")
783 (default-nginx-config config))
787 (define (nginx-shepherd-service config)
789 <nginx-configuration>
790 (nginx file run-directory shepherd-requirement)
791 (let* ((nginx-binary (file-append nginx "/sbin/nginx"))
792 (pid-file (in-vicinity run-directory "pid"))
796 (invoke #$nginx-binary "-c"
798 (default-nginx-config config))
803 ;; When FILE is true, we cannot be sure that PID-FILE will
804 ;; be created, so assume it won't show up. When FILE is
805 ;; false, read PID-FILE.
808 #~(read-pid-file #$pid-file))))))))
810 (list (shepherd-service
812 (documentation "Run the nginx daemon.")
813 (requirement `(user-processes loopback ,@shepherd-requirement))
814 (modules `((ice-9 match)
816 (start (nginx-action "-p" run-directory))
817 (stop (nginx-action "-s" "stop"))
822 (documentation "Reload nginx configuration file and restart worker processes.
823 This has the effect of killing old worker processes and starting new ones, using
824 the same configuration file. It is useful for situations where the same nginx
825 configuration file can point to different things after a reload, such as
826 renewed TLS certificates, or @code{include}d files.")
827 (procedure (nginx-action "-s" "reload"))))))))))
829 (define nginx-service-type
830 (service-type (name 'nginx)
832 (list (service-extension shepherd-root-service-type
833 nginx-shepherd-service)
834 (service-extension activation-service-type
836 (service-extension account-service-type
837 (const %nginx-accounts))))
838 (compose concatenate)
839 (extend (lambda (config servers)
843 (append (nginx-configuration-server-blocks config)
845 (default-value (nginx-configuration))
846 (description "Run the nginx Web server.")))
848 (define-record-type* <fcgiwrap-configuration> fcgiwrap-configuration
849 make-fcgiwrap-configuration
850 fcgiwrap-configuration?
851 (package fcgiwrap-configuration-package ;file-like
853 (socket fcgiwrap-configuration-socket
854 (default "tcp:127.0.0.1:9000"))
855 (user fcgiwrap-configuration-user
856 (default "fcgiwrap"))
857 (group fcgiwrap-configuration-group
858 (default "fcgiwrap")))
860 (define fcgiwrap-accounts
862 (($ <fcgiwrap-configuration> package socket user group)
865 (and (equal? group "fcgiwrap")
869 (and (equal? user "fcgiwrap")
874 (comment "Fcgiwrap Daemon")
875 (home-directory "/var/empty")
876 (shell (file-append shadow "/sbin/nologin")))))))))
878 (define fcgiwrap-shepherd-service
880 (($ <fcgiwrap-configuration> package socket user group)
881 (list (shepherd-service
882 (provision '(fcgiwrap))
883 (documentation "Run the fcgiwrap daemon.")
884 (requirement '(networking))
885 (start #~(make-forkexec-constructor
886 '(#$(file-append package "/sbin/fcgiwrap")
888 #:user #$user #:group #$group
889 #:log-file "/var/log/fcgiwrap.log"))
890 (stop #~(make-kill-destructor)))))))
892 (define fcgiwrap-activation
894 (($ <fcgiwrap-configuration> package socket user group)
896 ;; When listening on a unix socket, create a parent directory for the
897 ;; socket with the correct permissions.
898 (when (string-prefix? "unix:" #$socket)
900 (dirname (substring #$socket (string-length "unix:")))))
901 (mkdir-p run-directory)
903 (passwd:uid (getpw #$user))
904 (group:gid (getgr #$group)))))))))
906 (define fcgiwrap-service-type
907 (service-type (name 'fcgiwrap)
909 (list (service-extension shepherd-root-service-type
910 fcgiwrap-shepherd-service)
911 (service-extension account-service-type
913 (service-extension activation-service-type
914 fcgiwrap-activation)))
915 (default-value (fcgiwrap-configuration))
916 (description "Run FastCGI, an interface between the front-end
917 and the back-end of a Web service.")))
919 (define-record-type* <php-fpm-configuration> php-fpm-configuration
920 make-php-fpm-configuration
921 php-fpm-configuration?
922 (php php-fpm-configuration-php ;file-like
924 (socket php-fpm-configuration-socket
925 (default (string-append "/var/run/php"
926 (version-major (package-version php))
928 (user php-fpm-configuration-user
930 (group php-fpm-configuration-group
932 (socket-user php-fpm-configuration-socket-user
934 (socket-group php-fpm-configuration-socket-group
936 (pid-file php-fpm-configuration-pid-file
937 (default (string-append "/var/run/php"
938 (version-major (package-version php))
940 (log-file php-fpm-configuration-log-file
941 (default (string-append "/var/log/php"
942 (version-major (package-version php))
944 (process-manager php-fpm-configuration-process-manager
945 (default (php-fpm-dynamic-process-manager-configuration)))
946 (display-errors php-fpm-configuration-display-errors
948 (timezone php-fpm-configuration-timezone
950 (workers-log-file php-fpm-configuration-workers-log-file
951 (default (string-append "/var/log/php"
952 (version-major (package-version php))
954 (file php-fpm-configuration-file ;#f | file-like
956 (php-ini-file php-fpm-configuration-php-ini-file ;#f | file-like
959 (define-record-type* <php-fpm-dynamic-process-manager-configuration>
960 php-fpm-dynamic-process-manager-configuration
961 make-php-fpm-dynamic-process-manager-configuration
962 php-fpm-dynamic-process-manager-configuration?
963 (max-children php-fpm-dynamic-process-manager-configuration-max-children
965 (start-servers php-fpm-dynamic-process-manager-configuration-start-servers
967 (min-spare-servers php-fpm-dynamic-process-manager-configuration-min-spare-servers
969 (max-spare-servers php-fpm-dynamic-process-manager-configuration-max-spare-servers
972 (define-record-type* <php-fpm-static-process-manager-configuration>
973 php-fpm-static-process-manager-configuration
974 make-php-fpm-static-process-manager-configuration
975 php-fpm-static-process-manager-configuration?
976 (max-children php-fpm-static-process-manager-configuration-max-children
979 (define-record-type* <php-fpm-on-demand-process-manager-configuration>
980 php-fpm-on-demand-process-manager-configuration
981 make-php-fpm-on-demand-process-manager-configuration
982 php-fpm-on-demand-process-manager-configuration?
983 (max-children php-fpm-on-demand-process-manager-configuration-max-children
985 (process-idle-timeout php-fpm-on-demand-process-manager-configuration-process-idle-timeout
988 (define php-fpm-accounts
990 (($ <php-fpm-configuration> php socket user group socket-user socket-group _ _ _ _ _ _)
991 `(,@(if (equal? group "php-fpm")
993 (list (user-group (name "php-fpm") (system? #t))))
1000 (supplementary-groups '("php-fpm"))
1002 (comment "php-fpm daemon user")
1003 (home-directory "/var/empty")
1004 (shell (file-append shadow "/sbin/nologin")))))))
1006 (define (default-php-fpm-config socket user group socket-user socket-group
1007 pid-file log-file pm display-errors timezone workers-log-file)
1008 (apply mixed-text-file "php-fpm.conf"
1011 "pid =" pid-file "\n"
1012 "error_log =" log-file "\n"
1015 "group =" group "\n"
1016 "listen =" socket "\n"
1017 "listen.owner =" socket-user "\n"
1018 "listen.group =" socket-group "\n"
1021 (string-append "php_admin_value[date.timezone] = \"" timezone "\"\n")
1025 (($ <php-fpm-dynamic-process-manager-configuration>
1028 pm.min-spare-servers
1029 pm.max-spare-servers)
1032 "pm.max_children =" (number->string pm.max-children) "\n"
1033 "pm.start_servers =" (number->string pm.start-servers) "\n"
1034 "pm.min_spare_servers =" (number->string pm.min-spare-servers) "\n"
1035 "pm.max_spare_servers =" (number->string pm.max-spare-servers) "\n"))
1037 (($ <php-fpm-static-process-manager-configuration>
1041 "pm.max_children =" (number->string pm.max-children) "\n"))
1043 (($ <php-fpm-on-demand-process-manager-configuration>
1045 pm.process-idle-timeout)
1048 "pm.max_children =" (number->string pm.max-children) "\n"
1049 "pm.process_idle_timeout =" (number->string pm.process-idle-timeout) "s\n")))
1052 "php_flag[display_errors] = " (if display-errors "on" "off") "\n"
1054 (if workers-log-file
1055 (list "catch_workers_output = yes\n"
1056 "php_admin_value[error_log] =" workers-log-file "\n"
1057 "php_admin_flag[log_errors] = on\n")
1058 (list "catch_workers_output = no\n")))))
1060 (define php-fpm-shepherd-service
1062 (($ <php-fpm-configuration> php socket user group socket-user socket-group
1063 pid-file log-file pm display-errors
1064 timezone workers-log-file file php-ini-file)
1065 (list (shepherd-service
1066 (provision '(php-fpm))
1067 (documentation "Run the php-fpm daemon.")
1068 (requirement '(networking))
1069 (start #~(make-forkexec-constructor
1070 '(#$(file-append php "/sbin/php-fpm")
1073 (default-php-fpm-config socket user group
1074 socket-user socket-group pid-file log-file
1075 pm display-errors timezone workers-log-file))
1077 `("-c" ,php-ini-file)
1079 #:pid-file #$pid-file))
1080 (stop #~(make-kill-destructor)))))))
1082 (define (php-fpm-activation config)
1084 (use-modules (guix build utils))
1085 (let* ((user (getpwnam #$(php-fpm-configuration-user config)))
1086 (touch (lambda (file-name)
1087 (call-with-output-file file-name (const #t))))
1089 #$(php-fpm-configuration-workers-log-file config))
1092 (when workers-log-file
1093 (when (not (file-exists? file-name))
1095 (chown file-name (passwd:uid user) (passwd:gid user))
1096 (chmod file-name #o660)))))
1097 (init-log-file #$(php-fpm-configuration-log-file config))
1098 (init-log-file workers-log-file))))
1101 (define php-fpm-service-type
1105 "Run @command{php-fpm} to provide a fastcgi socket for calling php through
1108 (list (service-extension shepherd-root-service-type
1109 php-fpm-shepherd-service)
1110 (service-extension activation-service-type
1112 (service-extension account-service-type
1114 (default-value (php-fpm-configuration))))
1116 (define* (nginx-php-location
1118 (nginx-package nginx)
1119 (socket (string-append "/var/run/php"
1120 (version-major (package-version php))
1122 "Return a nginx-location-configuration that makes nginx run .php files."
1123 (nginx-location-configuration
1126 "fastcgi_split_path_info ^(.+\\.php)(/.+)$;"
1127 (string-append "fastcgi_pass unix:" socket ";")
1128 "fastcgi_index index.php;"
1129 (list "include " nginx-package "/share/nginx/conf/fastcgi.conf;")))))
1131 (define* (cat-avatar-generator-service
1133 (cache-dir "/var/cache/cat-avatar-generator")
1134 (package cat-avatar-generator)
1135 (configuration (nginx-server-configuration)))
1137 'cat-http-server nginx-service-type
1138 (list (nginx-server-configuration
1139 (inherit configuration)
1142 (let ((base (nginx-php-location)))
1143 (nginx-location-configuration
1145 (body (list (string-append "fastcgi_param CACHE_DIR \""
1147 (nginx-location-configuration-body base)))))
1148 (nginx-server-configuration-locations configuration)))
1149 (root #~(string-append #$package
1150 "/share/web/cat-avatar-generator"))))))
1153 (define-record-type* <hpcguix-web-configuration>
1154 hpcguix-web-configuration make-hpcguix-web-configuration
1155 hpcguix-web-configuration?
1157 (package hpcguix-web-package (default hpcguix-web)) ;file-like
1159 ;; Specs is gexp of hpcguix-web configuration file
1160 (specs hpcguix-web-configuration-specs)
1161 (address hpcguix-web-configuration-address (default "127.0.0.1"))
1162 (port hpcguix-web-configuration-port (default 5000)))
1164 (define %hpcguix-web-accounts
1166 (name "hpcguix-web")
1169 (name "hpcguix-web")
1170 (group "hpcguix-web")
1172 (comment "hpcguix-web")
1173 (home-directory "/var/empty")
1174 (shell (file-append shadow "/sbin/nologin")))))
1176 (define %hpcguix-web-activation
1177 (with-imported-modules '((guix build utils))
1179 (use-modules (guix build utils)
1182 (let ((home-dir "/var/cache/guix/web")
1183 (user (getpwnam "hpcguix-web")))
1185 (chown home-dir (passwd:uid user) (passwd:gid user))
1186 (chmod home-dir #o755)
1188 ;; Remove stale 'packages.json.lock' file (and other lock files, if
1189 ;; any) since that would prevent 'packages.json' from being updated.
1190 (for-each (lambda (lock)
1191 (delete-file (string-append home-dir "/" lock)))
1194 (string-suffix? ".lock" file))))))))
1196 (define %hpcguix-web-log-file
1197 "/var/log/hpcguix-web.log")
1199 (define %hpcguix-web-log-rotations
1201 (files (list %hpcguix-web-log-file))
1202 (frequency 'weekly))))
1204 (define (hpcguix-web-shepherd-service config)
1205 (let ((specs (hpcguix-web-configuration-specs config))
1206 (hpcguix-web (hpcguix-web-package config)))
1207 (with-imported-modules (source-module-closure
1208 '((gnu build shepherd)))
1210 (documentation "hpcguix-web daemon")
1211 (provision '(hpcguix-web))
1212 (requirement '(networking))
1213 (start #~(make-forkexec-constructor
1214 (list #$(file-append hpcguix-web "/bin/hpcguix-web")
1215 (string-append "--listen="
1216 #$(hpcguix-web-configuration-address
1220 (hpcguix-web-configuration-port config))
1221 (string-append "--config="
1222 #$(scheme-file "hpcguix-web.scm" specs)))
1223 #:user "hpcguix-web"
1224 #:group "hpcguix-web"
1225 #:environment-variables
1226 (list "XDG_CACHE_HOME=/var/cache/guix/web"
1227 "SSL_CERT_DIR=/etc/ssl/certs")
1228 #:log-file #$%hpcguix-web-log-file))
1229 (stop #~(make-kill-destructor))))))
1231 (define hpcguix-web-service-type
1234 (description "Run the hpcguix-web server.")
1236 (list (service-extension account-service-type
1237 (const %hpcguix-web-accounts))
1238 (service-extension activation-service-type
1239 (const %hpcguix-web-activation))
1240 (service-extension rottlog-service-type
1241 (const %hpcguix-web-log-rotations))
1242 (service-extension shepherd-root-service-type
1243 (compose list hpcguix-web-shepherd-service))))))
1250 (define-record-type* <tailon-configuration-file>
1251 tailon-configuration-file make-tailon-configuration-file
1252 tailon-configuration-file?
1253 (files tailon-configuration-file-files
1254 (default '("/var/log")))
1255 (bind tailon-configuration-file-bind
1256 (default "localhost:8080"))
1257 (relative-root tailon-configuration-file-relative-root
1259 (allow-transfers? tailon-configuration-file-allow-transfers?
1261 (follow-names? tailon-configuration-file-follow-names?
1263 (tail-lines tailon-configuration-file-tail-lines
1265 (allowed-commands tailon-configuration-file-allowed-commands
1266 (default '("tail" "grep" "awk")))
1267 (debug? tailon-configuration-file-debug?
1269 (wrap-lines tailon-configuration-file-wrap-lines
1271 (http-auth tailon-configuration-file-http-auth
1273 (users tailon-configuration-file-users
1276 (define (tailon-configuration-files-string files)
1286 (simple-format #f "'~A'" x))
1289 (cons (simple-format #f "'~A':" (car x))
1291 (lambda (x) (simple-format #f " - '~A'" x))
1298 (define-gexp-compiler (tailon-configuration-file-compiler
1299 (file <tailon-configuration-file>) system target)
1301 (($ <tailon-configuration-file> files bind relative-root
1302 allow-transfers? follow-names?
1303 tail-lines allowed-commands debug?
1304 wrap-lines http-auth users)
1306 "tailon-config.yaml"
1311 ((key . value) (string-append key ": " value "\n")))
1313 `(("files" . ,(tailon-configuration-files-string files))
1315 ("relative-root" . ,relative-root)
1316 ("allow-transfers" . ,(if allow-transfers? "true" "false"))
1317 ("follow-names" . ,(if follow-names? "true" "false"))
1318 ("tail-lines" . ,(number->string tail-lines))
1319 ("commands" . ,(string-append "["
1320 (string-join allowed-commands ", ")
1322 ("debug" . ,(if debug? "true" #f))
1323 ("wrap-lines" . ,(if wrap-lines "true" "false"))
1324 ("http-auth" . ,http-auth)
1325 ("users" . ,(if users
1331 " " user ":" pass)))
1335 (define-record-type* <tailon-configuration>
1336 tailon-configuration make-tailon-configuration
1337 tailon-configuration?
1338 (config-file tailon-configuration-config-file
1339 (default (tailon-configuration-file)))
1340 (package tailon-configuration-package
1343 (define tailon-shepherd-service
1345 (($ <tailon-configuration> config-file package)
1346 (list (shepherd-service
1347 (provision '(tailon))
1348 (documentation "Run the tailon daemon.")
1349 (start #~(make-forkexec-constructor
1350 `(,(string-append #$package "/bin/tailon")
1351 "-c" ,#$config-file)
1354 (stop #~(make-kill-destructor)))))))
1356 (define %tailon-accounts
1357 (list (user-group (name "tailon") (system? #t))
1363 (home-directory "/var/empty")
1364 (shell (file-append shadow "/sbin/nologin")))))
1366 (define tailon-service-type
1370 "Run Tailon, a Web application for monitoring, viewing, and searching log
1373 (list (service-extension shepherd-root-service-type
1374 tailon-shepherd-service)
1375 (service-extension account-service-type
1376 (const %tailon-accounts))))
1377 (compose concatenate)
1378 (extend (lambda (parameter files)
1379 (tailon-configuration
1382 (let ((old-config-file
1383 (tailon-configuration-config-file parameter)))
1384 (tailon-configuration-file
1385 (inherit old-config-file)
1386 (files (append (tailon-configuration-file-files old-config-file)
1388 (default-value (tailon-configuration))))
1393 ;;; Log anonymization
1396 (define-record-type* <anonip-configuration>
1397 anonip-configuration make-anonip-configuration
1398 anonip-configuration?
1399 (anonip anonip-configuration-anonip ;file-like
1401 (input anonip-configuration-input) ;string
1402 (output anonip-configuration-output) ;string
1403 (skip-private? anonip-configuration-skip-private? ;boolean
1405 (column anonip-configuration-column ;number
1407 (replacement anonip-configuration-replacement ;string
1409 (ipv4mask anonip-configuration-ipv4mask ;number
1411 (ipv6mask anonip-configuration-ipv6mask ;number
1413 (increment anonip-configuration-increment ;number
1415 (delimiter anonip-configuration-delimiter ;string
1417 (regex anonip-configuration-regex ;string
1420 (define (anonip-activation config)
1421 (with-imported-modules '((guix build utils))
1423 (use-modules (guix build utils))
1427 (chmod directory #o755))
1428 (list (dirname #$(anonip-configuration-input config))
1429 (dirname #$(anonip-configuration-output config)))))))
1431 (define (anonip-shepherd-service config)
1432 (let ((input (anonip-configuration-input config))
1433 (output (anonip-configuration-output config))
1435 (lambda (accessor option)
1436 (or (and=> (accessor config)
1439 (format #false "~a=~a"
1445 (list (symbol-append 'anonip- (string->symbol output))))
1446 (requirement '(user-processes))
1448 "Anonimyze the given log file location with anonip.")
1454 (list #$(file-append (anonip-configuration-anonip config)
1456 (string-append "--input=" #$input)
1457 (string-append "--output=" #$output))
1458 (if #$(anonip-configuration-skip-private? config)
1459 '("--skip-private") (list))
1460 '#$(optional anonip-configuration-column "--column")
1461 '#$(optional anonip-configuration-ipv4mask "--ipv4mask")
1462 '#$(optional anonip-configuration-ipv6mask "--ipv6mask")
1463 '#$(optional anonip-configuration-increment "--increment")
1464 '#$(optional anonip-configuration-replacement
1466 '#$(optional anonip-configuration-delimiter "--delimiter")
1467 '#$(optional anonip-configuration-regex "--regex"))
1468 ;; Run in a UTF-8 locale
1469 #:environment-variables
1470 (list (string-append "GUIX_LOCPATH=" #$glibc-utf8-locales
1472 "LC_ALL=en_US.utf8")))
1474 (let ((stat (stat #$input #f)))
1476 (mknod #$input 'fifo #o600 0)
1478 ((eq? 'fifo (stat:type stat))
1481 (format #t "'~a' is not a FIFO; bailing out~%"
1484 (stop #~(make-kill-destructor))))))
1486 (define anonip-service-type
1490 (list (service-extension shepherd-root-service-type
1491 anonip-shepherd-service)
1492 (service-extension activation-service-type
1493 anonip-activation)))
1495 "Provide web server log anonymization with @command{anonip}.")))
1502 (define-record-type* <varnish-configuration>
1503 varnish-configuration make-varnish-configuration
1504 varnish-configuration?
1505 (package varnish-configuration-package ;file-like
1507 (name varnish-configuration-name ;string
1508 (default "default"))
1509 (backend varnish-configuration-backend ;string
1510 (default "localhost:8080"))
1511 (vcl varnish-configuration-vcl ;#f | <file-like>
1513 (listen varnish-configuration-listen ;list of strings
1514 (default '("localhost:80")))
1515 (storage varnish-configuration-storage ;list of strings
1516 (default '("malloc,128m")))
1517 (parameters varnish-configuration-parameters ;list of string pairs
1519 (extra-options varnish-configuration-extra-options ;list of strings
1522 (define %varnish-accounts
1530 (comment "Varnish Cache User")
1531 (home-directory "/var/varnish")
1532 (shell (file-append shadow "/sbin/nologin")))))
1534 (define varnish-shepherd-service
1536 (($ <varnish-configuration> package name backend vcl listen storage
1537 parameters extra-options)
1538 (list (shepherd-service
1539 (provision (list (symbol-append 'varnish- (string->symbol name))))
1540 (documentation (string-append "The Varnish Web Accelerator"
1542 (requirement '(networking))
1543 (start #~(make-forkexec-constructor
1544 (list #$(file-append package "/sbin/varnishd")
1549 #$@(append-map (lambda (a) (list "-a" a)) listen)
1550 #$@(append-map (lambda (s) (list "-s" s)) storage)
1551 #$@(append-map (lambda (p)
1552 (list "-p" (format #f "~a=~a"
1556 ;; Varnish will drop privileges to the "varnish" user when
1557 ;; it exists. Not passing #:user here allows the service
1558 ;; to bind to ports < 1024.
1559 #:pid-file (if (string-prefix? "/" #$name)
1560 (string-append #$name "/_.pid")
1561 (string-append "/var/varnish/" #$name "/_.pid"))))
1562 (stop #~(make-kill-destructor)))))))
1564 (define varnish-service-type
1567 (description "Run the Varnish cache server.")
1569 (list (service-extension account-service-type
1570 (const %varnish-accounts))
1571 (service-extension shepherd-root-service-type
1572 varnish-shepherd-service)))
1574 (varnish-configuration))))
1581 (define-record-type* <patchwork-database-configuration>
1582 patchwork-database-configuration make-patchwork-database-configuration
1583 patchwork-database-configuration?
1584 (engine patchwork-database-configuration-engine
1585 (default "django.db.backends.postgresql_psycopg2"))
1586 (name patchwork-database-configuration-name
1587 (default "patchwork"))
1588 (user patchwork-database-configuration-user
1590 (password patchwork-database-configuration-password
1592 (host patchwork-database-configuration-host
1594 (port patchwork-database-configuration-port
1597 (define-record-type* <patchwork-settings-module>
1598 patchwork-settings-module make-patchwork-settings-module
1599 patchwork-settings-module?
1600 (database-configuration patchwork-settings-module-database-configuration
1601 (default (patchwork-database-configuration)))
1602 (secret-key-file patchwork-settings-module-secret-key-file
1603 (default "/etc/patchwork/django-secret-key"))
1604 (allowed-hosts patchwork-settings-module-allowed-hosts)
1605 (default-from-email patchwork-settings-module-default-from-email)
1606 (static-url patchwork-settings-module-static-url
1607 (default "/static/"))
1608 (admins patchwork-settings-module-admins
1610 (debug? patchwork-settings-module-debug?
1612 (enable-rest-api? patchwork-settings-module-enable-rest-api?
1614 (enable-xmlrpc? patchwork-settings-module-enable-xmlrpc?
1616 (force-https-links? patchwork-settings-module-force-https-links?
1618 (extra-settings patchwork-settings-module-extra-settings
1621 (define-record-type* <patchwork-configuration>
1622 patchwork-configuration make-patchwork-configuration
1623 patchwork-configuration?
1624 (patchwork patchwork-configuration-patchwork
1625 (default patchwork))
1626 (domain patchwork-configuration-domain)
1627 (settings-module patchwork-configuration-settings-module)
1628 (static-path patchwork-configuration-static-url
1629 (default "/static/"))
1630 (getmail-retriever-config getmail-retriever-config))
1632 ;; Django uses a Python module for configuration, so this compiler generates a
1633 ;; Python module from the configuration record.
1634 (define-gexp-compiler (patchwork-settings-module-compiler
1635 (file <patchwork-settings-module>) system target)
1637 (($ <patchwork-settings-module> database-configuration secret-key-file
1638 allowed-hosts default-from-email
1639 static-url admins debug? enable-rest-api?
1640 enable-xmlrpc? force-https-links?
1641 extra-configuration)
1643 "patchwork-settings"
1644 (with-imported-modules '((guix build utils))
1645 #~(let ((output #$output))
1646 (define (create-__init__.py filename)
1647 (call-with-output-file filename
1648 (lambda (port) (display "" port))))
1650 (use-modules (guix build utils)
1653 (mkdir-p (string-append output "/guix/patchwork"))
1655 (string-append output "/guix/__init__.py"))
1657 (string-append output "/guix/patchwork/__init__.py"))
1659 (call-with-output-file
1660 (string-append output "/guix/patchwork/settings.py")
1663 (string-append "from patchwork.settings.base import *
1665 # Configuration from Guix
1666 with open('" #$secret-key-file "') as f:
1667 SECRET_KEY = f.read().strip()
1670 " #$(string-concatenate
1671 (map (lambda (allowed-host)
1672 (string-append " '" allowed-host "'\n"))
1676 DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
1678 DEFAULT_FROM_EMAIL = '" #$default-from-email "'
1679 SERVER_EMAIL = DEFAULT_FROM_EMAIL
1680 NOTIFICATION_FROM_EMAIL = DEFAULT_FROM_EMAIL
1683 " #$(string-concatenate
1685 ((name email-address)
1687 "('" name "','" email-address "'),")))
1691 DEBUG = " #$(if debug? "True" "False") "
1693 ENABLE_REST_API = " #$(if enable-rest-api? "True" "False") "
1694 ENABLE_XMLRPC = " #$(if enable-xmlrpc? "True" "False") "
1696 FORCE_HTTPS_LINKS = " #$(if force-https-links? "True" "False") "
1700 " #$(match database-configuration
1701 (($ <patchwork-database-configuration>
1702 engine name user password host port)
1704 " 'ENGINE': '" engine "',\n"
1705 " 'NAME': '" name "',\n"
1706 " 'USER': '" user "',\n"
1707 " 'PASSWORD': '" password "',\n"
1708 " 'HOST': '" host "',\n"
1709 " 'PORT': '" port "',\n"))) "
1714 #~(string-append "STATIC_ROOT = '"
1715 #$(file-append patchwork "/share/patchwork/htdocs")
1717 #~(string-append "STATIC_URL = '" #$static-url "'")) "
1719 STATICFILES_STORAGE = (
1720 'django.contrib.staticfiles.storage.StaticFilesStorage'
1723 # Guix Extra Configuration
1724 " #$extra-configuration "
1727 #:local-build? #t))))
1729 (define patchwork-virtualhost
1731 (($ <patchwork-configuration> patchwork domain
1732 settings-module static-path
1733 getmail-retriever-config)
1735 (file-append patchwork
1738 (version-major+minor
1739 (package-version python))
1740 "/site-packages/patchwork/wsgi.py")))
1744 `("ServerAdmin admin@example.com`
1745 ServerName " ,domain "
1747 LogFormat \"%v %h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\"\" customformat
1749 CustomLog \"/var/log/httpd/" ,domain "-access_log\" customformat
1751 ErrorLog /var/log/httpd/error.log
1753 WSGIScriptAlias / " ,wsgi.py "
1754 WSGIDaemonProcess " ,(package-name patchwork) " user=httpd group=httpd processes=1 threads=2 display-name=%{GROUP} lang='en_US.UTF-8' locale='en_US.UTF-8' python-path=" ,settings-module "
1755 WSGIProcessGroup " ,(package-name patchwork) "
1756 WSGIPassAuthorization On
1758 <Files " ,wsgi.py ">
1763 `("Alias " ,static-path " " ,patchwork "/share/patchwork/htdocs/")
1766 <Directory \"/srv/http/" ,domain "/\">
1768 Options MultiViews Indexes SymlinksIfOwnerMatch IncludesNoExec
1769 Require method GET POST OPTIONS
1772 (define (patchwork-httpd-configuration patchwork-configuration)
1773 (list "WSGISocketPrefix /var/run/mod_wsgi"
1774 (list "LoadModule wsgi_module "
1775 (file-append mod-wsgi "/modules/mod_wsgi.so"))
1776 (patchwork-virtualhost patchwork-configuration)))
1778 (define (patchwork-django-admin-gexp patchwork settings-module)
1780 (let ((pid (primitive-fork))
1781 (user (getpwnam "httpd")))
1786 (setgid (passwd:gid user))
1787 (setuid (passwd:uid user))
1789 (setenv "DJANGO_SETTINGS_MODULE" "guix.patchwork.settings")
1790 (setenv "PYTHONPATH" #$settings-module)
1794 #$(file-append patchwork "/bin/patchwork-admin")
1799 (primitive-exit 1)))
1800 (zero? (cdr (waitpid pid)))))))
1802 (define (patchwork-django-admin-action patchwork settings-module)
1804 (name 'django-admin)
1806 "Run a django admin command for patchwork")
1807 (procedure (patchwork-django-admin-gexp patchwork settings-module))))
1809 (define patchwork-shepherd-services
1811 (($ <patchwork-configuration> patchwork domain
1812 settings-module static-path
1813 getmail-retriever-config)
1814 (define secret-key-file-creation-gexp
1815 (if (patchwork-settings-module? settings-module)
1816 (with-extensions (list guile-gcrypt)
1817 #~(let ((secret-key-file
1818 #$(patchwork-settings-module-secret-key-file
1820 (use-modules (guix build utils)
1823 (unless (file-exists? secret-key-file)
1824 (mkdir-p (dirname secret-key-file))
1825 (call-with-output-file secret-key-file
1827 (display (random-token 30 'very-strong) port)))
1828 (let* ((pw (getpwnam "httpd"))
1829 (uid (passwd:uid pw))
1830 (gid (passwd:gid pw)))
1831 (chown secret-key-file uid gid)
1832 (chmod secret-key-file #o400)))))
1835 (list (shepherd-service
1836 (requirement '(postgres))
1837 (provision (list (string->symbol
1838 (string-append (package-name patchwork)
1842 (define run-django-admin-command
1843 #$(patchwork-django-admin-gexp patchwork
1846 #$secret-key-file-creation-gexp
1848 (run-django-admin-command "migrate")))
1851 (list (patchwork-django-admin-action patchwork
1854 (documentation "Setup Patchwork."))))))
1856 (define patchwork-getmail-configs
1858 (($ <patchwork-configuration> patchwork domain
1859 settings-module static-path
1860 getmail-retriever-config)
1862 (getmail-configuration
1863 (name (string->symbol (package-name patchwork)))
1865 (directory (string-append
1866 "/var/lib/getmail/" (package-name patchwork)))
1868 (getmail-configuration-file
1869 (retriever getmail-retriever-config)
1871 (getmail-destination-configuration
1872 (type "MDA_external")
1873 (path (file-append patchwork "/bin/patchwork-admin"))
1875 '((arguments . ("parsemail"))))))
1877 (getmail-options-configuration
1882 (getmail-retriever-configuration-extra-parameters
1883 getmail-retriever-config)
1885 (environment-variables
1886 (list "DJANGO_SETTINGS_MODULE=guix.patchwork.settings"
1887 #~(string-append "PYTHONPATH=" #$settings-module))))))))
1889 (define patchwork-service-type
1891 (name 'patchwork-setup)
1893 (list (service-extension httpd-service-type
1894 patchwork-httpd-configuration)
1895 (service-extension shepherd-root-service-type
1896 patchwork-shepherd-services)
1897 (service-extension getmail-service-type
1898 patchwork-getmail-configs)))
1900 "Patchwork patch tracking system.")))
1907 (define-record-type* <mumi-configuration>
1908 mumi-configuration make-mumi-configuration
1910 (mumi mumi-configuration-mumi (default mumi))
1911 (mailer? mumi-configuration-mailer? (default #t))
1912 (sender mumi-configuration-sender (default #f))
1913 (smtp mumi-configuration-smtp (default #f)))
1915 (define %mumi-activation
1916 (with-imported-modules '((guix build utils))
1918 (use-modules (guix build utils))
1920 (mkdir-p "/var/mumi/db")
1921 (mkdir-p "/var/mumi/mails")
1922 (let* ((pw (getpwnam "mumi"))
1923 (uid (passwd:uid pw))
1924 (gid (passwd:gid pw)))
1925 (chown "/var/mumi" uid gid)
1926 (chown "/var/mumi/mails" uid gid)
1927 (chown "/var/mumi/db" uid gid)))))
1929 (define %mumi-accounts
1930 (list (user-group (name "mumi") (system? #t))
1935 (comment "Mumi web server")
1936 (home-directory "/var/empty")
1937 (shell (file-append shadow "/sbin/nologin")))))
1939 (define %mumi-log "/var/log/mumi.log")
1941 (define %mumi-mailer-log "/var/log/mumi.mailer.log")
1943 (define %mumi-worker-log "/var/log/mumi.worker.log")
1945 (define (mumi-shepherd-services config)
1947 #~(list "LC_ALL=en_US.utf8"
1948 (string-append "GUIX_LOCPATH=" #$glibc-utf8-locales
1952 (($ <mumi-configuration> mumi mailer? sender smtp)
1953 (list (shepherd-service
1955 (documentation "Mumi bug-tracking web interface.")
1956 (requirement '(networking))
1957 (start #~(make-forkexec-constructor
1958 `(#$(file-append mumi "/bin/mumi") "web"
1959 ,@(if #$mailer? '() '("--disable-mailer")))
1960 #:environment-variables #$environment
1961 #:user "mumi" #:group "mumi"
1962 #:log-file #$%mumi-log))
1963 (stop #~(make-kill-destructor)))
1965 (provision '(mumi-worker))
1966 (documentation "Mumi bug-tracking web interface database worker.")
1967 (requirement '(networking))
1968 (start #~(make-forkexec-constructor
1969 '(#$(file-append mumi "/bin/mumi") "worker")
1970 #:environment-variables #$environment
1971 #:user "mumi" #:group "mumi"
1972 #:log-file #$%mumi-worker-log))
1973 (stop #~(make-kill-destructor)))
1975 (provision '(mumi-mailer))
1976 (documentation "Mumi bug-tracking web interface mailer.")
1977 (requirement '(networking))
1978 (start #~(make-forkexec-constructor
1979 `(#$(file-append mumi "/bin/mumi") "mailer"
1981 (list (string-append "--sender=" #$sender))
1984 (list (string-append "--smtp=" #$smtp))
1986 #:environment-variables #$environment
1987 #:user "mumi" #:group "mumi"
1988 #:log-file #$%mumi-mailer-log))
1989 (stop #~(make-kill-destructor)))))))
1991 (define %mumi-log-rotations
1993 (files (list %mumi-log
1995 %mumi-worker-log)))))
1997 (define mumi-service-type
2001 (list (service-extension activation-service-type
2002 (const %mumi-activation))
2003 (service-extension account-service-type
2004 (const %mumi-accounts))
2005 (service-extension shepherd-root-service-type
2006 mumi-shepherd-services)
2007 (service-extension rottlog-service-type
2008 (const %mumi-log-rotations))))
2010 "Run Mumi, a Web interface to the Debbugs bug-tracking server.")
2012 (mumi-configuration))))
2014 (define %default-gmnisrv-config-file
2015 (plain-file "gmnisrv.ini" "
2016 listen=0.0.0.0:1965 [::]:1965
2019 store=/var/lib/gemini/certs
2021 organization=gmnisrv on Guix user
2027 (define-record-type* <gmnisrv-configuration>
2028 gmnisrv-configuration make-gmnisrv-configuration
2029 gmnisrv-configuration?
2030 (package gmnisrv-configuration-package
2032 (config-file gmnisrv-configuration-config-file
2033 (default %default-gmnisrv-config-file)))
2035 (define gmnisrv-shepherd-service
2037 (($ <gmnisrv-configuration> package config-file)
2038 (list (shepherd-service
2039 (provision '(gmnisrv))
2040 (requirement '(networking))
2041 (documentation "Run the gmnisrv Gemini server.")
2042 (start (let ((gmnisrv (file-append package "/bin/gmnisrv")))
2043 #~(make-forkexec-constructor
2044 (list #$gmnisrv "-C" #$config-file)
2045 #:user "gmnisrv" #:group "gmnisrv"
2046 #:log-file "/var/log/gmnisrv.log")))
2047 (stop #~(make-kill-destructor)))))))
2049 (define %gmnisrv-accounts
2050 (list (user-group (name "gmnisrv") (system? #t))
2055 (comment "gmnisrv Gemini server")
2056 (home-directory "/var/empty")
2057 (shell (file-append shadow "/sbin/nologin")))))
2059 (define %gmnisrv-activation
2060 (with-imported-modules '((guix build utils))
2062 (use-modules (guix build utils))
2064 (mkdir-p "/var/lib/gemini/certs")
2065 (let* ((pw (getpwnam "gmnisrv"))
2066 (uid (passwd:uid pw))
2067 (gid (passwd:gid pw)))
2068 (chown "/var/lib/gemini" uid gid)
2069 (chown "/var/lib/gemini/certs" uid gid)))))
2071 (define gmnisrv-service-type
2075 (list (service-extension activation-service-type
2076 (const %gmnisrv-activation))
2077 (service-extension account-service-type
2078 (const %gmnisrv-accounts))
2079 (service-extension shepherd-root-service-type
2080 gmnisrv-shepherd-service)))
2082 "Run the gmnisrv Gemini server.")
2084 (gmnisrv-configuration))))
2086 (define-record-type* <agate-configuration>
2087 agate-configuration make-agate-configuration
2088 agate-configuration?
2089 (package agate-configuration-package
2091 (content agate-configuration-content
2092 (default "/srv/gemini"))
2093 (cert agate-configuration-cert
2095 (key agate-configuration-key
2097 (addr agate-configuration-addr
2098 (default '("0.0.0.0:1965" "[::]:1965")))
2099 (hostname agate-configuration-hostname
2101 (lang agate-configuration-lang
2103 (silent? agate-configuration-silent
2105 (serve-secret? agate-configuration-serve-secret
2107 (log-ip? agate-configuration-log-ip
2109 (user agate-configuration-user
2111 (group agate-configuration-group
2113 (log-file agate-configuration-log
2114 (default "/var/log/agate.log")))
2116 (define agate-shepherd-service
2118 (($ <agate-configuration> package content cert key addr
2119 hostname lang silent? serve-secret?
2120 log-ip? user group log-file)
2121 (list (shepherd-service
2122 (provision '(agate))
2123 (requirement '(networking))
2124 (documentation "Run the agate Gemini server.")
2125 (start (let ((agate (file-append package "/bin/agate")))
2126 #~(make-forkexec-constructor
2128 "--content" #$content
2133 (list "--lang" lang)
2136 (list "--hostname" hostname)
2138 #$@(if silent? '("--silent") '())
2139 #$@(if serve-secret? '("--serve-secret") '())
2140 #$@(if log-ip? '("--log-ip") '()))
2141 #:user #$user #:group #$group
2142 #:log-file #$log-file)))
2143 (stop #~(make-kill-destructor)))))))
2145 (define agate-accounts
2147 (($ <agate-configuration> _ _ _ _ _
2150 `(,@(if (equal? group "agate")
2152 (list (user-group (name "agate") (system? #t))))
2159 (supplementary-groups '("agate"))
2161 (comment "agate server user")
2162 (home-directory "/var/empty")
2163 (shell (file-append shadow "/sbin/nologin")))))))
2165 (define agate-service-type
2169 (list (service-extension account-service-type
2171 (service-extension shepherd-root-service-type
2172 agate-shepherd-service)))
2173 (default-value (agate-configuration))
2174 (description "Run Agate, a simple Gemini protocol server written in