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