web.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2015 David Thompson <davet@gnu.org>
  3. ;;; Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
  4. ;;; Copyright © 2016 ng0 <ng0@we.make.ritual.n0.is>
  5. ;;; Copyright © 2016, 2017 Julien Lepiller <julien@lepiller.eu>
  6. ;;; Copyright © 2017 Christopher Baines <mail@cbaines.net>
  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. (define-module (gnu services web)
  23. #:use-module (gnu services)
  24. #:use-module (gnu services shepherd)
  25. #:use-module (gnu system shadow)
  26. #:use-module (gnu packages admin)
  27. #:use-module (gnu packages web)
  28. #:use-module (guix records)
  29. #:use-module (guix gexp)
  30. #:use-module (srfi srfi-1)
  31. #:use-module (ice-9 match)
  32. #:export (<nginx-configuration>
  33. nginx-configuration
  34. nginx-configuration?
  35. nginx-configuartion-nginx
  36. nginx-configuration-log-directory
  37. nginx-configuration-run-directory
  38. nginx-configuration-server-blocks
  39. nginx-configuration-upstream-blocks
  40. nginx-configuration-file
  41. <nginx-server-configuration>
  42. nginx-server-configuration
  43. nginx-server-configuration?
  44. nginx-server-configuration-http-port
  45. nginx-server-configuartion-https-port
  46. nginx-server-configuration-server-name
  47. nginx-server-configuration-root
  48. nginx-server-configuration-locations
  49. nginx-server-configuration-index
  50. nginx-server-configuration-ssl-certificate
  51. nginx-server-configuration-ssl-certificate-key
  52. nginx-server-configuration-server-tokens?
  53. <nginx-upstream-configuration>
  54. nginx-upstream-configuration
  55. nginx-upstream-configuration?
  56. nginx-upstream-configuration-name
  57. nginx-upstream-configuration-servers
  58. <nginx-location-configuration>
  59. nginx-location-configuration
  60. nginx-location-configuration?
  61. nginx-location-configuration-uri
  62. nginx-location-configuration-body
  63. <nginx-named-location-configuration>
  64. nginx-named-location-configuration
  65. nginx-named-location-configuration?
  66. nginx-named-location-configuration-name
  67. nginx-named-location-configuration-body
  68. nginx-service
  69. nginx-service-type
  70. fcgiwrap-configuration
  71. fcgiwrap-configuration?
  72. fcgiwrap-service-type))
  73. ;;; Commentary:
  74. ;;;
  75. ;;; Web services.
  76. ;;;
  77. ;;; Code:
  78. (define-record-type* <nginx-server-configuration>
  79. nginx-server-configuration make-nginx-server-configuration
  80. nginx-server-configuration?
  81. (http-port nginx-server-configuration-http-port
  82. (default 80))
  83. (https-port nginx-server-configuration-https-port
  84. (default 443))
  85. (server-name nginx-server-configuration-server-name
  86. (default (list 'default)))
  87. (root nginx-server-configuration-root
  88. (default "/srv/http"))
  89. (locations nginx-server-configuration-locations
  90. (default '()))
  91. (index nginx-server-configuration-index
  92. (default (list "index.html")))
  93. (try-files nginx-server-configuration-try-files
  94. (default '()))
  95. (ssl-certificate nginx-server-configuration-ssl-certificate
  96. (default "/etc/nginx/cert.pem"))
  97. (ssl-certificate-key nginx-server-configuration-ssl-certificate-key
  98. (default "/etc/nginx/key.pem"))
  99. (server-tokens? nginx-server-configuration-server-tokens?
  100. (default #f)))
  101. (define-record-type* <nginx-upstream-configuration>
  102. nginx-upstream-configuration make-nginx-upstream-configuration
  103. nginx-upstream-configuration?
  104. (name nginx-upstream-configuration-name)
  105. (servers nginx-upstream-configuration-servers))
  106. (define-record-type* <nginx-location-configuration>
  107. nginx-location-configuration make-nginx-location-configuration
  108. nginx-location-configuration?
  109. (uri nginx-location-configuration-uri
  110. (default #f))
  111. (body nginx-location-configuration-body))
  112. (define-record-type* <nginx-named-location-configuration>
  113. nginx-named-location-configuration make-nginx-named-location-configuration
  114. nginx-named-location-configuration?
  115. (name nginx-named-location-configuration-name
  116. (default #f))
  117. (body nginx-named-location-configuration-body))
  118. (define-record-type* <nginx-configuration>
  119. nginx-configuration make-nginx-configuration
  120. nginx-configuration?
  121. (nginx nginx-configuration-nginx ;<package>
  122. (default nginx))
  123. (log-directory nginx-configuration-log-directory ;string
  124. (default "/var/log/nginx"))
  125. (run-directory nginx-configuration-run-directory ;string
  126. (default "/var/run/nginx"))
  127. (server-blocks nginx-configuration-server-blocks
  128. (default '())) ;list of <nginx-server-configuration>
  129. (upstream-blocks nginx-configuration-upstream-blocks
  130. (default '())) ;list of <nginx-upstream-configuration>
  131. (file nginx-configuration-file ;#f | string | file-like
  132. (default #f)))
  133. (define (config-domain-strings names)
  134. "Return a string denoting the nginx config representation of NAMES, a list
  135. of domain names."
  136. (map (match-lambda
  137. ('default "_ ")
  138. ((? string? str) (list str " ")))
  139. names))
  140. (define (config-index-strings names)
  141. "Return a string denoting the nginx config representation of NAMES, a list
  142. of index files."
  143. (map (match-lambda
  144. ((? string? str) (list str " ")))
  145. names))
  146. (define emit-nginx-location-config
  147. (match-lambda
  148. (($ <nginx-location-configuration> uri body)
  149. (list
  150. " location " uri " {\n"
  151. (map (lambda (x) (list " " x "\n")) body)
  152. " }\n"))
  153. (($ <nginx-named-location-configuration> name body)
  154. (list
  155. " location @" name " {\n"
  156. (map (lambda (x) (list " " x "\n")) body)
  157. " }\n"))))
  158. (define (emit-nginx-server-config server)
  159. (let ((http-port (nginx-server-configuration-http-port server))
  160. (https-port (nginx-server-configuration-https-port server))
  161. (server-name (nginx-server-configuration-server-name server))
  162. (ssl-certificate (nginx-server-configuration-ssl-certificate server))
  163. (ssl-certificate-key
  164. (nginx-server-configuration-ssl-certificate-key server))
  165. (root (nginx-server-configuration-root server))
  166. (index (nginx-server-configuration-index server))
  167. (try-files (nginx-server-configuration-try-files server))
  168. (server-tokens? (nginx-server-configuration-server-tokens? server))
  169. (locations (nginx-server-configuration-locations server)))
  170. (define-syntax-parameter <> (syntax-rules ()))
  171. (define-syntax-rule (and/l x tail ...)
  172. (let ((x* x))
  173. (if x*
  174. (syntax-parameterize ((<> (identifier-syntax x*)))
  175. (list tail ...))
  176. '())))
  177. (for-each
  178. (match-lambda
  179. ((record-key . file)
  180. (if (and file (not (file-exists? file)))
  181. (error
  182. (simple-format
  183. #f
  184. "~A in the nginx configuration for the server with name \"~A\" does not exist" record-key server-name)))))
  185. `(("ssl-certificate" . ,ssl-certificate)
  186. ("ssl-certificate-key" . ,ssl-certificate-key)))
  187. (list
  188. " server {\n"
  189. (and/l http-port " listen " (number->string <>) ";\n")
  190. (and/l https-port " listen " (number->string <>) " ssl;\n")
  191. " server_name " (config-domain-strings server-name) ";\n"
  192. (and/l ssl-certificate " ssl_certificate " <> ";\n")
  193. (and/l ssl-certificate-key " ssl_certificate_key " <> ";\n")
  194. " root " root ";\n"
  195. " index " (config-index-strings index) ";\n"
  196. (if (not (nil? try-files))
  197. (and/l (config-index-strings try-files) " try_files " <> ";\n")
  198. "")
  199. " server_tokens " (if server-tokens? "on" "off") ";\n"
  200. "\n"
  201. (map emit-nginx-location-config locations)
  202. "\n"
  203. " }\n")))
  204. (define (emit-nginx-upstream-config upstream)
  205. (list
  206. " upstream " (nginx-upstream-configuration-name upstream) " {\n"
  207. (map (lambda (server)
  208. (simple-format #f " server ~A;\n" server))
  209. (nginx-upstream-configuration-servers upstream))
  210. " }\n"))
  211. (define (flatten . lst)
  212. "Return a list that recursively concatenates all sub-lists of LST."
  213. (define (flatten1 head out)
  214. (if (list? head)
  215. (fold-right flatten1 out head)
  216. (cons head out)))
  217. (fold-right flatten1 '() lst))
  218. (define (default-nginx-config nginx log-directory run-directory server-list upstream-list)
  219. (apply mixed-text-file "nginx.conf"
  220. (flatten
  221. "user nginx nginx;\n"
  222. "pid " run-directory "/pid;\n"
  223. "error_log " log-directory "/error.log info;\n"
  224. "http {\n"
  225. " client_body_temp_path " run-directory "/client_body_temp;\n"
  226. " proxy_temp_path " run-directory "/proxy_temp;\n"
  227. " fastcgi_temp_path " run-directory "/fastcgi_temp;\n"
  228. " uwsgi_temp_path " run-directory "/uwsgi_temp;\n"
  229. " scgi_temp_path " run-directory "/scgi_temp;\n"
  230. " access_log " log-directory "/access.log;\n"
  231. " include " nginx "/share/nginx/conf/mime.types;\n"
  232. "\n"
  233. (map emit-nginx-upstream-config upstream-list)
  234. (map emit-nginx-server-config server-list)
  235. "}\n"
  236. "events {}\n")))
  237. (define %nginx-accounts
  238. (list (user-group (name "nginx") (system? #t))
  239. (user-account
  240. (name "nginx")
  241. (group "nginx")
  242. (system? #t)
  243. (comment "nginx server user")
  244. (home-directory "/var/empty")
  245. (shell (file-append shadow "/sbin/nologin")))))
  246. (define nginx-activation
  247. (match-lambda
  248. (($ <nginx-configuration> nginx log-directory run-directory server-blocks
  249. upstream-blocks file)
  250. #~(begin
  251. (use-modules (guix build utils))
  252. (format #t "creating nginx log directory '~a'~%" #$log-directory)
  253. (mkdir-p #$log-directory)
  254. (format #t "creating nginx run directory '~a'~%" #$run-directory)
  255. (mkdir-p #$run-directory)
  256. (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory)
  257. (mkdir-p (string-append #$run-directory "/client_body_temp"))
  258. (mkdir-p (string-append #$run-directory "/proxy_temp"))
  259. (mkdir-p (string-append #$run-directory "/fastcgi_temp"))
  260. (mkdir-p (string-append #$run-directory "/uwsgi_temp"))
  261. (mkdir-p (string-append #$run-directory "/scgi_temp"))
  262. ;; Start-up logs. Once configuration is loaded, nginx switches to
  263. ;; log-directory.
  264. (mkdir-p (string-append #$run-directory "/logs"))
  265. ;; Check configuration file syntax.
  266. (system* (string-append #$nginx "/sbin/nginx")
  267. "-c" #$(or file
  268. (default-nginx-config nginx log-directory
  269. run-directory server-blocks upstream-blocks))
  270. "-t")))))
  271. (define nginx-shepherd-service
  272. (match-lambda
  273. (($ <nginx-configuration> nginx log-directory run-directory server-blocks
  274. upstream-blocks file)
  275. (let* ((nginx-binary (file-append nginx "/sbin/nginx"))
  276. (nginx-action
  277. (lambda args
  278. #~(lambda _
  279. (zero?
  280. (system* #$nginx-binary "-c"
  281. #$(or file
  282. (default-nginx-config nginx log-directory
  283. run-directory server-blocks upstream-blocks))
  284. #$@args))))))
  285. ;; TODO: Add 'reload' action.
  286. (list (shepherd-service
  287. (provision '(nginx))
  288. (documentation "Run the nginx daemon.")
  289. (requirement '(user-processes loopback))
  290. (start (nginx-action "-p" run-directory))
  291. (stop (nginx-action "-s" "stop"))))))))
  292. (define nginx-service-type
  293. (service-type (name 'nginx)
  294. (extensions
  295. (list (service-extension shepherd-root-service-type
  296. nginx-shepherd-service)
  297. (service-extension activation-service-type
  298. nginx-activation)
  299. (service-extension account-service-type
  300. (const %nginx-accounts))))
  301. (compose concatenate)
  302. (extend (lambda (config servers)
  303. (nginx-configuration
  304. (inherit config)
  305. (server-blocks
  306. (append (nginx-configuration-server-blocks config)
  307. servers)))))
  308. (default-value
  309. (nginx-configuration))))
  310. (define-record-type* <fcgiwrap-configuration> fcgiwrap-configuration
  311. make-fcgiwrap-configuration
  312. fcgiwrap-configuration?
  313. (package fcgiwrap-configuration-package ;<package>
  314. (default fcgiwrap))
  315. (socket fcgiwrap-configuration-socket
  316. (default "tcp:127.0.0.1:9000"))
  317. (user fcgiwrap-configuration-user
  318. (default "fcgiwrap"))
  319. (group fcgiwrap-configuration-group
  320. (default "fcgiwrap")))
  321. (define fcgiwrap-accounts
  322. (match-lambda
  323. (($ <fcgiwrap-configuration> package socket user group)
  324. (filter identity
  325. (list
  326. (and (equal? group "fcgiwrap")
  327. (user-group
  328. (name "fcgiwrap")
  329. (system? #t)))
  330. (and (equal? user "fcgiwrap")
  331. (user-account
  332. (name "fcgiwrap")
  333. (group group)
  334. (system? #t)
  335. (comment "Fcgiwrap Daemon")
  336. (home-directory "/var/empty")
  337. (shell (file-append shadow "/sbin/nologin")))))))))
  338. (define fcgiwrap-shepherd-service
  339. (match-lambda
  340. (($ <fcgiwrap-configuration> package socket user group)
  341. (list (shepherd-service
  342. (provision '(fcgiwrap))
  343. (documentation "Run the fcgiwrap daemon.")
  344. (requirement '(networking))
  345. (start #~(make-forkexec-constructor
  346. '(#$(file-append package "/sbin/fcgiwrap")
  347. "-s" #$socket)
  348. #:user #$user #:group #$group))
  349. (stop #~(make-kill-destructor)))))))
  350. (define fcgiwrap-service-type
  351. (service-type (name 'fcgiwrap)
  352. (extensions
  353. (list (service-extension shepherd-root-service-type
  354. fcgiwrap-shepherd-service)
  355. (service-extension account-service-type
  356. fcgiwrap-accounts)))
  357. (default-value (fcgiwrap-configuration))))