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> |
8c00b838 | 5 | ;;; Copyright © 2016 Julien Lepiller <julien@lepiller.eu> |
cb341293 | 6 | ;;; Copyright © 2017 Christopher Baines <mail@cbaines.net> |
58724c48 DT |
7 | ;;; |
8 | ;;; This file is part of GNU Guix. | |
9 | ;;; | |
10 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | |
11 | ;;; under the terms of the GNU General Public License as published by | |
12 | ;;; the Free Software Foundation; either version 3 of the License, or (at | |
13 | ;;; your option) any later version. | |
14 | ;;; | |
15 | ;;; GNU Guix is distributed in the hope that it will be useful, but | |
16 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | ;;; GNU General Public License for more details. | |
19 | ;;; | |
20 | ;;; You should have received a copy of the GNU General Public License | |
21 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | |
22 | ||
23 | (define-module (gnu services web) | |
24 | #:use-module (gnu services) | |
0190c1c0 | 25 | #:use-module (gnu services shepherd) |
58724c48 DT |
26 | #:use-module (gnu system shadow) |
27 | #:use-module (gnu packages admin) | |
28 | #:use-module (gnu packages web) | |
29 | #:use-module (guix records) | |
58724c48 | 30 | #:use-module (guix gexp) |
d338237d | 31 | #:use-module (srfi srfi-1) |
0adfe95a | 32 | #:use-module (ice-9 match) |
24e96431 TČ |
33 | #:export (nginx-configuration |
34 | nginx-configuration? | |
3b9b12ef JL |
35 | nginx-server-configuration |
36 | nginx-server-configuration? | |
cb341293 CB |
37 | nginx-upstream-configuration |
38 | nginx-upstream-configuration? | |
9c557a69 CB |
39 | nginx-location-configuration |
40 | nginx-location-configuration? | |
41 | nginx-named-location-configuration | |
42 | nginx-named-location-configuration? | |
24e96431 TČ |
43 | nginx-service |
44 | nginx-service-type)) | |
58724c48 DT |
45 | |
46 | ;;; Commentary: | |
47 | ;;; | |
48 | ;;; Web services. | |
49 | ;;; | |
50 | ;;; Code: | |
51 | ||
3b9b12ef JL |
52 | (define-record-type* <nginx-server-configuration> |
53 | nginx-server-configuration make-nginx-server-configuration | |
54 | nginx-server-configuration? | |
55 | (http-port nginx-server-configuration-http-port | |
8c00b838 | 56 | (default 80)) |
3b9b12ef | 57 | (https-port nginx-server-configuration-https-port |
8c00b838 | 58 | (default 443)) |
3b9b12ef | 59 | (server-name nginx-server-configuration-server-name |
8c00b838 | 60 | (default (list 'default))) |
3b9b12ef | 61 | (root nginx-server-configuration-root |
8c00b838 | 62 | (default "/srv/http")) |
9c557a69 CB |
63 | (locations nginx-server-configuration-locations |
64 | (default '())) | |
3b9b12ef | 65 | (index nginx-server-configuration-index |
8c00b838 | 66 | (default (list "index.html"))) |
3b9b12ef | 67 | (ssl-certificate nginx-server-configuration-ssl-certificate |
8c00b838 | 68 | (default "/etc/nginx/cert.pem")) |
3b9b12ef | 69 | (ssl-certificate-key nginx-server-configuration-ssl-certificate-key |
8c00b838 | 70 | (default "/etc/nginx/key.pem")) |
3b9b12ef | 71 | (server-tokens? nginx-server-configuration-server-tokens? |
8c00b838 JL |
72 | (default #f))) |
73 | ||
cb341293 CB |
74 | (define-record-type* <nginx-upstream-configuration> |
75 | nginx-upstream-configuration make-nginx-upstream-configuration | |
76 | nginx-upstream-configuration? | |
77 | (name nginx-upstream-configuration-name) | |
78 | (servers nginx-upstream-configuration-servers)) | |
79 | ||
9c557a69 CB |
80 | (define-record-type* <nginx-location-configuration> |
81 | nginx-location-configuration make-nginx-location-configuration | |
82 | nginx-location-configuration? | |
83 | (uri nginx-location-configuration-uri | |
84 | (default #f)) | |
85 | (body nginx-location-configuration-body)) | |
86 | ||
87 | (define-record-type* <nginx-named-location-configuration> | |
88 | nginx-named-location-configuration make-nginx-named-location-configuration | |
89 | nginx-named-location-configuration? | |
90 | (name nginx-named-location-configuration-name | |
91 | (default #f)) | |
92 | (body nginx-named-location-configuration-body)) | |
93 | ||
0adfe95a LC |
94 | (define-record-type* <nginx-configuration> |
95 | nginx-configuration make-nginx-configuration | |
96 | nginx-configuration? | |
dc72a7f7 LC |
97 | (nginx nginx-configuration-nginx ;<package> |
98 | (default nginx)) | |
99 | (log-directory nginx-configuration-log-directory ;string | |
100 | (default "/var/log/nginx")) | |
101 | (run-directory nginx-configuration-run-directory ;string | |
102 | (default "/var/run/nginx")) | |
103 | (server-blocks nginx-configuration-server-blocks | |
104 | (default '())) ;list of <nginx-server-configuration> | |
105 | (upstream-blocks nginx-configuration-upstream-blocks | |
106 | (default '())) ;list of <nginx-upstream-configuration> | |
107 | (file nginx-configuration-file ;#f | string | file-like | |
108 | (default #f))) | |
0adfe95a | 109 | |
8c00b838 JL |
110 | (define (config-domain-strings names) |
111 | "Return a string denoting the nginx config representation of NAMES, a list | |
112 | of domain names." | |
819c1945 | 113 | (string-join |
8c00b838 | 114 | (map (match-lambda |
4e9ae301 JL |
115 | ('default "_ ") |
116 | ((? string? str) (string-append str " "))) | |
8c00b838 JL |
117 | names))) |
118 | ||
119 | (define (config-index-strings names) | |
120 | "Return a string denoting the nginx config representation of NAMES, a list | |
121 | of index files." | |
819c1945 | 122 | (string-join |
8c00b838 | 123 | (map (match-lambda |
4e9ae301 | 124 | ((? string? str) (string-append str " "))) |
8c00b838 JL |
125 | names))) |
126 | ||
9c557a69 CB |
127 | (define nginx-location-config |
128 | (match-lambda | |
129 | (($ <nginx-location-configuration> uri body) | |
130 | (string-append | |
131 | " location " uri " {\n" | |
132 | " " (string-join body "\n ") "\n" | |
133 | " }\n")) | |
134 | (($ <nginx-named-location-configuration> name body) | |
135 | (string-append | |
136 | " location @" name " {\n" | |
137 | " " (string-join body "\n ") "\n" | |
138 | " }\n")))) | |
139 | ||
3b9b12ef | 140 | (define (default-nginx-server-config server) |
8c00b838 JL |
141 | (string-append |
142 | " server {\n" | |
3b9b12ef | 143 | (if (nginx-server-configuration-http-port server) |
8c00b838 | 144 | (string-append " listen " |
3b9b12ef | 145 | (number->string (nginx-server-configuration-http-port server)) |
8c00b838 JL |
146 | ";\n") |
147 | "") | |
3b9b12ef | 148 | (if (nginx-server-configuration-https-port server) |
8c00b838 | 149 | (string-append " listen " |
3b9b12ef | 150 | (number->string (nginx-server-configuration-https-port server)) |
8c00b838 JL |
151 | " ssl;\n") |
152 | "") | |
153 | " server_name " (config-domain-strings | |
3b9b12ef | 154 | (nginx-server-configuration-server-name server)) |
8c00b838 | 155 | ";\n" |
3b9b12ef | 156 | (if (nginx-server-configuration-ssl-certificate server) |
8c00b838 | 157 | (string-append " ssl_certificate " |
3b9b12ef | 158 | (nginx-server-configuration-ssl-certificate server) ";\n") |
8c00b838 | 159 | "") |
3b9b12ef | 160 | (if (nginx-server-configuration-ssl-certificate-key server) |
8c00b838 | 161 | (string-append " ssl_certificate_key " |
3b9b12ef | 162 | (nginx-server-configuration-ssl-certificate-key server) ";\n") |
8c00b838 | 163 | "") |
3b9b12ef JL |
164 | " root " (nginx-server-configuration-root server) ";\n" |
165 | " index " (config-index-strings (nginx-server-configuration-index server)) ";\n" | |
166 | " server_tokens " (if (nginx-server-configuration-server-tokens? server) | |
8c00b838 | 167 | "on" "off") ";\n" |
9c557a69 CB |
168 | "\n" |
169 | (string-join | |
170 | (map nginx-location-config (nginx-server-configuration-locations server)) | |
171 | "\n") | |
172 | " }\n")) | |
cb341293 CB |
173 | |
174 | (define (nginx-upstream-config upstream) | |
175 | (string-append | |
176 | " upstream " (nginx-upstream-configuration-name upstream) " {\n" | |
177 | (string-concatenate | |
178 | (map (lambda (server) | |
179 | (simple-format #f " server ~A;\n" server)) | |
180 | (nginx-upstream-configuration-servers upstream))) | |
8c00b838 JL |
181 | " }\n")) |
182 | ||
cb341293 CB |
183 | (define (default-nginx-config log-directory run-directory server-list upstream-list) |
184 | (mixed-text-file "nginx.conf" | |
58724c48 DT |
185 | "user nginx nginx;\n" |
186 | "pid " run-directory "/pid;\n" | |
187 | "error_log " log-directory "/error.log info;\n" | |
188 | "http {\n" | |
8c00b838 JL |
189 | " client_body_temp_path " run-directory "/client_body_temp;\n" |
190 | " proxy_temp_path " run-directory "/proxy_temp;\n" | |
191 | " fastcgi_temp_path " run-directory "/fastcgi_temp;\n" | |
192 | " uwsgi_temp_path " run-directory "/uwsgi_temp;\n" | |
193 | " scgi_temp_path " run-directory "/scgi_temp;\n" | |
58724c48 | 194 | " access_log " log-directory "/access.log;\n" |
cb341293 CB |
195 | "\n" |
196 | (string-join | |
197 | (filter (lambda (section) (not (null? section))) | |
198 | (map nginx-upstream-config upstream-list)) | |
199 | "\n") | |
200 | "\n" | |
3b9b12ef | 201 | (let ((http (map default-nginx-server-config server-list))) |
8c00b838 JL |
202 | (do ((http http (cdr http)) |
203 | (block "" (string-append (car http) "\n" block ))) | |
204 | ((null? http) block))) | |
58724c48 | 205 | "}\n" |
cb341293 | 206 | "events {}\n")) |
58724c48 | 207 | |
0adfe95a LC |
208 | (define %nginx-accounts |
209 | (list (user-group (name "nginx") (system? #t)) | |
210 | (user-account | |
211 | (name "nginx") | |
212 | (group "nginx") | |
213 | (system? #t) | |
214 | (comment "nginx server user") | |
215 | (home-directory "/var/empty") | |
9e41130b | 216 | (shell (file-append shadow "/sbin/nologin"))))) |
0adfe95a LC |
217 | |
218 | (define nginx-activation | |
219 | (match-lambda | |
d338237d | 220 | (($ <nginx-configuration> nginx log-directory run-directory server-blocks |
cb341293 | 221 | upstream-blocks config-file) |
0adfe95a LC |
222 | #~(begin |
223 | (use-modules (guix build utils)) | |
224 | ||
225 | (format #t "creating nginx log directory '~a'~%" #$log-directory) | |
226 | (mkdir-p #$log-directory) | |
227 | (format #t "creating nginx run directory '~a'~%" #$run-directory) | |
228 | (mkdir-p #$run-directory) | |
8c00b838 JL |
229 | (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory) |
230 | (mkdir-p (string-append #$run-directory "/client_body_temp")) | |
231 | (mkdir-p (string-append #$run-directory "/proxy_temp")) | |
232 | (mkdir-p (string-append #$run-directory "/fastcgi_temp")) | |
233 | (mkdir-p (string-append #$run-directory "/uwsgi_temp")) | |
234 | (mkdir-p (string-append #$run-directory "/scgi_temp")) | |
0adfe95a | 235 | ;; Check configuration file syntax. |
d21047d5 | 236 | (system* (string-append #$nginx "/sbin/nginx") |
d338237d JL |
237 | "-c" #$(or config-file |
238 | (default-nginx-config log-directory | |
cb341293 | 239 | run-directory server-blocks upstream-blocks)) |
d338237d | 240 | "-t"))))) |
0adfe95a | 241 | |
d4053c71 | 242 | (define nginx-shepherd-service |
0adfe95a | 243 | (match-lambda |
d338237d | 244 | (($ <nginx-configuration> nginx log-directory run-directory server-blocks |
cb341293 | 245 | upstream-blocks config-file) |
9e41130b | 246 | (let* ((nginx-binary (file-append nginx "/sbin/nginx")) |
0adfe95a LC |
247 | (nginx-action |
248 | (lambda args | |
249 | #~(lambda _ | |
250 | (zero? | |
d338237d JL |
251 | (system* #$nginx-binary "-c" |
252 | #$(or config-file | |
253 | (default-nginx-config log-directory | |
cb341293 | 254 | run-directory server-blocks upstream-blocks)) |
d338237d | 255 | #$@args)))))) |
0adfe95a LC |
256 | |
257 | ;; TODO: Add 'reload' action. | |
d4053c71 | 258 | (list (shepherd-service |
0adfe95a LC |
259 | (provision '(nginx)) |
260 | (documentation "Run the nginx daemon.") | |
261 | (requirement '(user-processes loopback)) | |
262 | (start (nginx-action "-p" run-directory)) | |
263 | (stop (nginx-action "-s" "stop")))))))) | |
264 | ||
265 | (define nginx-service-type | |
266 | (service-type (name 'nginx) | |
267 | (extensions | |
d4053c71 AK |
268 | (list (service-extension shepherd-root-service-type |
269 | nginx-shepherd-service) | |
0adfe95a LC |
270 | (service-extension activation-service-type |
271 | nginx-activation) | |
272 | (service-extension account-service-type | |
d338237d JL |
273 | (const %nginx-accounts)))) |
274 | (compose concatenate) | |
275 | (extend (lambda (config servers) | |
276 | (nginx-configuration | |
277 | (inherit config) | |
278 | (server-blocks | |
279 | (append (nginx-configuration-server-blocks config) | |
280 | servers))))))) | |
0adfe95a | 281 | |
58724c48 DT |
282 | (define* (nginx-service #:key (nginx nginx) |
283 | (log-directory "/var/log/nginx") | |
284 | (run-directory "/var/run/nginx") | |
d338237d | 285 | (server-list '()) |
cb341293 | 286 | (upstream-list '()) |
d338237d | 287 | (config-file #f)) |
58724c48 DT |
288 | "Return a service that runs NGINX, the nginx web server. |
289 | ||
6c12abbd | 290 | The nginx daemon loads its runtime configuration from CONFIG-FILE, stores log |
58724c48 | 291 | files in LOG-DIRECTORY, and stores temporary runtime files in RUN-DIRECTORY." |
0adfe95a LC |
292 | (service nginx-service-type |
293 | (nginx-configuration | |
294 | (nginx nginx) | |
295 | (log-directory log-directory) | |
296 | (run-directory run-directory) | |
d338237d | 297 | (server-blocks server-list) |
cb341293 | 298 | (upstream-blocks upstream-list) |
0adfe95a | 299 | (file config-file)))) |