Commit | Line | Data |
---|---|---|
58724c48 DT |
1 | ;;; GNU Guix --- Functional package management for GNU |
2 | ;;; Copyright © 2015 David Thompson <davet@gnu.org> | |
dc72a7f7 | 3 | ;;; Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org> |
4a78fd46 | 4 | ;;; Copyright © 2016 Nils Gillmann <ng0@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> |
58724c48 DT |
10 | ;;; |
11 | ;;; This file is part of GNU Guix. | |
12 | ;;; | |
13 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | |
14 | ;;; under the terms of the GNU General Public License as published by | |
15 | ;;; the Free Software Foundation; either version 3 of the License, or (at | |
16 | ;;; your option) any later version. | |
17 | ;;; | |
18 | ;;; GNU Guix is distributed in the hope that it will be useful, but | |
19 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | ;;; GNU General Public License for more details. | |
22 | ;;; | |
23 | ;;; You should have received a copy of the GNU General Public License | |
24 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | |
25 | ||
26 | (define-module (gnu services web) | |
27 | #:use-module (gnu services) | |
0190c1c0 | 28 | #:use-module (gnu services shepherd) |
93b83eb3 | 29 | #:use-module (gnu system pam) |
58724c48 DT |
30 | #:use-module (gnu system shadow) |
31 | #:use-module (gnu packages admin) | |
32 | #:use-module (gnu packages web) | |
64bae723 | 33 | #:use-module (gnu packages php) |
93b83eb3 | 34 | #:use-module (gnu packages guile) |
58724c48 | 35 | #:use-module (guix records) |
93b83eb3 | 36 | #:use-module (guix modules) |
58724c48 | 37 | #:use-module (guix gexp) |
64bae723 | 38 | #:use-module ((guix utils) #:select (version-major)) |
39 | #:use-module ((guix packages) #:select (package-version)) | |
d338237d | 40 | #:use-module (srfi srfi-1) |
d067e4ba | 41 | #:use-module (srfi srfi-9) |
0adfe95a | 42 | #:use-module (ice-9 match) |
d067e4ba CB |
43 | #:export (<httpd-configuration> |
44 | httpd-configuration | |
45 | httpd-configuration? | |
46 | httpd-configuration-package | |
47 | httpd-configuration-pid-file | |
48 | httpd-configuration-config | |
49 | ||
50 | <httpd-virtualhost> | |
51 | httpd-virtualhost | |
52 | httpd-virtualhost? | |
53 | httpd-virtualhost-addresses-and-ports | |
54 | httpd-virtualhost-contents | |
55 | ||
56 | <httpd-config-file> | |
57 | httpd-config-file | |
58 | httpd-config-file? | |
59 | httpd-config-file-modules | |
60 | httpd-config-file-server-root | |
61 | httpd-config-file-server-name | |
62 | httpd-config-file-listen | |
63 | httpd-config-file-pid-file | |
64 | httpd-config-file-error-log | |
65 | httpd-config-file-user | |
66 | httpd-config-file-group | |
67 | ||
68 | httpd-service-type | |
69 | ||
70 | <nginx-configuration> | |
e4b729f8 | 71 | nginx-configuration |
24e96431 | 72 | nginx-configuration? |
e4b729f8 CB |
73 | nginx-configuartion-nginx |
74 | nginx-configuration-log-directory | |
75 | nginx-configuration-run-directory | |
76 | nginx-configuration-server-blocks | |
77 | nginx-configuration-upstream-blocks | |
2881f852 CB |
78 | nginx-configuration-server-names-hash-bucket-size |
79 | nginx-configuration-server-names-hash-bucket-max-size | |
25e071ea | 80 | nginx-configuration-extra-content |
e4b729f8 CB |
81 | nginx-configuration-file |
82 | ||
83 | <nginx-server-configuration> | |
3b9b12ef JL |
84 | nginx-server-configuration |
85 | nginx-server-configuration? | |
8b223cea | 86 | nginx-server-configuration-listen |
e4b729f8 CB |
87 | nginx-server-configuration-server-name |
88 | nginx-server-configuration-root | |
89 | nginx-server-configuration-locations | |
90 | nginx-server-configuration-index | |
91 | nginx-server-configuration-ssl-certificate | |
92 | nginx-server-configuration-ssl-certificate-key | |
93 | nginx-server-configuration-server-tokens? | |
b05e8ee1 | 94 | nginx-server-configuration-raw-content |
e4b729f8 CB |
95 | |
96 | <nginx-upstream-configuration> | |
cb341293 CB |
97 | nginx-upstream-configuration |
98 | nginx-upstream-configuration? | |
e4b729f8 CB |
99 | nginx-upstream-configuration-name |
100 | nginx-upstream-configuration-servers | |
101 | ||
102 | <nginx-location-configuration> | |
9c557a69 CB |
103 | nginx-location-configuration |
104 | nginx-location-configuration? | |
e4b729f8 CB |
105 | nginx-location-configuration-uri |
106 | nginx-location-configuration-body | |
107 | ||
108 | <nginx-named-location-configuration> | |
9c557a69 CB |
109 | nginx-named-location-configuration |
110 | nginx-named-location-configuration? | |
e4b729f8 CB |
111 | nginx-named-location-configuration-name |
112 | nginx-named-location-configuration-body | |
113 | ||
24e96431 | 114 | nginx-service |
a5130d10 AW |
115 | nginx-service-type |
116 | ||
117 | fcgiwrap-configuration | |
118 | fcgiwrap-configuration? | |
64bae723 | 119 | fcgiwrap-service-type |
120 | ||
121 | <php-fpm-configuration> | |
122 | php-fpm-configuration | |
123 | make-php-fpm-configuration | |
124 | php-fpm-configuration? | |
125 | php-fpm-configuration-php | |
126 | php-fpm-configuration-socket | |
127 | php-fpm-configuration-user | |
128 | php-fpm-configuration-group | |
129 | php-fpm-configuration-socket-user | |
130 | php-fpm-configuration-socket-group | |
131 | php-fpm-configuration-pid-file | |
132 | php-fpm-configuration-log-file | |
133 | php-fpm-configuration-process-manager | |
134 | php-fpm-configuration-display-errors | |
135 | php-fpm-configuration-workers-log-file | |
136 | php-fpm-configuration-file | |
137 | ||
138 | <php-fpm-dynamic-process-manager-configuration> | |
139 | php-fpm-dynamic-process-manager-configuration | |
140 | make-php-fpm-dynamic-process-manager-configuration | |
141 | php-fpm-dynamic-process-manager-configuration? | |
142 | php-fpm-dynamic-process-manager-configuration-max-children | |
143 | php-fpm-dynamic-process-manager-configuration-start-servers | |
144 | php-fpm-dynamic-process-manager-configuration-min-spare-servers | |
145 | php-fpm-dynamic-process-manager-configuration-max-spare-servers | |
146 | ||
147 | <php-fpm-static-process-manager-configuration> | |
148 | php-fpm-static-process-manager-configuration | |
149 | make-php-fpm-static-process-manager-configuration | |
150 | php-fpm-static-process-manager-configuration? | |
151 | php-fpm-static-process-manager-configuration-max-children | |
152 | ||
153 | <php-fpm-on-demand-process-manager-configuration> | |
154 | php-fpm-on-demand-process-manager-configuration | |
155 | make-php-fpm-on-demand-process-manager-configuration | |
156 | php-fpm-on-demand-process-manager-configuration? | |
157 | php-fpm-on-demand-process-manager-configuration-max-children | |
158 | php-fpm-on-demand-process-manager-configuration-process-idle-timeout | |
159 | ||
160 | php-fpm-service-type | |
08da664d JL |
161 | nginx-php-location |
162 | ||
93b83eb3 PAR |
163 | cat-avatar-generator-service |
164 | ||
165 | hpcguix-web-configuration | |
166 | hpcguix-web-configuration? | |
167 | hpcguix-web-service-type)) | |
58724c48 DT |
168 | |
169 | ;;; Commentary: | |
170 | ;;; | |
171 | ;;; Web services. | |
172 | ;;; | |
173 | ;;; Code: | |
174 | ||
d067e4ba CB |
175 | (define-record-type* <httpd-module> |
176 | httpd-module make-httpd-module | |
177 | httpd-module? | |
178 | (name httpd-load-module-name) | |
179 | (file httpd-load-module-file)) | |
180 | ||
181 | ;; Default modules for the httpd-service-type, taken from etc/httpd/httpd.conf | |
182 | ;; file in the httpd package. | |
183 | (define %default-httpd-modules | |
184 | (map (match-lambda | |
185 | ((name file) | |
186 | (httpd-module | |
187 | (name name) | |
188 | (file file)))) | |
189 | '(("authn_file_module" "modules/mod_authn_file.so") | |
190 | ("authn_core_module" "modules/mod_authn_core.so") | |
191 | ("authz_host_module" "modules/mod_authz_host.so") | |
192 | ("authz_groupfile_module" "modules/mod_authz_groupfile.so") | |
193 | ("authz_user_module" "modules/mod_authz_user.so") | |
194 | ("authz_core_module" "modules/mod_authz_core.so") | |
195 | ("access_compat_module" "modules/mod_access_compat.so") | |
196 | ("auth_basic_module" "modules/mod_auth_basic.so") | |
197 | ("reqtimeout_module" "modules/mod_reqtimeout.so") | |
198 | ("filter_module" "modules/mod_filter.so") | |
199 | ("mime_module" "modules/mod_mime.so") | |
200 | ("log_config_module" "modules/mod_log_config.so") | |
201 | ("env_module" "modules/mod_env.so") | |
202 | ("headers_module" "modules/mod_headers.so") | |
203 | ("setenvif_module" "modules/mod_setenvif.so") | |
204 | ("version_module" "modules/mod_version.so") | |
205 | ("unixd_module" "modules/mod_unixd.so") | |
206 | ("status_module" "modules/mod_status.so") | |
207 | ("autoindex_module" "modules/mod_autoindex.so") | |
208 | ("dir_module" "modules/mod_dir.so") | |
209 | ("alias_module" "modules/mod_alias.so")))) | |
210 | ||
211 | (define-record-type* <httpd-config-file> | |
212 | httpd-config-file make-httpd-config-file | |
213 | httpd-config-file? | |
214 | (modules httpd-config-file-modules | |
215 | (default %default-httpd-modules)) | |
216 | (server-root httpd-config-file-server-root | |
217 | (default httpd)) | |
218 | (server-name httpd-config-file-server-name | |
219 | (default #f)) | |
220 | (document-root httpd-config-file-document-root | |
221 | (default "/srv/http")) | |
222 | (listen httpd-config-file-listen | |
223 | (default '("80"))) | |
224 | (pid-file httpd-config-file-pid-file | |
225 | (default "/var/run/httpd")) | |
226 | (error-log httpd-config-file-error-log | |
227 | (default "/var/log/httpd/error_log")) | |
228 | (user httpd-config-file-user | |
229 | (default "httpd")) | |
230 | (group httpd-config-file-group | |
231 | (default "httpd")) | |
232 | (extra-config httpd-config-file-extra-config | |
233 | (default | |
234 | (list "TypesConfig etc/httpd/mime.types")))) | |
235 | ||
236 | (define-gexp-compiler (httpd-config-file-compiler | |
237 | (file <httpd-config-file>) system target) | |
238 | (match file | |
239 | (($ <httpd-config-file> load-modules server-root server-name | |
240 | document-root listen pid-file error-log | |
241 | user group extra-config) | |
242 | (gexp->derivation | |
243 | "httpd.conf" | |
244 | #~(call-with-output-file (ungexp output "out") | |
245 | (lambda (port) | |
246 | (display | |
247 | (string-append | |
248 | (ungexp-splicing | |
249 | `(,@(append-map | |
250 | (match-lambda | |
251 | (($ <httpd-module> name module) | |
252 | `("LoadModule " ,name " " ,module "\n"))) | |
253 | load-modules) | |
254 | ,@`("ServerRoot " ,server-root "\n") | |
255 | ,@(if server-name | |
256 | `("ServerName " ,server-name "\n") | |
257 | '()) | |
258 | ,@`("DocumentRoot " ,document-root "\n") | |
259 | ,@(append-map | |
260 | (lambda (listen-value) | |
261 | `("Listen " ,listen-value "\n")) | |
262 | listen) | |
263 | ,@(if pid-file | |
264 | `("Pidfile " ,pid-file "\n") | |
265 | '()) | |
266 | ,@(if error-log | |
267 | `("ErrorLog " ,error-log "\n") | |
268 | '()) | |
269 | ,@(if user | |
270 | `("User " ,user "\n") | |
271 | '()) | |
272 | ,@(if group | |
273 | `("Group " ,group "\n") | |
274 | '()) | |
275 | "\n\n" | |
276 | ,@extra-config))) | |
277 | port))) | |
278 | #:local-build? #t)))) | |
279 | ||
280 | (define-record-type <httpd-virtualhost> | |
281 | (httpd-virtualhost addresses-and-ports contents) | |
282 | httpd-virtualhost? | |
283 | (addresses-and-ports httpd-virtualhost-addresses-and-ports) | |
284 | (contents httpd-virtualhost-contents)) | |
285 | ||
286 | (define-record-type* <httpd-configuration> | |
287 | httpd-configuration make-httpd-configuration | |
288 | httpd-configuration? | |
289 | (package httpd-configuration-package | |
290 | (default httpd)) | |
291 | (pid-file httpd-configuration-pid-file | |
292 | (default "/var/run/httpd")) | |
293 | (config httpd-configuration-config | |
294 | (default (httpd-config-file)))) | |
295 | ||
296 | (define %httpd-accounts | |
297 | (list (user-group (name "httpd") (system? #t)) | |
298 | (user-account | |
299 | (name "httpd") | |
300 | (group "httpd") | |
301 | (system? #t) | |
302 | (comment "Apache HTTPD server user") | |
303 | (home-directory "/var/empty") | |
304 | (shell (file-append shadow "/sbin/nologin"))))) | |
305 | ||
306 | (define httpd-shepherd-services | |
307 | (match-lambda | |
308 | (($ <httpd-configuration> package pid-file config) | |
309 | (list (shepherd-service | |
310 | (provision '(httpd)) | |
311 | (documentation "The Apache HTTP Server") | |
312 | (requirement '(networking)) | |
313 | (start #~(make-forkexec-constructor | |
314 | `(#$(file-append package "/bin/httpd") | |
315 | #$@(if config | |
316 | (list "-f" config) | |
317 | '())) | |
318 | #:pid-file #$pid-file)) | |
319 | (stop #~(make-kill-destructor))))))) | |
320 | ||
321 | (define httpd-activation | |
322 | (match-lambda | |
323 | (($ <httpd-configuration> package pid-file config) | |
324 | (match-record | |
325 | config | |
326 | <httpd-config-file> | |
327 | (error-log document-root) | |
328 | #~(begin | |
329 | (use-modules (guix build utils)) | |
330 | ||
331 | (mkdir-p #$(dirname error-log)) | |
332 | (mkdir-p #$document-root)))))) | |
333 | ||
334 | (define (httpd-process-extensions original-config extension-configs) | |
335 | (let ((config (httpd-configuration-config | |
336 | original-config))) | |
337 | (if (httpd-config-file? config) | |
338 | (httpd-configuration | |
339 | (inherit original-config) | |
340 | (config | |
341 | (httpd-config-file | |
342 | (inherit config) | |
343 | (extra-config | |
344 | (append (httpd-config-file-extra-config config) | |
345 | (append-map | |
346 | (match-lambda | |
347 | (($ <httpd-virtualhost> | |
348 | addresses-and-ports | |
349 | contents) | |
350 | `(,(string-append | |
351 | "<VirtualHost " addresses-and-ports ">\n") | |
352 | ,@contents | |
353 | "\n</VirtualHost>\n")) | |
354 | ((? string? x) | |
355 | `("\n" ,x "\n")) | |
356 | ((? list? x) | |
357 | `("\n" ,@x "\n"))) | |
358 | extension-configs))))))))) | |
359 | ||
360 | (define httpd-service-type | |
361 | (service-type (name 'httpd) | |
362 | (extensions | |
363 | (list (service-extension shepherd-root-service-type | |
364 | httpd-shepherd-services) | |
365 | (service-extension activation-service-type | |
366 | httpd-activation) | |
367 | (service-extension account-service-type | |
368 | (const %httpd-accounts)))) | |
369 | (compose concatenate) | |
370 | (extend httpd-process-extensions) | |
371 | (default-value | |
372 | (httpd-configuration)))) | |
373 | ||
3b9b12ef JL |
374 | (define-record-type* <nginx-server-configuration> |
375 | nginx-server-configuration make-nginx-server-configuration | |
376 | nginx-server-configuration? | |
8b223cea CL |
377 | (listen nginx-server-configuration-listen |
378 | (default '("80" "443 ssl"))) | |
3b9b12ef | 379 | (server-name nginx-server-configuration-server-name |
8c00b838 | 380 | (default (list 'default))) |
3b9b12ef | 381 | (root nginx-server-configuration-root |
8c00b838 | 382 | (default "/srv/http")) |
9c557a69 CB |
383 | (locations nginx-server-configuration-locations |
384 | (default '())) | |
3b9b12ef | 385 | (index nginx-server-configuration-index |
8c00b838 | 386 | (default (list "index.html"))) |
4d14808a OP |
387 | (try-files nginx-server-configuration-try-files |
388 | (default '())) | |
3b9b12ef | 389 | (ssl-certificate nginx-server-configuration-ssl-certificate |
c48aa70a | 390 | (default #f)) |
3b9b12ef | 391 | (ssl-certificate-key nginx-server-configuration-ssl-certificate-key |
c48aa70a | 392 | (default #f)) |
3b9b12ef | 393 | (server-tokens? nginx-server-configuration-server-tokens? |
b05e8ee1 CL |
394 | (default #f)) |
395 | (raw-content nginx-server-configuration-raw-content | |
396 | (default '()))) | |
8c00b838 | 397 | |
cb341293 CB |
398 | (define-record-type* <nginx-upstream-configuration> |
399 | nginx-upstream-configuration make-nginx-upstream-configuration | |
400 | nginx-upstream-configuration? | |
401 | (name nginx-upstream-configuration-name) | |
402 | (servers nginx-upstream-configuration-servers)) | |
403 | ||
9c557a69 CB |
404 | (define-record-type* <nginx-location-configuration> |
405 | nginx-location-configuration make-nginx-location-configuration | |
406 | nginx-location-configuration? | |
407 | (uri nginx-location-configuration-uri | |
408 | (default #f)) | |
409 | (body nginx-location-configuration-body)) | |
410 | ||
411 | (define-record-type* <nginx-named-location-configuration> | |
412 | nginx-named-location-configuration make-nginx-named-location-configuration | |
413 | nginx-named-location-configuration? | |
414 | (name nginx-named-location-configuration-name | |
415 | (default #f)) | |
416 | (body nginx-named-location-configuration-body)) | |
417 | ||
0adfe95a LC |
418 | (define-record-type* <nginx-configuration> |
419 | nginx-configuration make-nginx-configuration | |
420 | nginx-configuration? | |
dc72a7f7 LC |
421 | (nginx nginx-configuration-nginx ;<package> |
422 | (default nginx)) | |
423 | (log-directory nginx-configuration-log-directory ;string | |
424 | (default "/var/log/nginx")) | |
425 | (run-directory nginx-configuration-run-directory ;string | |
426 | (default "/var/run/nginx")) | |
427 | (server-blocks nginx-configuration-server-blocks | |
428 | (default '())) ;list of <nginx-server-configuration> | |
429 | (upstream-blocks nginx-configuration-upstream-blocks | |
430 | (default '())) ;list of <nginx-upstream-configuration> | |
2881f852 CB |
431 | (server-names-hash-bucket-size nginx-configuration-server-names-hash-bucket-size |
432 | (default #f)) | |
433 | (server-names-hash-bucket-max-size nginx-configuration-server-names-hash-bucket-max-size | |
434 | (default #f)) | |
25e071ea CB |
435 | (extra-content nginx-configuration-extra-content |
436 | (default "")) | |
dc72a7f7 LC |
437 | (file nginx-configuration-file ;#f | string | file-like |
438 | (default #f))) | |
0adfe95a | 439 | |
8c00b838 JL |
440 | (define (config-domain-strings names) |
441 | "Return a string denoting the nginx config representation of NAMES, a list | |
442 | of domain names." | |
c9aa261b | 443 | (map (match-lambda |
4e9ae301 | 444 | ('default "_ ") |
c9aa261b AW |
445 | ((? string? str) (list str " "))) |
446 | names)) | |
8c00b838 JL |
447 | |
448 | (define (config-index-strings names) | |
449 | "Return a string denoting the nginx config representation of NAMES, a list | |
450 | of index files." | |
c9aa261b AW |
451 | (map (match-lambda |
452 | ((? string? str) (list str " "))) | |
453 | names)) | |
8c00b838 | 454 | |
c9aa261b | 455 | (define emit-nginx-location-config |
9c557a69 CB |
456 | (match-lambda |
457 | (($ <nginx-location-configuration> uri body) | |
c9aa261b | 458 | (list |
9c557a69 | 459 | " location " uri " {\n" |
c9aa261b | 460 | (map (lambda (x) (list " " x "\n")) body) |
9c557a69 CB |
461 | " }\n")) |
462 | (($ <nginx-named-location-configuration> name body) | |
c9aa261b | 463 | (list |
9c557a69 | 464 | " location @" name " {\n" |
c9aa261b | 465 | (map (lambda (x) (list " " x "\n")) body) |
9c557a69 CB |
466 | " }\n")))) |
467 | ||
c9aa261b | 468 | (define (emit-nginx-server-config server) |
8b223cea | 469 | (let ((listen (nginx-server-configuration-listen server)) |
c9aa261b AW |
470 | (server-name (nginx-server-configuration-server-name server)) |
471 | (ssl-certificate (nginx-server-configuration-ssl-certificate server)) | |
472 | (ssl-certificate-key | |
473 | (nginx-server-configuration-ssl-certificate-key server)) | |
474 | (root (nginx-server-configuration-root server)) | |
475 | (index (nginx-server-configuration-index server)) | |
4d14808a | 476 | (try-files (nginx-server-configuration-try-files server)) |
c9aa261b | 477 | (server-tokens? (nginx-server-configuration-server-tokens? server)) |
b05e8ee1 CL |
478 | (locations (nginx-server-configuration-locations server)) |
479 | (raw-content (nginx-server-configuration-raw-content server))) | |
c9aa261b AW |
480 | (define-syntax-parameter <> (syntax-rules ())) |
481 | (define-syntax-rule (and/l x tail ...) | |
482 | (let ((x* x)) | |
483 | (if x* | |
484 | (syntax-parameterize ((<> (identifier-syntax x*))) | |
485 | (list tail ...)) | |
486 | '()))) | |
487 | (list | |
488 | " server {\n" | |
8b223cea | 489 | (map (lambda (directive) (list " listen " directive ";\n")) listen) |
c9aa261b AW |
490 | " server_name " (config-domain-strings server-name) ";\n" |
491 | (and/l ssl-certificate " ssl_certificate " <> ";\n") | |
492 | (and/l ssl-certificate-key " ssl_certificate_key " <> ";\n") | |
493 | " root " root ";\n" | |
494 | " index " (config-index-strings index) ";\n" | |
4d14808a OP |
495 | (if (not (nil? try-files)) |
496 | (and/l (config-index-strings try-files) " try_files " <> ";\n") | |
497 | "") | |
c9aa261b AW |
498 | " server_tokens " (if server-tokens? "on" "off") ";\n" |
499 | "\n" | |
500 | (map emit-nginx-location-config locations) | |
501 | "\n" | |
b05e8ee1 | 502 | (map (lambda (x) (list " " x "\n")) raw-content) |
c9aa261b | 503 | " }\n"))) |
cb341293 | 504 | |
c9aa261b AW |
505 | (define (emit-nginx-upstream-config upstream) |
506 | (list | |
cb341293 | 507 | " upstream " (nginx-upstream-configuration-name upstream) " {\n" |
c9aa261b AW |
508 | (map (lambda (server) |
509 | (simple-format #f " server ~A;\n" server)) | |
510 | (nginx-upstream-configuration-servers upstream)) | |
8c00b838 JL |
511 | " }\n")) |
512 | ||
c9aa261b AW |
513 | (define (flatten . lst) |
514 | "Return a list that recursively concatenates all sub-lists of LST." | |
515 | (define (flatten1 head out) | |
516 | (if (list? head) | |
517 | (fold-right flatten1 out head) | |
518 | (cons head out))) | |
519 | (fold-right flatten1 '() lst)) | |
520 | ||
472368a8 CB |
521 | (define (default-nginx-config config) |
522 | (match-record config | |
523 | <nginx-configuration> | |
524 | (nginx log-directory run-directory | |
525 | server-blocks upstream-blocks | |
526 | server-names-hash-bucket-size | |
25e071ea CB |
527 | server-names-hash-bucket-max-size |
528 | extra-content) | |
472368a8 CB |
529 | (apply mixed-text-file "nginx.conf" |
530 | (flatten | |
531 | "user nginx nginx;\n" | |
532 | "pid " run-directory "/pid;\n" | |
533 | "error_log " log-directory "/error.log info;\n" | |
534 | "http {\n" | |
535 | " client_body_temp_path " run-directory "/client_body_temp;\n" | |
536 | " proxy_temp_path " run-directory "/proxy_temp;\n" | |
537 | " fastcgi_temp_path " run-directory "/fastcgi_temp;\n" | |
538 | " uwsgi_temp_path " run-directory "/uwsgi_temp;\n" | |
539 | " scgi_temp_path " run-directory "/scgi_temp;\n" | |
540 | " access_log " log-directory "/access.log;\n" | |
541 | " include " nginx "/share/nginx/conf/mime.types;\n" | |
542 | (if server-names-hash-bucket-size | |
543 | (string-append | |
544 | " server_names_hash_bucket_size " | |
545 | (number->string server-names-hash-bucket-size) | |
546 | ";\n") | |
547 | "") | |
548 | (if server-names-hash-bucket-max-size | |
549 | (string-append | |
550 | " server_names_hash_bucket_max_size " | |
551 | (number->string server-names-hash-bucket-max-size) | |
552 | ";\n") | |
553 | "") | |
554 | "\n" | |
555 | (map emit-nginx-upstream-config upstream-blocks) | |
556 | (map emit-nginx-server-config server-blocks) | |
25e071ea CB |
557 | extra-content |
558 | "\n}\n" | |
472368a8 | 559 | "events {}\n")))) |
58724c48 | 560 | |
0adfe95a LC |
561 | (define %nginx-accounts |
562 | (list (user-group (name "nginx") (system? #t)) | |
563 | (user-account | |
564 | (name "nginx") | |
565 | (group "nginx") | |
566 | (system? #t) | |
567 | (comment "nginx server user") | |
568 | (home-directory "/var/empty") | |
9e41130b | 569 | (shell (file-append shadow "/sbin/nologin"))))) |
0adfe95a | 570 | |
472368a8 CB |
571 | (define (nginx-activation config) |
572 | (match-record config | |
573 | <nginx-configuration> | |
574 | (nginx log-directory run-directory file) | |
575 | #~(begin | |
576 | (use-modules (guix build utils)) | |
0adfe95a | 577 | |
472368a8 CB |
578 | (format #t "creating nginx log directory '~a'~%" #$log-directory) |
579 | (mkdir-p #$log-directory) | |
580 | (format #t "creating nginx run directory '~a'~%" #$run-directory) | |
581 | (mkdir-p #$run-directory) | |
582 | (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory) | |
583 | (mkdir-p (string-append #$run-directory "/client_body_temp")) | |
584 | (mkdir-p (string-append #$run-directory "/proxy_temp")) | |
585 | (mkdir-p (string-append #$run-directory "/fastcgi_temp")) | |
586 | (mkdir-p (string-append #$run-directory "/uwsgi_temp")) | |
587 | (mkdir-p (string-append #$run-directory "/scgi_temp")) | |
588 | ;; Start-up logs. Once configuration is loaded, nginx switches to | |
589 | ;; log-directory. | |
590 | (mkdir-p (string-append #$run-directory "/logs")) | |
591 | ;; Check configuration file syntax. | |
592 | (system* (string-append #$nginx "/sbin/nginx") | |
593 | "-c" #$(or file | |
594 | (default-nginx-config config)) | |
595 | "-t")))) | |
0adfe95a | 596 | |
472368a8 CB |
597 | (define (nginx-shepherd-service config) |
598 | (match-record config | |
599 | <nginx-configuration> | |
600 | (nginx file run-directory) | |
601 | (let* ((nginx-binary (file-append nginx "/sbin/nginx")) | |
602 | (nginx-action | |
603 | (lambda args | |
604 | #~(lambda _ | |
4ae0607d CL |
605 | (invoke #$nginx-binary "-c" |
606 | #$(or file | |
607 | (default-nginx-config config)) | |
608 | #$@args))))) | |
0adfe95a | 609 | |
472368a8 CB |
610 | ;; TODO: Add 'reload' action. |
611 | (list (shepherd-service | |
612 | (provision '(nginx)) | |
613 | (documentation "Run the nginx daemon.") | |
614 | (requirement '(user-processes loopback)) | |
615 | (start (nginx-action "-p" run-directory)) | |
616 | (stop (nginx-action "-s" "stop"))))))) | |
0adfe95a LC |
617 | |
618 | (define nginx-service-type | |
619 | (service-type (name 'nginx) | |
620 | (extensions | |
d4053c71 AK |
621 | (list (service-extension shepherd-root-service-type |
622 | nginx-shepherd-service) | |
0adfe95a LC |
623 | (service-extension activation-service-type |
624 | nginx-activation) | |
625 | (service-extension account-service-type | |
d338237d JL |
626 | (const %nginx-accounts)))) |
627 | (compose concatenate) | |
628 | (extend (lambda (config servers) | |
629 | (nginx-configuration | |
630 | (inherit config) | |
631 | (server-blocks | |
632 | (append (nginx-configuration-server-blocks config) | |
ad4cc435 CB |
633 | servers))))) |
634 | (default-value | |
635 | (nginx-configuration)))) | |
0adfe95a | 636 | |
a5130d10 AW |
637 | (define-record-type* <fcgiwrap-configuration> fcgiwrap-configuration |
638 | make-fcgiwrap-configuration | |
639 | fcgiwrap-configuration? | |
640 | (package fcgiwrap-configuration-package ;<package> | |
641 | (default fcgiwrap)) | |
642 | (socket fcgiwrap-configuration-socket | |
643 | (default "tcp:127.0.0.1:9000")) | |
644 | (user fcgiwrap-configuration-user | |
645 | (default "fcgiwrap")) | |
646 | (group fcgiwrap-configuration-group | |
647 | (default "fcgiwrap"))) | |
648 | ||
649 | (define fcgiwrap-accounts | |
650 | (match-lambda | |
651 | (($ <fcgiwrap-configuration> package socket user group) | |
652 | (filter identity | |
653 | (list | |
654 | (and (equal? group "fcgiwrap") | |
655 | (user-group | |
656 | (name "fcgiwrap") | |
657 | (system? #t))) | |
658 | (and (equal? user "fcgiwrap") | |
659 | (user-account | |
660 | (name "fcgiwrap") | |
661 | (group group) | |
662 | (system? #t) | |
663 | (comment "Fcgiwrap Daemon") | |
664 | (home-directory "/var/empty") | |
665 | (shell (file-append shadow "/sbin/nologin"))))))))) | |
666 | ||
667 | (define fcgiwrap-shepherd-service | |
668 | (match-lambda | |
669 | (($ <fcgiwrap-configuration> package socket user group) | |
670 | (list (shepherd-service | |
671 | (provision '(fcgiwrap)) | |
672 | (documentation "Run the fcgiwrap daemon.") | |
673 | (requirement '(networking)) | |
674 | (start #~(make-forkexec-constructor | |
675 | '(#$(file-append package "/sbin/fcgiwrap") | |
676 | "-s" #$socket) | |
677 | #:user #$user #:group #$group)) | |
678 | (stop #~(make-kill-destructor))))))) | |
679 | ||
680 | (define fcgiwrap-service-type | |
681 | (service-type (name 'fcgiwrap) | |
682 | (extensions | |
683 | (list (service-extension shepherd-root-service-type | |
684 | fcgiwrap-shepherd-service) | |
685 | (service-extension account-service-type | |
686 | fcgiwrap-accounts))) | |
687 | (default-value (fcgiwrap-configuration)))) | |
64bae723 | 688 | |
689 | (define-record-type* <php-fpm-configuration> php-fpm-configuration | |
690 | make-php-fpm-configuration | |
691 | php-fpm-configuration? | |
692 | (php php-fpm-configuration-php ;<package> | |
693 | (default php)) | |
694 | (socket php-fpm-configuration-socket | |
695 | (default (string-append "/var/run/php" | |
696 | (version-major (package-version php)) | |
697 | "-fpm.sock"))) | |
698 | (user php-fpm-configuration-user | |
699 | (default "php-fpm")) | |
700 | (group php-fpm-configuration-group | |
701 | (default "php-fpm")) | |
702 | (socket-user php-fpm-configuration-socket-user | |
703 | (default "php-fpm")) | |
704 | (socket-group php-fpm-configuration-socket-group | |
705 | (default "nginx")) | |
706 | (pid-file php-fpm-configuration-pid-file | |
707 | (default (string-append "/var/run/php" | |
708 | (version-major (package-version php)) | |
709 | "-fpm.pid"))) | |
710 | (log-file php-fpm-configuration-log-file | |
711 | (default (string-append "/var/log/php" | |
712 | (version-major (package-version php)) | |
713 | "-fpm.log"))) | |
714 | (process-manager php-fpm-configuration-process-manager | |
715 | (default (php-fpm-dynamic-process-manager-configuration))) | |
716 | (display-errors php-fpm-configuration-display-errors | |
717 | (default #f)) | |
718 | (workers-log-file php-fpm-configuration-workers-log-file | |
719 | (default (string-append "/var/log/php" | |
720 | (version-major (package-version php)) | |
721 | "-fpm.www.log"))) | |
722 | (file php-fpm-configuration-file ;#f | file-like | |
723 | (default #f))) | |
724 | ||
725 | (define-record-type* <php-fpm-dynamic-process-manager-configuration> | |
726 | php-fpm-dynamic-process-manager-configuration | |
727 | make-php-fpm-dynamic-process-manager-configuration | |
728 | php-fpm-dynamic-process-manager-configuration? | |
729 | (max-children php-fpm-dynamic-process-manager-configuration-max-children | |
730 | (default 5)) | |
731 | (start-servers php-fpm-dynamic-process-manager-configuration-start-servers | |
732 | (default 2)) | |
733 | (min-spare-servers php-fpm-dynamic-process-manager-configuration-min-spare-servers | |
734 | (default 1)) | |
735 | (max-spare-servers php-fpm-dynamic-process-manager-configuration-max-spare-servers | |
736 | (default 3))) | |
737 | ||
738 | (define-record-type* <php-fpm-static-process-manager-configuration> | |
739 | php-fpm-static-process-manager-configuration | |
740 | make-php-fpm-static-process-manager-configuration | |
741 | php-fpm-static-process-manager-configuration? | |
742 | (max-children php-fpm-static-process-manager-configuration-max-children | |
743 | (default 5))) | |
744 | ||
745 | (define-record-type* <php-fpm-on-demand-process-manager-configuration> | |
746 | php-fpm-on-demand-process-manager-configuration | |
747 | make-php-fpm-on-demand-process-manager-configuration | |
748 | php-fpm-on-demand-process-manager-configuration? | |
749 | (max-children php-fpm-on-demand-process-manager-configuration-max-children | |
750 | (default 5)) | |
751 | (process-idle-timeout php-fpm-on-demand-process-manager-configuration-process-idle-timeout | |
752 | (default 10))) | |
753 | ||
754 | (define php-fpm-accounts | |
755 | (match-lambda | |
756 | (($ <php-fpm-configuration> php socket user group socket-user socket-group _ _ _ _ _ _) | |
757 | (list | |
758 | (user-group (name "php-fpm") (system? #t)) | |
759 | (user-group | |
760 | (name group) | |
761 | (system? #t)) | |
762 | (user-account | |
763 | (name user) | |
764 | (group group) | |
765 | (supplementary-groups '("php-fpm")) | |
766 | (system? #t) | |
767 | (comment "php-fpm daemon user") | |
768 | (home-directory "/var/empty") | |
769 | (shell (file-append shadow "/sbin/nologin"))))))) | |
770 | ||
771 | (define (default-php-fpm-config socket user group socket-user socket-group | |
772 | pid-file log-file pm display-errors workers-log-file) | |
773 | (apply mixed-text-file "php-fpm.conf" | |
774 | (flatten | |
775 | "[global]\n" | |
776 | "pid =" pid-file "\n" | |
777 | "error_log =" log-file "\n" | |
778 | "[www]\n" | |
779 | "user =" user "\n" | |
780 | "group =" group "\n" | |
781 | "listen =" socket "\n" | |
782 | "listen.owner =" socket-user "\n" | |
783 | "listen.group =" socket-group "\n" | |
784 | ||
785 | (match pm | |
786 | (($ <php-fpm-dynamic-process-manager-configuration> | |
787 | pm.max-children | |
788 | pm.start-servers | |
789 | pm.min-spare-servers | |
790 | pm.max-spare-servers) | |
791 | (list | |
792 | "pm = dynamic\n" | |
793 | "pm.max_children =" (number->string pm.max-children) "\n" | |
794 | "pm.start_servers =" (number->string pm.start-servers) "\n" | |
795 | "pm.min_spare_servers =" (number->string pm.min-spare-servers) "\n" | |
796 | "pm.max_spare_servers =" (number->string pm.max-spare-servers) "\n")) | |
797 | ||
798 | (($ <php-fpm-static-process-manager-configuration> | |
799 | pm.max-children) | |
800 | (list | |
801 | "pm = static\n" | |
802 | "pm.max_children =" (number->string pm.max-children) "\n")) | |
803 | ||
804 | (($ <php-fpm-on-demand-process-manager-configuration> | |
805 | pm.max-children | |
806 | pm.process-idle-timeout) | |
807 | (list | |
808 | "pm = ondemand\n" | |
809 | "pm.max_children =" (number->string pm.max-children) "\n" | |
810 | "pm.process_idle_timeout =" (number->string pm.process-idle-timeout) "s\n"))) | |
811 | ||
812 | ||
813 | "php_flag[display_errors] = " (if display-errors "on" "off") "\n" | |
814 | ||
815 | (if workers-log-file | |
816 | (list "catch_workers_output = yes\n" | |
817 | "php_admin_value[error_log] =" workers-log-file "\n" | |
818 | "php_admin_flag[log_errors] = on\n") | |
819 | (list "catch_workers_output = no\n"))))) | |
820 | ||
821 | (define php-fpm-shepherd-service | |
822 | (match-lambda | |
823 | (($ <php-fpm-configuration> php socket user group socket-user socket-group | |
824 | pid-file log-file pm display-errors workers-log-file file) | |
825 | (list (shepherd-service | |
826 | (provision '(php-fpm)) | |
827 | (documentation "Run the php-fpm daemon.") | |
828 | (requirement '(networking)) | |
829 | (start #~(make-forkexec-constructor | |
830 | '(#$(file-append php "/sbin/php-fpm") | |
831 | "--fpm-config" | |
832 | #$(or file | |
833 | (default-php-fpm-config socket user group | |
834 | socket-user socket-group pid-file log-file | |
835 | pm display-errors workers-log-file))) | |
836 | #:pid-file #$pid-file)) | |
837 | (stop #~(make-kill-destructor))))))) | |
838 | ||
839 | (define php-fpm-activation | |
840 | (match-lambda | |
841 | (($ <php-fpm-configuration> _ _ user _ _ _ _ log-file _ _ workers-log-file _) | |
842 | #~(begin | |
843 | (use-modules (guix build utils)) | |
844 | (let* ((user (getpwnam #$user)) | |
845 | (touch (lambda (file-name) | |
846 | (call-with-output-file file-name (const #t)))) | |
847 | (init-log-file | |
848 | (lambda (file-name) | |
849 | (when #$workers-log-file | |
850 | (when (not (file-exists? file-name)) | |
851 | (touch file-name)) | |
852 | (chown file-name (passwd:uid user) (passwd:gid user)) | |
853 | (chmod file-name #o660))))) | |
854 | (init-log-file #$log-file) | |
855 | (init-log-file #$workers-log-file)))))) | |
856 | ||
857 | ||
858 | (define php-fpm-service-type | |
859 | (service-type | |
860 | (name 'php-fpm) | |
861 | (description | |
862 | "Run @command{php-fpm} to provide a fastcgi socket for calling php through | |
863 | a webserver.") | |
864 | (extensions | |
865 | (list (service-extension shepherd-root-service-type | |
866 | php-fpm-shepherd-service) | |
867 | (service-extension activation-service-type | |
868 | php-fpm-activation) | |
869 | (service-extension account-service-type | |
870 | php-fpm-accounts))) | |
871 | (default-value (php-fpm-configuration)))) | |
872 | ||
873 | (define* (nginx-php-location | |
874 | #:key | |
875 | (nginx-package nginx) | |
876 | (socket (string-append "/var/run/php" | |
877 | (version-major (package-version php)) | |
878 | "-fpm.sock"))) | |
879 | "Return a nginx-location-configuration that makes nginx run .php files." | |
880 | (nginx-location-configuration | |
881 | (uri "~ \\.php$") | |
882 | (body (list | |
883 | "fastcgi_split_path_info ^(.+\\.php)(/.+)$;" | |
884 | (string-append "fastcgi_pass unix:" socket ";") | |
885 | "fastcgi_index index.php;" | |
886 | (list "include " nginx-package "/share/nginx/conf/fastcgi.conf;"))))) | |
08da664d JL |
887 | |
888 | (define* (cat-avatar-generator-service | |
889 | #:key | |
890 | (cache-dir "/var/cache/cat-avatar-generator") | |
891 | (package cat-avatar-generator) | |
892 | (configuration (nginx-server-configuration))) | |
893 | (simple-service | |
894 | 'cat-http-server nginx-service-type | |
895 | (list (nginx-server-configuration | |
896 | (inherit configuration) | |
897 | (locations | |
898 | (cons | |
899 | (let ((base (nginx-php-location))) | |
900 | (nginx-location-configuration | |
901 | (inherit base) | |
902 | (body (list (string-append "fastcgi_param CACHE_DIR \"" | |
903 | cache-dir "\";") | |
904 | (nginx-location-configuration-body base))))) | |
905 | (nginx-server-configuration-locations configuration))) | |
906 | (root #~(string-append #$package | |
907 | "/share/web/cat-avatar-generator")))))) | |
93b83eb3 PAR |
908 | |
909 | \f | |
910 | (define-record-type* <hpcguix-web-configuration> | |
911 | hpcguix-web-configuration make-hpcguix-web-configuration | |
912 | hpcguix-web-configuration? | |
913 | ||
914 | (package hpcguix-web-package (default hpcguix-web)) ;<package> | |
915 | ||
916 | ;; Specs is gexp of hpcguix-web configuration file | |
917 | (specs hpcguix-web-configuration-specs)) | |
918 | ||
919 | (define %hpcguix-web-accounts | |
920 | (list (user-group | |
921 | (name "hpcguix-web") | |
922 | (system? #t)) | |
923 | (user-account | |
924 | (name "hpcguix-web") | |
925 | (group "hpcguix-web") | |
926 | (system? #t) | |
927 | (comment "hpcguix-web") | |
928 | (home-directory "/var/empty") | |
929 | (shell (file-append shadow "/sbin/nologin"))))) | |
930 | ||
931 | (define %hpcguix-web-activation | |
932 | #~(begin | |
933 | (use-modules (guix build utils)) | |
934 | (let ((home-dir "/var/cache/guix/web") | |
935 | (user (getpwnam "hpcguix-web"))) | |
936 | (mkdir-p home-dir) | |
937 | (chown home-dir (passwd:uid user) (passwd:gid user)) | |
938 | (chmod home-dir #o755)))) | |
939 | ||
940 | (define (hpcguix-web-shepherd-service config) | |
941 | (let ((specs (hpcguix-web-configuration-specs config)) | |
942 | (hpcguix-web (hpcguix-web-package config))) | |
943 | (with-imported-modules (source-module-closure | |
944 | '((gnu build shepherd))) | |
945 | (shepherd-service | |
946 | (documentation "hpcguix-web daemon") | |
947 | (provision '(hpcguix-web)) | |
948 | (requirement '(networking)) | |
949 | (start #~(make-forkexec-constructor | |
950 | (list #$(file-append hpcguix-web "/bin/run") | |
951 | (string-append "--config=" | |
952 | #$(scheme-file "hpcguix-web.scm" specs))) | |
953 | #:user "hpcguix-web" | |
954 | #:group "hpcguix-web" | |
955 | #:environment-variables | |
956 | (list "XDG_CACHE_HOME=/var/cache"))) | |
957 | (stop #~(make-kill-destructor)))))) | |
958 | ||
959 | (define hpcguix-web-service-type | |
960 | (service-type | |
961 | (name 'hpcguix-web) | |
962 | (description "Run the hpcguix-web server.") | |
963 | (extensions | |
964 | (list (service-extension account-service-type | |
965 | (const %hpcguix-web-accounts)) | |
966 | (service-extension activation-service-type | |
967 | (const %hpcguix-web-activation)) | |
968 | (service-extension shepherd-root-service-type | |
969 | (compose list hpcguix-web-shepherd-service)))))) |