gnu: datamash: Update to 1.1.1.
[jackhill/guix/guix.git] / gnu / services / web.scm
index bc0aa62..11408d7 100644 (file)
@@ -1,6 +1,9 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 David Thompson <davet@gnu.org>
-;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 ng0 <ng0@we.make.ritual.n0.is>
+;;; Copyright © 2016 Julien Lepiller <julien@lepiller.eu>
+;;; Copyright © 2017 Christopher Baines <mail@cbaines.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
   #:use-module (gnu packages web)
   #:use-module (guix records)
   #:use-module (guix gexp)
+  #:use-module (srfi srfi-1)
   #:use-module (ice-9 match)
-  #:export (nginx-service))
+  #:export (nginx-configuration
+            nginx-configuration?
+            nginx-server-configuration
+            nginx-server-configuration?
+            nginx-upstream-configuration
+            nginx-upstream-configuration?
+            nginx-location-configuration
+            nginx-location-configuration?
+            nginx-named-location-configuration
+            nginx-named-location-configuration?
+            nginx-service
+            nginx-service-type))
 
 ;;; Commentary:
 ;;;
 ;;;
 ;;; Code:
 
+(define-record-type* <nginx-server-configuration>
+  nginx-server-configuration make-nginx-server-configuration
+  nginx-server-configuration?
+  (http-port           nginx-server-configuration-http-port
+                       (default 80))
+  (https-port          nginx-server-configuration-https-port
+                       (default 443))
+  (server-name         nginx-server-configuration-server-name
+                       (default (list 'default)))
+  (root                nginx-server-configuration-root
+                       (default "/srv/http"))
+  (locations           nginx-server-configuration-locations
+                       (default '()))
+  (index               nginx-server-configuration-index
+                       (default (list "index.html")))
+  (ssl-certificate     nginx-server-configuration-ssl-certificate
+                       (default "/etc/nginx/cert.pem"))
+  (ssl-certificate-key nginx-server-configuration-ssl-certificate-key
+                       (default "/etc/nginx/key.pem"))
+  (server-tokens?      nginx-server-configuration-server-tokens?
+                       (default #f)))
+
+(define-record-type* <nginx-upstream-configuration>
+  nginx-upstream-configuration make-nginx-upstream-configuration
+  nginx-upstream-configuration?
+  (name                nginx-upstream-configuration-name)
+  (servers             nginx-upstream-configuration-servers))
+
+(define-record-type* <nginx-location-configuration>
+  nginx-location-configuration make-nginx-location-configuration
+  nginx-location-configuration?
+  (uri                 nginx-location-configuration-uri
+                       (default #f))
+  (body                nginx-location-configuration-body))
+
+(define-record-type* <nginx-named-location-configuration>
+  nginx-named-location-configuration make-nginx-named-location-configuration
+  nginx-named-location-configuration?
+  (name                nginx-named-location-configuration-name
+                       (default #f))
+  (body                nginx-named-location-configuration-body))
+
 (define-record-type* <nginx-configuration>
   nginx-configuration make-nginx-configuration
   nginx-configuration?
-  (nginx         nginx-configuration-nginx)         ;<package>
-  (log-directory nginx-configuration-log-directory) ;string
-  (run-directory nginx-configuration-run-directory) ;string
-  (file          nginx-configuration-file))         ;string | file-like
-
-(define (default-nginx-config log-directory run-directory)
-  (plain-file "nginx.conf"
-              (string-append
+  (nginx         nginx-configuration-nginx          ;<package>
+                 (default nginx))
+  (log-directory nginx-configuration-log-directory  ;string
+                 (default "/var/log/nginx"))
+  (run-directory nginx-configuration-run-directory  ;string
+                 (default "/var/run/nginx"))
+  (server-blocks nginx-configuration-server-blocks
+                 (default '()))          ;list of <nginx-server-configuration>
+  (upstream-blocks nginx-configuration-upstream-blocks
+                   (default '()))      ;list of <nginx-upstream-configuration>
+  (file          nginx-configuration-file         ;#f | string | file-like
+                 (default #f)))
+
+(define (config-domain-strings names)
+ "Return a string denoting the nginx config representation of NAMES, a list
+of domain names."
+ (string-join
+  (map (match-lambda
+        ('default "_ ")
+        ((? string? str) (string-append str " ")))
+       names)))
+
+(define (config-index-strings names)
+ "Return a string denoting the nginx config representation of NAMES, a list
+of index files."
+ (string-join
+  (map (match-lambda
+        ((? string? str) (string-append str " ")))
+       names)))
+
+(define nginx-location-config
+  (match-lambda
+    (($ <nginx-location-configuration> uri body)
+     (string-append
+      "      location " uri " {\n"
+      "        " (string-join body "\n    ") "\n"
+      "      }\n"))
+    (($ <nginx-named-location-configuration> name body)
+     (string-append
+      "      location @" name " {\n"
+      "        " (string-join body "\n    ") "\n"
+      "      }\n"))))
+
+(define (default-nginx-server-config server)
+  (string-append
+   "    server {\n"
+   (if (nginx-server-configuration-http-port server)
+       (string-append "      listen "
+                      (number->string (nginx-server-configuration-http-port server))
+                      ";\n")
+       "")
+   (if (nginx-server-configuration-https-port server)
+       (string-append "      listen "
+                      (number->string (nginx-server-configuration-https-port server))
+                      " ssl;\n")
+       "")
+   "      server_name " (config-domain-strings
+                         (nginx-server-configuration-server-name server))
+                        ";\n"
+   (if (nginx-server-configuration-ssl-certificate server)
+       (string-append "      ssl_certificate "
+                      (nginx-server-configuration-ssl-certificate server) ";\n")
+       "")
+   (if (nginx-server-configuration-ssl-certificate-key server)
+       (string-append "      ssl_certificate_key "
+                      (nginx-server-configuration-ssl-certificate-key server) ";\n")
+       "")
+   "      root " (nginx-server-configuration-root server) ";\n"
+   "      index " (config-index-strings (nginx-server-configuration-index server)) ";\n"
+   "      server_tokens " (if (nginx-server-configuration-server-tokens? server)
+                              "on" "off") ";\n"
+   "\n"
+   (string-join
+    (map nginx-location-config (nginx-server-configuration-locations server))
+    "\n")
+   "    }\n"))
+
+(define (nginx-upstream-config upstream)
+  (string-append
+   "    upstream " (nginx-upstream-configuration-name upstream) " {\n"
+   (string-concatenate
+    (map (lambda (server)
+           (simple-format #f "      server ~A;\n" server))
+         (nginx-upstream-configuration-servers upstream)))
+   "    }\n"))
+
+(define (default-nginx-config log-directory run-directory server-list upstream-list)
+  (mixed-text-file "nginx.conf"
                "user nginx nginx;\n"
                "pid " run-directory "/pid;\n"
                "error_log " log-directory "/error.log info;\n"
                "http {\n"
+               "    client_body_temp_path " run-directory "/client_body_temp;\n"
+               "    proxy_temp_path " run-directory "/proxy_temp;\n"
+               "    fastcgi_temp_path " run-directory "/fastcgi_temp;\n"
+               "    uwsgi_temp_path " run-directory "/uwsgi_temp;\n"
+               "    scgi_temp_path " run-directory "/scgi_temp;\n"
                "    access_log " log-directory "/access.log;\n"
-               "    root /var/www;\n"
-               "    server {}\n"
+               "\n"
+               (string-join
+                (filter (lambda (section) (not (null? section)))
+                        (map nginx-upstream-config upstream-list))
+                "\n")
+               "\n"
+               (let ((http (map default-nginx-server-config server-list)))
+                 (do ((http http (cdr http))
+                      (block "" (string-append (car http) "\n" block )))
+                     ((null? http) block)))
                "}\n"
-               "events {}\n")))
+               "events {}\n"))
 
 (define %nginx-accounts
   (list (user-group (name "nginx") (system? #t))
          (system? #t)
          (comment "nginx server user")
          (home-directory "/var/empty")
-         (shell #~(string-append #$shadow "/sbin/nologin")))))
+         (shell (file-append shadow "/sbin/nologin")))))
 
 (define nginx-activation
   (match-lambda
-    (($ <nginx-configuration> nginx log-directory run-directory config-file)
+    (($ <nginx-configuration> nginx log-directory run-directory server-blocks
+                              upstream-blocks config-file)
      #~(begin
          (use-modules (guix build utils))
 
          (mkdir-p #$log-directory)
          (format #t "creating nginx run directory '~a'~%" #$run-directory)
          (mkdir-p #$run-directory)
+         (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory)
+         (mkdir-p (string-append #$run-directory "/client_body_temp"))
+         (mkdir-p (string-append #$run-directory "/proxy_temp"))
+         (mkdir-p (string-append #$run-directory "/fastcgi_temp"))
+         (mkdir-p (string-append #$run-directory "/uwsgi_temp"))
+         (mkdir-p (string-append #$run-directory "/scgi_temp"))
          ;; Check configuration file syntax.
-         (system* (string-append #$nginx "/bin/nginx")
-                  "-c" #$config-file "-t")))))
+         (system* (string-append #$nginx "/sbin/nginx")
+                  "-c" #$(or config-file
+                             (default-nginx-config log-directory
+                               run-directory server-blocks upstream-blocks))
+                  "-t")))))
 
-(define nginx-dmd-service
+(define nginx-shepherd-service
   (match-lambda
-    (($ <nginx-configuration> nginx log-directory run-directory config-file)
-     (let* ((nginx-binary #~(string-append #$nginx "/sbin/nginx"))
+    (($ <nginx-configuration> nginx log-directory run-directory server-blocks
+                              upstream-blocks config-file)
+     (let* ((nginx-binary (file-append nginx "/sbin/nginx"))
             (nginx-action
              (lambda args
                #~(lambda _
                    (zero?
-                    (system* #$nginx-binary "-c" #$config-file #$@args))))))
+                    (system* #$nginx-binary "-c"
+                             #$(or config-file
+                                   (default-nginx-config log-directory
+                                     run-directory server-blocks upstream-blocks))
+                             #$@args))))))
 
        ;; TODO: Add 'reload' action.
-       (list (dmd-service
+       (list (shepherd-service
               (provision '(nginx))
               (documentation "Run the nginx daemon.")
               (requirement '(user-processes loopback))
 (define nginx-service-type
   (service-type (name 'nginx)
                 (extensions
-                 (list (service-extension dmd-root-service-type
-                                          nginx-dmd-service)
+                 (list (service-extension shepherd-root-service-type
+                                          nginx-shepherd-service)
                        (service-extension activation-service-type
                                           nginx-activation)
                        (service-extension account-service-type
-                                          (const %nginx-accounts))))))
+                                          (const %nginx-accounts))))
+                (compose concatenate)
+                (extend (lambda (config servers)
+                          (nginx-configuration
+                            (inherit config)
+                            (server-blocks
+                              (append (nginx-configuration-server-blocks config)
+                              servers)))))))
 
 (define* (nginx-service #:key (nginx nginx)
                         (log-directory "/var/log/nginx")
                         (run-directory "/var/run/nginx")
-                        (config-file
-                         (default-nginx-config log-directory run-directory)))
+                        (server-list '())
+                        (upstream-list '())
+                        (config-file #f))
   "Return a service that runs NGINX, the nginx web server.
 
-The nginx daemon loads its runtime configuration from CONFIG-FIGLE, stores log
+The nginx daemon loads its runtime configuration from CONFIG-FILE, stores log
 files in LOG-DIRECTORY, and stores temporary runtime files in RUN-DIRECTORY."
   (service nginx-service-type
            (nginx-configuration
             (nginx nginx)
             (log-directory log-directory)
             (run-directory run-directory)
+            (server-blocks server-list)
+            (upstream-blocks upstream-list)
             (file config-file))))