web.scm 86 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2015 David Thompson <davet@gnu.org>
  3. ;;; Copyright © 2015-2023 Ludovic Courtès <ludo@gnu.org>
  4. ;;; Copyright © 2016 Nikita <nikita@n0.is>
  5. ;;; Copyright © 2016, 2017, 2018 Julien Lepiller <julien@lepiller.eu>
  6. ;;; Copyright © 2017, 2018, 2019 Christopher Baines <mail@cbaines.net>
  7. ;;; Copyright © 2017 nee <nee-git@hidamari.blue>
  8. ;;; Copyright © 2017, 2018 Clément Lassieur <clement@lassieur.org>
  9. ;;; Copyright © 2018 Pierre-Antoine Rouby <pierre-antoine.rouby@inria.fr>
  10. ;;; Copyright © 2018 Marius Bakke <mbakke@fastmail.com>
  11. ;;; Copyright © 2019, 2020 Florian Pelz <pelzflorian@pelzflorian.de>
  12. ;;; Copyright © 2020, 2022 Ricardo Wurmus <rekado@elephly.net>
  13. ;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
  14. ;;; Copyright © 2020 Arun Isaac <arunisaac@systemreboot.net>
  15. ;;; Copyright © 2020 Oleg Pykhalov <go.wigust@gmail.com>
  16. ;;; Copyright © 2020, 2021 Alexandru-Sergiu Marton <brown121407@posteo.ro>
  17. ;;; Copyright © 2022 Simen Endsjø <simendsjo@gmail.com>
  18. ;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
  19. ;;;
  20. ;;; This file is part of GNU Guix.
  21. ;;;
  22. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  23. ;;; under the terms of the GNU General Public License as published by
  24. ;;; the Free Software Foundation; either version 3 of the License, or (at
  25. ;;; your option) any later version.
  26. ;;;
  27. ;;; GNU Guix is distributed in the hope that it will be useful, but
  28. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  29. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30. ;;; GNU General Public License for more details.
  31. ;;;
  32. ;;; You should have received a copy of the GNU General Public License
  33. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  34. (define-module (gnu services web)
  35. #:use-module (gnu services)
  36. #:use-module (gnu services shepherd)
  37. #:use-module (gnu services admin)
  38. #:use-module (gnu services getmail)
  39. #:use-module (gnu services mail)
  40. #:use-module (gnu system pam)
  41. #:use-module (gnu system shadow)
  42. #:use-module (gnu packages admin)
  43. #:use-module (gnu packages base)
  44. #:use-module (gnu packages databases)
  45. #:use-module (gnu packages web)
  46. #:use-module (gnu packages patchutils)
  47. #:use-module (gnu packages php)
  48. #:use-module (gnu packages python)
  49. #:use-module (gnu packages gnupg)
  50. #:use-module (gnu packages guile)
  51. #:use-module (gnu packages logging)
  52. #:use-module (gnu packages mail)
  53. #:use-module (gnu packages rust-apps)
  54. #:autoload (guix i18n) (G_)
  55. #:use-module (guix diagnostics)
  56. #:use-module (guix packages)
  57. #:use-module (guix records)
  58. #:use-module (guix modules)
  59. #:use-module (guix utils)
  60. #:use-module (guix gexp)
  61. #:use-module ((guix store) #:select (text-file))
  62. #:use-module ((guix utils) #:select (version-major))
  63. #:use-module ((guix packages) #:select (package-version))
  64. #:use-module (srfi srfi-1)
  65. #:use-module (srfi srfi-9)
  66. #:use-module (srfi srfi-34)
  67. #:use-module (ice-9 match)
  68. #:use-module (ice-9 format)
  69. #:export (httpd-configuration
  70. httpd-configuration?
  71. httpd-configuration-package
  72. httpd-configuration-pid-file
  73. httpd-configuration-config
  74. httpd-virtualhost
  75. httpd-virtualhost?
  76. httpd-virtualhost-addresses-and-ports
  77. httpd-virtualhost-contents
  78. httpd-config-file
  79. httpd-config-file?
  80. httpd-config-file-modules
  81. httpd-config-file-server-root
  82. httpd-config-file-server-name
  83. httpd-config-file-listen
  84. httpd-config-file-pid-file
  85. httpd-config-file-error-log
  86. httpd-config-file-user
  87. httpd-config-file-group
  88. httpd-module
  89. httpd-module?
  90. %default-httpd-modules
  91. httpd-service-type
  92. nginx-configuration
  93. nginx-configuration?
  94. nginx-configuration-nginx
  95. nginx-configuration-shepherd-requirement
  96. nginx-configuration-log-directory
  97. nginx-configuration-log-level
  98. nginx-configuration-run-directory
  99. nginx-configuration-server-blocks
  100. nginx-configuration-upstream-blocks
  101. nginx-configuration-server-names-hash-bucket-size
  102. nginx-configuration-server-names-hash-bucket-max-size
  103. nginx-configuration-modules
  104. nginx-configuration-global-directives
  105. nginx-configuration-extra-content
  106. nginx-configuration-file
  107. nginx-server-configuration
  108. nginx-server-configuration?
  109. nginx-server-configuration-listen
  110. nginx-server-configuration-server-name
  111. nginx-server-configuration-root
  112. nginx-server-configuration-locations
  113. nginx-server-configuration-index
  114. nginx-server-configuration-ssl-certificate
  115. nginx-server-configuration-ssl-certificate-key
  116. nginx-server-configuration-server-tokens?
  117. nginx-server-configuration-raw-content
  118. nginx-upstream-configuration
  119. nginx-upstream-configuration?
  120. nginx-upstream-configuration-name
  121. nginx-upstream-configuration-servers
  122. nginx-upstream-configuration-extra-content
  123. nginx-location-configuration
  124. nginx-location-configuration?
  125. nginx-location-configuration-uri
  126. nginx-location-configuration-body
  127. nginx-named-location-configuration
  128. nginx-named-location-configuration?
  129. nginx-named-location-configuration-name
  130. nginx-named-location-configuration-body
  131. nginx-service
  132. nginx-service-type
  133. fcgiwrap-configuration
  134. fcgiwrap-configuration?
  135. fcgiwrap-service-type
  136. php-fpm-configuration
  137. make-php-fpm-configuration
  138. php-fpm-configuration?
  139. php-fpm-configuration-php
  140. php-fpm-configuration-socket
  141. php-fpm-configuration-user
  142. php-fpm-configuration-group
  143. php-fpm-configuration-socket-user
  144. php-fpm-configuration-socket-group
  145. php-fpm-configuration-pid-file
  146. php-fpm-configuration-log-file
  147. php-fpm-configuration-process-manager
  148. php-fpm-configuration-display-errors
  149. php-fpm-configuration-timezone
  150. php-fpm-configuration-workers-log-file
  151. php-fpm-configuration-file
  152. php-fpm-configuration-php-ini-file
  153. php-fpm-dynamic-process-manager-configuration
  154. make-php-fpm-dynamic-process-manager-configuration
  155. php-fpm-dynamic-process-manager-configuration?
  156. php-fpm-dynamic-process-manager-configuration-max-children
  157. php-fpm-dynamic-process-manager-configuration-start-servers
  158. php-fpm-dynamic-process-manager-configuration-min-spare-servers
  159. php-fpm-dynamic-process-manager-configuration-max-spare-servers
  160. php-fpm-static-process-manager-configuration
  161. make-php-fpm-static-process-manager-configuration
  162. php-fpm-static-process-manager-configuration?
  163. php-fpm-static-process-manager-configuration-max-children
  164. php-fpm-on-demand-process-manager-configuration
  165. make-php-fpm-on-demand-process-manager-configuration
  166. php-fpm-on-demand-process-manager-configuration?
  167. php-fpm-on-demand-process-manager-configuration-max-children
  168. php-fpm-on-demand-process-manager-configuration-process-idle-timeout
  169. php-fpm-service-type
  170. nginx-php-location
  171. cat-avatar-generator-service
  172. hpcguix-web-configuration
  173. hpcguix-web-configuration?
  174. hpcguix-web-service-type
  175. tailon-configuration-file
  176. tailon-configuration-file?
  177. tailon-configuration-file-files
  178. tailon-configuration-file-bind
  179. tailon-configuration-file-relative-root
  180. tailon-configuration-file-allow-transfers?
  181. tailon-configuration-file-follow-names?
  182. tailon-configuration-file-tail-lines
  183. tailon-configuration-file-allowed-commands
  184. tailon-configuration-file-debug?
  185. tailon-configuration-file-http-auth
  186. tailon-configuration-file-users
  187. tailon-configuration
  188. tailon-configuration?
  189. tailon-configuration-config-file
  190. tailon-configuration-package
  191. tailon-service-type
  192. anonip-configuration
  193. anonip-configuration?
  194. anonip-configuration-anonip
  195. anonip-configuration-input
  196. anonip-configuration-output
  197. anonip-configuration-skip-private?
  198. anonip-configuration-column
  199. anonip-configuration-replacement
  200. anonip-configuration-ipv4mask
  201. anonip-configuration-ipv6mask
  202. anonip-configuration-increment
  203. anonip-configuration-delimiter
  204. anonip-configuration-regex
  205. anonip-service-type
  206. varnish-configuration
  207. varnish-configuration?
  208. varnish-configuration-package
  209. varnish-configuration-name
  210. varnish-configuration-backend
  211. varnish-configuration-vcl
  212. varnish-configuration-listen
  213. varnish-configuration-storage
  214. varnish-configuration-parameters
  215. varnish-configuration-extra-options
  216. varnish-service-type
  217. patchwork-database-configuration
  218. patchwork-database-configuration?
  219. patchwork-database-configuration-engine
  220. patchwork-database-configuration-name
  221. patchwork-database-configuration-user
  222. patchwork-database-configuration-password
  223. patchwork-database-configuration-host
  224. patchwork-database-configuration-port
  225. patchwork-settings-module
  226. patchwork-settings-module?
  227. patchwork-settings-module-database-configuration
  228. patchwork-settings-module-secret-key
  229. patchwork-settings-module-allowed-hosts
  230. patchwork-settings-module-default-from-email
  231. patchwork-settings-module-static-url
  232. patchwork-settings-module-admins
  233. patchwork-settings-module-debug?
  234. patchwork-settings-module-enable-rest-api?
  235. patchwork-settings-module-enable-xmlrpc?
  236. patchwork-settings-module-force-https-links?
  237. patchwork-settings-module-extra-settings
  238. patchwork-configuration
  239. patchwork-configuration?
  240. patchwork-configuration-patchwork
  241. patchwork-configuration-settings-module
  242. patchwork-configuration-domain
  243. patchwork-virtualhost
  244. patchwork-service-type
  245. mumi-configuration
  246. mumi-configuration?
  247. mumi-configuration-mumi
  248. mumi-configuration-mailer?
  249. mumi-configuration-sender
  250. mumi-configuration-smtp
  251. mumi-service-type
  252. gmnisrv-configuration
  253. gmnisrv-configuration?
  254. gmnisrv-configuration-package
  255. gmnisrv-configuration-config-file
  256. gmnisrv-service-type
  257. agate-configuration
  258. agate-configuration?
  259. agate-configuration-package
  260. agate-configuration-content
  261. agate-configuration-cert
  262. agate-configuration-key
  263. agate-configuration-addr
  264. agate-configuration-hostname
  265. agate-configuration-lang
  266. agate-configuration-silent
  267. agate-configuration-serve-secret
  268. agate-configuration-log-ip
  269. agate-configuration-user
  270. agate-configuration-group
  271. agate-configuration-log-file
  272. agate-service-type))
  273. ;;; Commentary:
  274. ;;;
  275. ;;; Web services.
  276. ;;;
  277. ;;; Code:
  278. (define-record-type* <httpd-module>
  279. httpd-module make-httpd-module
  280. httpd-module?
  281. (name httpd-load-module-name)
  282. (file httpd-load-module-file))
  283. ;; Default modules for the httpd-service-type, taken from etc/httpd/httpd.conf
  284. ;; file in the httpd package.
  285. (define %default-httpd-modules
  286. (map (match-lambda
  287. ((name file)
  288. (httpd-module
  289. (name name)
  290. (file file))))
  291. '(("authn_file_module" "modules/mod_authn_file.so")
  292. ("authn_core_module" "modules/mod_authn_core.so")
  293. ("authz_host_module" "modules/mod_authz_host.so")
  294. ("authz_groupfile_module" "modules/mod_authz_groupfile.so")
  295. ("authz_user_module" "modules/mod_authz_user.so")
  296. ("authz_core_module" "modules/mod_authz_core.so")
  297. ("access_compat_module" "modules/mod_access_compat.so")
  298. ("auth_basic_module" "modules/mod_auth_basic.so")
  299. ("reqtimeout_module" "modules/mod_reqtimeout.so")
  300. ("filter_module" "modules/mod_filter.so")
  301. ("mime_module" "modules/mod_mime.so")
  302. ("log_config_module" "modules/mod_log_config.so")
  303. ("env_module" "modules/mod_env.so")
  304. ("headers_module" "modules/mod_headers.so")
  305. ("setenvif_module" "modules/mod_setenvif.so")
  306. ("version_module" "modules/mod_version.so")
  307. ("unixd_module" "modules/mod_unixd.so")
  308. ("status_module" "modules/mod_status.so")
  309. ("autoindex_module" "modules/mod_autoindex.so")
  310. ("dir_module" "modules/mod_dir.so")
  311. ("alias_module" "modules/mod_alias.so"))))
  312. (define-record-type* <httpd-config-file>
  313. httpd-config-file make-httpd-config-file
  314. httpd-config-file?
  315. (modules httpd-config-file-modules
  316. (default %default-httpd-modules))
  317. (server-root httpd-config-file-server-root
  318. (default httpd))
  319. (server-name httpd-config-file-server-name
  320. (default #f))
  321. (document-root httpd-config-file-document-root
  322. (default "/srv/http"))
  323. (listen httpd-config-file-listen
  324. (default '("80")))
  325. (pid-file httpd-config-file-pid-file
  326. (default "/var/run/httpd"))
  327. (error-log httpd-config-file-error-log
  328. (default "/var/log/httpd/error_log"))
  329. (user httpd-config-file-user
  330. (default "httpd"))
  331. (group httpd-config-file-group
  332. (default "httpd"))
  333. (extra-config httpd-config-file-extra-config
  334. (default
  335. (list "TypesConfig etc/httpd/mime.types"))))
  336. (define-gexp-compiler (httpd-config-file-compiler
  337. (file <httpd-config-file>) system target)
  338. (match file
  339. (($ <httpd-config-file> load-modules server-root server-name
  340. document-root listen pid-file error-log
  341. user group extra-config)
  342. (gexp->derivation
  343. "httpd.conf"
  344. #~(call-with-output-file (ungexp output "out")
  345. (lambda (port)
  346. (display
  347. (string-append
  348. (ungexp-splicing
  349. `(,@(append-map
  350. (match-lambda
  351. (($ <httpd-module> name module)
  352. `("LoadModule " ,name " " ,module "\n")))
  353. load-modules)
  354. ,@`("ServerRoot " ,server-root "\n")
  355. ,@(if server-name
  356. `("ServerName " ,server-name "\n")
  357. '())
  358. ,@`("DocumentRoot " ,document-root "\n")
  359. ,@(append-map
  360. (lambda (listen-value)
  361. `("Listen " ,listen-value "\n"))
  362. listen)
  363. ,@(if pid-file
  364. `("Pidfile " ,pid-file "\n")
  365. '())
  366. ,@(if error-log
  367. `("ErrorLog " ,error-log "\n")
  368. '())
  369. ,@(if user
  370. `("User " ,user "\n")
  371. '())
  372. ,@(if group
  373. `("Group " ,group "\n")
  374. '())
  375. "\n\n"
  376. ,@extra-config)))
  377. port)))
  378. #:local-build? #t))))
  379. (define-record-type <httpd-virtualhost>
  380. (httpd-virtualhost addresses-and-ports contents)
  381. httpd-virtualhost?
  382. (addresses-and-ports httpd-virtualhost-addresses-and-ports)
  383. (contents httpd-virtualhost-contents))
  384. (define-record-type* <httpd-configuration>
  385. httpd-configuration make-httpd-configuration
  386. httpd-configuration?
  387. (package httpd-configuration-package
  388. (default httpd))
  389. (pid-file httpd-configuration-pid-file
  390. (default "/var/run/httpd"))
  391. (config httpd-configuration-config
  392. (default (httpd-config-file))))
  393. (define %httpd-accounts
  394. (list (user-group (name "httpd") (system? #t))
  395. (user-account
  396. (name "httpd")
  397. (group "httpd")
  398. (system? #t)
  399. (comment "Apache HTTPD server user")
  400. (home-directory "/var/empty")
  401. (shell (file-append shadow "/sbin/nologin")))))
  402. (define httpd-shepherd-services
  403. (match-lambda
  404. (($ <httpd-configuration> package pid-file config)
  405. (list (shepherd-service
  406. (provision '(httpd))
  407. (documentation "The Apache HTTP Server")
  408. (requirement '(networking))
  409. (start #~(make-forkexec-constructor
  410. `(#$(file-append package "/bin/httpd")
  411. #$@(if config
  412. (list "-f" config)
  413. '()))
  414. #:pid-file #$pid-file))
  415. (stop #~(make-kill-destructor)))))))
  416. (define httpd-activation
  417. (match-lambda
  418. (($ <httpd-configuration> package pid-file config)
  419. (match-record
  420. config
  421. <httpd-config-file>
  422. (error-log document-root)
  423. #~(begin
  424. (use-modules (guix build utils))
  425. (mkdir-p #$(dirname error-log))
  426. (mkdir-p #$document-root))))))
  427. (define (httpd-process-extensions original-config extension-configs)
  428. (let ((config (httpd-configuration-config
  429. original-config)))
  430. (if (httpd-config-file? config)
  431. (httpd-configuration
  432. (inherit original-config)
  433. (config
  434. (httpd-config-file
  435. (inherit config)
  436. (extra-config
  437. (append (httpd-config-file-extra-config config)
  438. (append-map
  439. (match-lambda
  440. (($ <httpd-virtualhost>
  441. addresses-and-ports
  442. contents)
  443. `(,(string-append
  444. "\n<VirtualHost " addresses-and-ports ">\n")
  445. ,@contents
  446. "\n</VirtualHost>\n"))
  447. ((? string? x)
  448. `("\n" ,x "\n"))
  449. ((? list? x)
  450. `("\n" ,@x "\n")))
  451. extension-configs)))))))))
  452. (define httpd-service-type
  453. (service-type (name 'httpd)
  454. (extensions
  455. (list (service-extension shepherd-root-service-type
  456. httpd-shepherd-services)
  457. (service-extension activation-service-type
  458. httpd-activation)
  459. (service-extension account-service-type
  460. (const %httpd-accounts))))
  461. (compose concatenate)
  462. (extend httpd-process-extensions)
  463. (default-value
  464. (httpd-configuration))
  465. (description "Run the Apache httpd Web server.")))
  466. (define-record-type* <nginx-server-configuration>
  467. nginx-server-configuration make-nginx-server-configuration
  468. nginx-server-configuration?
  469. (listen nginx-server-configuration-listen
  470. (default '("80" "443 ssl")))
  471. (server-name nginx-server-configuration-server-name
  472. (default (list 'default)))
  473. (root nginx-server-configuration-root
  474. (default "/srv/http"))
  475. (locations nginx-server-configuration-locations
  476. (default '()))
  477. (index nginx-server-configuration-index
  478. (default (list "index.html")))
  479. (try-files nginx-server-configuration-try-files
  480. (default '()))
  481. (ssl-certificate nginx-server-configuration-ssl-certificate
  482. (default #f))
  483. (ssl-certificate-key nginx-server-configuration-ssl-certificate-key
  484. (default #f))
  485. (server-tokens? nginx-server-configuration-server-tokens?
  486. (default #f))
  487. (raw-content nginx-server-configuration-raw-content
  488. (default '())))
  489. (define-record-type* <nginx-upstream-configuration>
  490. nginx-upstream-configuration make-nginx-upstream-configuration
  491. nginx-upstream-configuration?
  492. (name nginx-upstream-configuration-name)
  493. (servers nginx-upstream-configuration-servers)
  494. (extra-content nginx-upstream-configuration-extra-content
  495. (default '())))
  496. (define-record-type* <nginx-location-configuration>
  497. nginx-location-configuration make-nginx-location-configuration
  498. nginx-location-configuration?
  499. (uri nginx-location-configuration-uri
  500. (default #f))
  501. (body nginx-location-configuration-body))
  502. (define-record-type* <nginx-named-location-configuration>
  503. nginx-named-location-configuration make-nginx-named-location-configuration
  504. nginx-named-location-configuration?
  505. (name nginx-named-location-configuration-name
  506. (default #f))
  507. (body nginx-named-location-configuration-body))
  508. (define-record-type* <nginx-configuration>
  509. nginx-configuration make-nginx-configuration
  510. nginx-configuration?
  511. (nginx nginx-configuration-nginx ;file-like
  512. (default nginx))
  513. (shepherd-requirement nginx-configuration-shepherd-requirement
  514. (default '())) ;list of symbols
  515. (log-directory nginx-configuration-log-directory ;string
  516. (default "/var/log/nginx"))
  517. (log-level nginx-configuration-log-level
  518. (sanitize assert-valid-log-level)
  519. (default 'error))
  520. (run-directory nginx-configuration-run-directory ;string
  521. (default "/var/run/nginx"))
  522. (server-blocks nginx-configuration-server-blocks
  523. (default '())) ;list of <nginx-server-configuration>
  524. (upstream-blocks nginx-configuration-upstream-blocks
  525. (default '())) ;list of <nginx-upstream-configuration>
  526. (server-names-hash-bucket-size nginx-configuration-server-names-hash-bucket-size
  527. (default #f))
  528. (server-names-hash-bucket-max-size nginx-configuration-server-names-hash-bucket-max-size
  529. (default #f))
  530. (modules nginx-configuration-modules (default '()))
  531. (global-directives nginx-configuration-global-directives
  532. (default '((events . ()))))
  533. (lua-package-path nginx-lua-package-path ;list of file-like
  534. (default #f))
  535. (lua-package-cpath nginx-lua-package-cpath ;list of file-like
  536. (default #f))
  537. (extra-content nginx-configuration-extra-content
  538. (default ""))
  539. (file nginx-configuration-file ;#f | string | file-like
  540. (default #f)))
  541. (define (assert-valid-log-level level)
  542. "Ensure @var{level} is one of @code{'debug}, @code{'info}, @code{'notice},
  543. @code{'warn}, @code{'error}, @code{'crit}, @code{'alert}, or @code{'emerg}."
  544. (unless (memq level '(debug info notice warn error crit alert emerg))
  545. (raise
  546. (formatted-message (G_ "unknown log level '~a'~%") level)))
  547. level)
  548. (define (config-domain-strings names)
  549. "Return a string denoting the nginx config representation of NAMES, a list
  550. of domain names."
  551. (map (match-lambda
  552. ('default "_ ")
  553. ((? string? str) (list str " ")))
  554. names))
  555. (define (config-index-strings names)
  556. "Return a string denoting the nginx config representation of NAMES, a list
  557. of index files."
  558. (map (match-lambda
  559. ((? string? str) (list str " ")))
  560. names))
  561. (define (emit-load-module module)
  562. (list "load_module " module ";\n"))
  563. (define emit-global-directive
  564. (match-lambda
  565. ((key . (? list? alist))
  566. (format #f "~a { ~{~a~}}~%" key (map emit-global-directive alist)))
  567. ((key . value)
  568. (format #f "~a ~a;~%" key value))))
  569. (define emit-nginx-location-config
  570. (match-lambda
  571. (($ <nginx-location-configuration> uri body)
  572. (list
  573. " location " uri " {\n"
  574. (map (lambda (x) (list " " x "\n")) body)
  575. " }\n"))
  576. (($ <nginx-named-location-configuration> name body)
  577. (list
  578. " location @" name " {\n"
  579. (map (lambda (x) (list " " x "\n")) body)
  580. " }\n"))))
  581. (define (emit-nginx-server-config server)
  582. (let ((listen (nginx-server-configuration-listen server))
  583. (server-name (nginx-server-configuration-server-name server))
  584. (ssl-certificate (nginx-server-configuration-ssl-certificate server))
  585. (ssl-certificate-key
  586. (nginx-server-configuration-ssl-certificate-key server))
  587. (root (nginx-server-configuration-root server))
  588. (index (nginx-server-configuration-index server))
  589. (try-files (nginx-server-configuration-try-files server))
  590. (server-tokens? (nginx-server-configuration-server-tokens? server))
  591. (locations (nginx-server-configuration-locations server))
  592. (raw-content (nginx-server-configuration-raw-content server)))
  593. (define-syntax-parameter <> (syntax-rules ()))
  594. (define-syntax-rule (and/l x tail ...)
  595. (let ((x* x))
  596. (if x*
  597. (syntax-parameterize ((<> (identifier-syntax x*)))
  598. (list tail ...))
  599. '())))
  600. (list
  601. " server {\n"
  602. (map (lambda (directive) (list " listen " directive ";\n")) listen)
  603. " server_name " (config-domain-strings server-name) ";\n"
  604. (and/l ssl-certificate " ssl_certificate " <> ";\n")
  605. (and/l ssl-certificate-key " ssl_certificate_key " <> ";\n")
  606. (if (not (equal? "" root))
  607. (list " root " root ";\n")
  608. "")
  609. (if (not (null? index))
  610. (list " index " (config-index-strings index) ";\n")
  611. "")
  612. (if (not (nil? try-files))
  613. (and/l (config-index-strings try-files) " try_files " <> ";\n")
  614. "")
  615. " server_tokens " (if server-tokens? "on" "off") ";\n"
  616. "\n"
  617. (map emit-nginx-location-config locations)
  618. "\n"
  619. (map (lambda (x) (list " " x "\n")) raw-content)
  620. " }\n")))
  621. (define (emit-nginx-upstream-config upstream)
  622. (list
  623. " upstream " (nginx-upstream-configuration-name upstream) " {\n"
  624. (map (lambda (server)
  625. (simple-format #f " server ~A;\n" server))
  626. (nginx-upstream-configuration-servers upstream))
  627. (let ((extra-content
  628. (nginx-upstream-configuration-extra-content upstream)))
  629. (if (and extra-content (not (null? extra-content)))
  630. (cons
  631. "\n"
  632. (map (lambda (line)
  633. (simple-format #f " ~A\n" line))
  634. (flatten extra-content)))
  635. '()))
  636. " }\n"))
  637. (define (flatten . lst)
  638. "Return a list that recursively concatenates all sub-lists of LST."
  639. (define (flatten1 head out)
  640. (if (list? head)
  641. (fold-right flatten1 out head)
  642. (cons head out)))
  643. (fold-right flatten1 '() lst))
  644. (define (default-nginx-config config)
  645. (match-record config
  646. <nginx-configuration>
  647. (nginx log-directory run-directory
  648. log-level
  649. server-blocks upstream-blocks
  650. server-names-hash-bucket-size
  651. server-names-hash-bucket-max-size
  652. modules
  653. global-directives
  654. lua-package-path
  655. lua-package-cpath
  656. extra-content)
  657. (apply mixed-text-file "nginx.conf"
  658. (flatten
  659. "user nginx nginx;\n"
  660. "pid " run-directory "/pid;\n"
  661. "error_log " log-directory "/error.log " (symbol->string log-level) ";\n"
  662. (map emit-load-module modules)
  663. (map emit-global-directive global-directives)
  664. "http {\n"
  665. " client_body_temp_path " run-directory "/client_body_temp;\n"
  666. " proxy_temp_path " run-directory "/proxy_temp;\n"
  667. " fastcgi_temp_path " run-directory "/fastcgi_temp;\n"
  668. " uwsgi_temp_path " run-directory "/uwsgi_temp;\n"
  669. " scgi_temp_path " run-directory "/scgi_temp;\n"
  670. " access_log " log-directory "/access.log;\n"
  671. " include " nginx "/share/nginx/conf/mime.types;\n"
  672. (if lua-package-path
  673. #~(format #f " lua_package_path ~s;~%"
  674. (string-join (map (lambda (path)
  675. (string-append path "/lib/?.lua"))
  676. '#$lua-package-path)
  677. ";"))
  678. "")
  679. (if lua-package-cpath
  680. #~(format #f " lua_package_cpath ~s;~%"
  681. (string-join (map (lambda (cpath)
  682. (string-append cpath "/lib/lua/?.lua"))
  683. '#$lua-package-cpath)
  684. ";"))
  685. "")
  686. (if server-names-hash-bucket-size
  687. (string-append
  688. " server_names_hash_bucket_size "
  689. (number->string server-names-hash-bucket-size)
  690. ";\n")
  691. "")
  692. (if server-names-hash-bucket-max-size
  693. (string-append
  694. " server_names_hash_bucket_max_size "
  695. (number->string server-names-hash-bucket-max-size)
  696. ";\n")
  697. "")
  698. "\n"
  699. (map emit-nginx-upstream-config upstream-blocks)
  700. (map emit-nginx-server-config server-blocks)
  701. extra-content
  702. "\n}\n"))))
  703. (define %nginx-accounts
  704. (list (user-group (name "nginx") (system? #t))
  705. (user-account
  706. (name "nginx")
  707. (group "nginx")
  708. (system? #t)
  709. (comment "nginx server user")
  710. (home-directory "/var/empty")
  711. (shell (file-append shadow "/sbin/nologin")))))
  712. (define (nginx-activation config)
  713. (match-record config
  714. <nginx-configuration>
  715. (nginx log-directory run-directory file)
  716. #~(begin
  717. (use-modules (guix build utils))
  718. (format #t "creating nginx log directory '~a'~%" #$log-directory)
  719. (mkdir-p #$log-directory)
  720. (format #t "creating nginx run directory '~a'~%" #$run-directory)
  721. (mkdir-p #$run-directory)
  722. (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory)
  723. (mkdir-p (string-append #$run-directory "/client_body_temp"))
  724. (mkdir-p (string-append #$run-directory "/proxy_temp"))
  725. (mkdir-p (string-append #$run-directory "/fastcgi_temp"))
  726. (mkdir-p (string-append #$run-directory "/uwsgi_temp"))
  727. (mkdir-p (string-append #$run-directory "/scgi_temp"))
  728. ;; Start-up logs. Once configuration is loaded, nginx switches to
  729. ;; log-directory.
  730. (mkdir-p (string-append #$run-directory "/logs"))
  731. ;; Check configuration file syntax.
  732. (system* (string-append #$nginx "/sbin/nginx")
  733. "-c" #$(or file
  734. (default-nginx-config config))
  735. "-p" #$run-directory
  736. "-t"))))
  737. (define (nginx-shepherd-service config)
  738. (match-record config
  739. <nginx-configuration>
  740. (nginx file run-directory shepherd-requirement)
  741. (let* ((nginx-binary (file-append nginx "/sbin/nginx"))
  742. (pid-file (in-vicinity run-directory "pid"))
  743. (config-file (or file (default-nginx-config config)))
  744. (nginx-action
  745. (lambda args
  746. #~(lambda _
  747. (invoke #$nginx-binary "-c" #$config-file #$@args)
  748. (match '#$args
  749. (("-s" . _) #f)
  750. (_
  751. ;; When FILE is true, we cannot be sure that PID-FILE will
  752. ;; be created, so assume it won't show up. When FILE is
  753. ;; false, read PID-FILE.
  754. #$(if file
  755. #~#t
  756. #~(read-pid-file #$pid-file))))))))
  757. (list (shepherd-service
  758. (provision '(nginx))
  759. (documentation "Run the nginx daemon.")
  760. (requirement `(user-processes loopback ,@shepherd-requirement))
  761. (modules `((ice-9 match)
  762. ,@%default-modules))
  763. (start (nginx-action "-p" run-directory))
  764. (stop (nginx-action "-s" "stop"))
  765. (actions
  766. (list
  767. (shepherd-configuration-action config-file)
  768. (shepherd-action
  769. (name 'reload)
  770. (documentation "Reload nginx configuration file and restart worker processes.
  771. This has the effect of killing old worker processes and starting new ones, using
  772. the same configuration file. It is useful for situations where the same nginx
  773. configuration file can point to different things after a reload, such as
  774. renewed TLS certificates, or @code{include}d files.")
  775. (procedure (nginx-action "-s" "reload")))
  776. (shepherd-action
  777. (name 'reopen)
  778. (documentation "Re-open log files.")
  779. (procedure (nginx-action "-s" "reopen"))))))))))
  780. (define nginx-service-type
  781. (service-type (name 'nginx)
  782. (extensions
  783. (list (service-extension shepherd-root-service-type
  784. nginx-shepherd-service)
  785. (service-extension activation-service-type
  786. nginx-activation)
  787. (service-extension account-service-type
  788. (const %nginx-accounts))))
  789. (compose concatenate)
  790. (extend (lambda (config servers)
  791. (nginx-configuration
  792. (inherit config)
  793. (server-blocks
  794. (append (nginx-configuration-server-blocks config)
  795. servers)))))
  796. (default-value (nginx-configuration))
  797. (description "Run the nginx Web server.")))
  798. (define-record-type* <fcgiwrap-configuration> fcgiwrap-configuration
  799. make-fcgiwrap-configuration
  800. fcgiwrap-configuration?
  801. (package fcgiwrap-configuration-package ;file-like
  802. (default fcgiwrap))
  803. (socket fcgiwrap-configuration-socket
  804. (default "tcp:127.0.0.1:9000"))
  805. (user fcgiwrap-configuration-user
  806. (default "fcgiwrap"))
  807. (group fcgiwrap-configuration-group
  808. (default "fcgiwrap")))
  809. (define fcgiwrap-accounts
  810. (match-lambda
  811. (($ <fcgiwrap-configuration> package socket user group)
  812. (filter identity
  813. (list
  814. (and (equal? group "fcgiwrap")
  815. (user-group
  816. (name "fcgiwrap")
  817. (system? #t)))
  818. (and (equal? user "fcgiwrap")
  819. (user-account
  820. (name "fcgiwrap")
  821. (group group)
  822. (system? #t)
  823. (comment "Fcgiwrap Daemon")
  824. (home-directory "/var/empty")
  825. (shell (file-append shadow "/sbin/nologin")))))))))
  826. (define fcgiwrap-shepherd-service
  827. (match-lambda
  828. (($ <fcgiwrap-configuration> package socket user group)
  829. (list (shepherd-service
  830. (provision '(fcgiwrap))
  831. (documentation "Run the fcgiwrap daemon.")
  832. (requirement '(networking))
  833. (start #~(make-forkexec-constructor
  834. '(#$(file-append package "/sbin/fcgiwrap")
  835. "-s" #$socket)
  836. #:user #$user #:group #$group
  837. #:log-file "/var/log/fcgiwrap.log"))
  838. (stop #~(make-kill-destructor)))))))
  839. (define fcgiwrap-activation
  840. (match-lambda
  841. (($ <fcgiwrap-configuration> package socket user group)
  842. #~(begin
  843. ;; When listening on a unix socket, create a parent directory for the
  844. ;; socket with the correct permissions.
  845. (when (string-prefix? "unix:" #$socket)
  846. (let ((run-directory
  847. (dirname (substring #$socket (string-length "unix:")))))
  848. (mkdir-p run-directory)
  849. (chown run-directory
  850. (passwd:uid (getpw #$user))
  851. (group:gid (getgr #$group)))))))))
  852. (define fcgiwrap-service-type
  853. (service-type (name 'fcgiwrap)
  854. (extensions
  855. (list (service-extension shepherd-root-service-type
  856. fcgiwrap-shepherd-service)
  857. (service-extension account-service-type
  858. fcgiwrap-accounts)
  859. (service-extension activation-service-type
  860. fcgiwrap-activation)))
  861. (default-value (fcgiwrap-configuration))
  862. (description "Run FastCGI, an interface between the front-end
  863. and the back-end of a Web service.")))
  864. (define-record-type* <php-fpm-configuration> php-fpm-configuration
  865. make-php-fpm-configuration
  866. php-fpm-configuration?
  867. (php php-fpm-configuration-php ;file-like
  868. (default php))
  869. (socket php-fpm-configuration-socket
  870. (default (string-append "/var/run/php"
  871. (version-major (package-version php))
  872. "-fpm.sock")))
  873. (user php-fpm-configuration-user
  874. (default "php-fpm"))
  875. (group php-fpm-configuration-group
  876. (default "php-fpm"))
  877. (socket-user php-fpm-configuration-socket-user
  878. (default "php-fpm"))
  879. (socket-group php-fpm-configuration-socket-group
  880. (default "nginx"))
  881. (pid-file php-fpm-configuration-pid-file
  882. (default (string-append "/var/run/php"
  883. (version-major (package-version php))
  884. "-fpm.pid")))
  885. (log-file php-fpm-configuration-log-file
  886. (default (string-append "/var/log/php"
  887. (version-major (package-version php))
  888. "-fpm.log")))
  889. (process-manager php-fpm-configuration-process-manager
  890. (default (php-fpm-dynamic-process-manager-configuration)))
  891. (display-errors php-fpm-configuration-display-errors
  892. (default #f))
  893. (timezone php-fpm-configuration-timezone
  894. (default #f))
  895. (workers-log-file php-fpm-configuration-workers-log-file
  896. (default (string-append "/var/log/php"
  897. (version-major (package-version php))
  898. "-fpm.www.log")))
  899. (file php-fpm-configuration-file ;#f | file-like
  900. (default #f))
  901. (php-ini-file php-fpm-configuration-php-ini-file ;#f | file-like
  902. (default #f)))
  903. (define-record-type* <php-fpm-dynamic-process-manager-configuration>
  904. php-fpm-dynamic-process-manager-configuration
  905. make-php-fpm-dynamic-process-manager-configuration
  906. php-fpm-dynamic-process-manager-configuration?
  907. (max-children php-fpm-dynamic-process-manager-configuration-max-children
  908. (default 5))
  909. (start-servers php-fpm-dynamic-process-manager-configuration-start-servers
  910. (default 2))
  911. (min-spare-servers php-fpm-dynamic-process-manager-configuration-min-spare-servers
  912. (default 1))
  913. (max-spare-servers php-fpm-dynamic-process-manager-configuration-max-spare-servers
  914. (default 3)))
  915. (define-record-type* <php-fpm-static-process-manager-configuration>
  916. php-fpm-static-process-manager-configuration
  917. make-php-fpm-static-process-manager-configuration
  918. php-fpm-static-process-manager-configuration?
  919. (max-children php-fpm-static-process-manager-configuration-max-children
  920. (default 5)))
  921. (define-record-type* <php-fpm-on-demand-process-manager-configuration>
  922. php-fpm-on-demand-process-manager-configuration
  923. make-php-fpm-on-demand-process-manager-configuration
  924. php-fpm-on-demand-process-manager-configuration?
  925. (max-children php-fpm-on-demand-process-manager-configuration-max-children
  926. (default 5))
  927. (process-idle-timeout php-fpm-on-demand-process-manager-configuration-process-idle-timeout
  928. (default 10)))
  929. (define php-fpm-accounts
  930. (match-lambda
  931. (($ <php-fpm-configuration> php socket user group socket-user socket-group)
  932. `(,@(if (equal? group "php-fpm")
  933. '()
  934. (list (user-group (name "php-fpm") (system? #t))))
  935. ,(user-group
  936. (name group)
  937. (system? #t))
  938. ,(user-account
  939. (name user)
  940. (group group)
  941. (supplementary-groups '("php-fpm"))
  942. (system? #t)
  943. (comment "php-fpm daemon user")
  944. (home-directory "/var/empty")
  945. (shell (file-append shadow "/sbin/nologin")))))))
  946. (define (default-php-fpm-config socket user group socket-user socket-group
  947. pid-file log-file pm display-errors timezone workers-log-file)
  948. (apply mixed-text-file "php-fpm.conf"
  949. (flatten
  950. "[global]\n"
  951. "pid =" pid-file "\n"
  952. "error_log =" log-file "\n"
  953. "[www]\n"
  954. "user =" user "\n"
  955. "group =" group "\n"
  956. "listen =" socket "\n"
  957. "listen.owner =" socket-user "\n"
  958. "listen.group =" socket-group "\n"
  959. (if timezone
  960. (string-append "php_admin_value[date.timezone] = \"" timezone "\"\n")
  961. "")
  962. (match pm
  963. (($ <php-fpm-dynamic-process-manager-configuration>
  964. pm.max-children
  965. pm.start-servers
  966. pm.min-spare-servers
  967. pm.max-spare-servers)
  968. (list
  969. "pm = dynamic\n"
  970. "pm.max_children =" (number->string pm.max-children) "\n"
  971. "pm.start_servers =" (number->string pm.start-servers) "\n"
  972. "pm.min_spare_servers =" (number->string pm.min-spare-servers) "\n"
  973. "pm.max_spare_servers =" (number->string pm.max-spare-servers) "\n"))
  974. (($ <php-fpm-static-process-manager-configuration>
  975. pm.max-children)
  976. (list
  977. "pm = static\n"
  978. "pm.max_children =" (number->string pm.max-children) "\n"))
  979. (($ <php-fpm-on-demand-process-manager-configuration>
  980. pm.max-children
  981. pm.process-idle-timeout)
  982. (list
  983. "pm = ondemand\n"
  984. "pm.max_children =" (number->string pm.max-children) "\n"
  985. "pm.process_idle_timeout =" (number->string pm.process-idle-timeout) "s\n")))
  986. "php_flag[display_errors] = " (if display-errors "on" "off") "\n"
  987. (if workers-log-file
  988. (list "catch_workers_output = yes\n"
  989. "php_admin_value[error_log] =" workers-log-file "\n"
  990. "php_admin_flag[log_errors] = on\n")
  991. (list "catch_workers_output = no\n")))))
  992. (define php-fpm-shepherd-service
  993. (match-lambda
  994. (($ <php-fpm-configuration> php socket user group socket-user socket-group
  995. pid-file log-file pm display-errors
  996. timezone workers-log-file file php-ini-file)
  997. (list (shepherd-service
  998. (provision '(php-fpm))
  999. (documentation "Run the php-fpm daemon.")
  1000. (requirement '(networking))
  1001. (start #~(make-forkexec-constructor
  1002. '(#$(file-append php "/sbin/php-fpm")
  1003. "--fpm-config"
  1004. #$(or file
  1005. (default-php-fpm-config socket user group
  1006. socket-user socket-group pid-file log-file
  1007. pm display-errors timezone workers-log-file))
  1008. #$@(if php-ini-file
  1009. `("-c" ,php-ini-file)
  1010. '()))
  1011. #:pid-file #$pid-file))
  1012. (stop #~(make-kill-destructor)))))))
  1013. (define (php-fpm-activation config)
  1014. #~(begin
  1015. (use-modules (guix build utils))
  1016. (let* ((user (getpwnam #$(php-fpm-configuration-user config)))
  1017. (touch (lambda (file-name)
  1018. (call-with-output-file file-name (const #t))))
  1019. (workers-log-file
  1020. #$(php-fpm-configuration-workers-log-file config))
  1021. (init-log-file
  1022. (lambda (file-name)
  1023. (when workers-log-file
  1024. (when (not (file-exists? file-name))
  1025. (touch file-name))
  1026. (chown file-name (passwd:uid user) (passwd:gid user))
  1027. (chmod file-name #o660)))))
  1028. (init-log-file #$(php-fpm-configuration-log-file config))
  1029. (init-log-file workers-log-file))))
  1030. (define php-fpm-service-type
  1031. (service-type
  1032. (name 'php-fpm)
  1033. (description
  1034. "Run @command{php-fpm} to provide a fastcgi socket for calling php through
  1035. a webserver.")
  1036. (extensions
  1037. (list (service-extension shepherd-root-service-type
  1038. php-fpm-shepherd-service)
  1039. (service-extension activation-service-type
  1040. php-fpm-activation)
  1041. (service-extension account-service-type
  1042. php-fpm-accounts)))
  1043. (default-value (php-fpm-configuration))))
  1044. (define* (nginx-php-location
  1045. #:key
  1046. (nginx-package nginx)
  1047. (socket (string-append "/var/run/php"
  1048. (version-major (package-version php))
  1049. "-fpm.sock")))
  1050. "Return a nginx-location-configuration that makes nginx run .php files."
  1051. (nginx-location-configuration
  1052. (uri "~ \\.php$")
  1053. (body (list
  1054. "fastcgi_split_path_info ^(.+\\.php)(/.+)$;"
  1055. (string-append "fastcgi_pass unix:" socket ";")
  1056. "fastcgi_index index.php;"
  1057. (list "include " nginx-package "/share/nginx/conf/fastcgi.conf;")))))
  1058. (define* (cat-avatar-generator-service
  1059. #:key
  1060. (cache-dir "/var/cache/cat-avatar-generator")
  1061. (package cat-avatar-generator)
  1062. (configuration (nginx-server-configuration)))
  1063. (simple-service
  1064. 'cat-http-server nginx-service-type
  1065. (list (nginx-server-configuration
  1066. (inherit configuration)
  1067. (locations
  1068. (cons
  1069. (let ((base (nginx-php-location)))
  1070. (nginx-location-configuration
  1071. (inherit base)
  1072. (body (list (string-append "fastcgi_param CACHE_DIR \""
  1073. cache-dir "\";")
  1074. (nginx-location-configuration-body base)))))
  1075. (nginx-server-configuration-locations configuration)))
  1076. (root #~(string-append #$package
  1077. "/share/web/cat-avatar-generator"))))))
  1078. (define-record-type* <hpcguix-web-configuration>
  1079. hpcguix-web-configuration make-hpcguix-web-configuration
  1080. hpcguix-web-configuration?
  1081. (package hpcguix-web-package (default hpcguix-web)) ;file-like
  1082. (specs hpcguix-web-configuration-specs (default #f)) ;#f | gexp
  1083. (address hpcguix-web-configuration-address (default "127.0.0.1"))
  1084. (port hpcguix-web-configuration-port (default 5000)))
  1085. (define %hpcguix-web-accounts
  1086. (list (user-group
  1087. (name "hpcguix-web")
  1088. (system? #t))
  1089. (user-account
  1090. (name "hpcguix-web")
  1091. (group "hpcguix-web")
  1092. (system? #t)
  1093. (comment "hpcguix-web")
  1094. (home-directory "/var/empty")
  1095. (shell (file-append shadow "/sbin/nologin")))))
  1096. (define %hpcguix-web-activation
  1097. (with-imported-modules '((guix build utils))
  1098. #~(begin
  1099. (use-modules (guix build utils)
  1100. (ice-9 ftw))
  1101. (let ((home-dir "/var/cache/guix/web")
  1102. (user (getpwnam "hpcguix-web")))
  1103. (mkdir-p home-dir)
  1104. (chown home-dir (passwd:uid user) (passwd:gid user))
  1105. (chmod home-dir #o755)
  1106. ;; Remove stale 'packages.json.lock' file (and other lock files, if
  1107. ;; any) since that would prevent 'packages.json' from being updated.
  1108. (for-each (lambda (lock)
  1109. (delete-file (string-append home-dir "/" lock)))
  1110. (scandir home-dir
  1111. (lambda (file)
  1112. (string-suffix? ".lock" file))))))))
  1113. (define %hpcguix-web-log-file
  1114. "/var/log/hpcguix-web.log")
  1115. (define %hpcguix-web-log-rotations
  1116. (list (log-rotation
  1117. (files (list %hpcguix-web-log-file))
  1118. (frequency 'weekly))))
  1119. (define (hpcguix-web-shepherd-service config)
  1120. (let ((specs (hpcguix-web-configuration-specs config))
  1121. (hpcguix-web (hpcguix-web-package config)))
  1122. (with-imported-modules (source-module-closure
  1123. '((gnu build shepherd)))
  1124. (shepherd-service
  1125. (documentation "hpcguix-web daemon")
  1126. (provision '(hpcguix-web))
  1127. (requirement '(networking))
  1128. (start #~(make-forkexec-constructor
  1129. (list #$(file-append hpcguix-web "/bin/hpcguix-web")
  1130. (string-append "--listen="
  1131. #$(hpcguix-web-configuration-address
  1132. config))
  1133. "-p"
  1134. #$(number->string
  1135. (hpcguix-web-configuration-port config))
  1136. #$@(if specs
  1137. #~((string-append "--config="
  1138. #$(scheme-file
  1139. "hpcguix-web.scm" specs)))
  1140. #~()))
  1141. #:user "hpcguix-web"
  1142. #:group "hpcguix-web"
  1143. #:environment-variables
  1144. (list "XDG_CACHE_HOME=/var/cache/guix/web"
  1145. "SSL_CERT_DIR=/etc/ssl/certs")
  1146. #:log-file #$%hpcguix-web-log-file))
  1147. (stop #~(make-kill-destructor))))))
  1148. (define hpcguix-web-service-type
  1149. (service-type
  1150. (name 'hpcguix-web)
  1151. (description "Run the hpcguix-web server.")
  1152. (extensions
  1153. (list (service-extension account-service-type
  1154. (const %hpcguix-web-accounts))
  1155. (service-extension activation-service-type
  1156. (const %hpcguix-web-activation))
  1157. (service-extension rottlog-service-type
  1158. (const %hpcguix-web-log-rotations))
  1159. (service-extension shepherd-root-service-type
  1160. (compose list hpcguix-web-shepherd-service))))
  1161. (default-value (hpcguix-web-configuration))))
  1162. ;;;
  1163. ;;; Tailon
  1164. ;;;
  1165. (define-record-type* <tailon-configuration-file>
  1166. tailon-configuration-file make-tailon-configuration-file
  1167. tailon-configuration-file?
  1168. (files tailon-configuration-file-files
  1169. (default '("/var/log")))
  1170. (bind tailon-configuration-file-bind
  1171. (default "localhost:8080"))
  1172. (relative-root tailon-configuration-file-relative-root
  1173. (default #f))
  1174. (allow-transfers? tailon-configuration-file-allow-transfers?
  1175. (default #t))
  1176. (follow-names? tailon-configuration-file-follow-names?
  1177. (default #t))
  1178. (tail-lines tailon-configuration-file-tail-lines
  1179. (default 200))
  1180. (allowed-commands tailon-configuration-file-allowed-commands
  1181. (default '("tail" "grep" "awk")))
  1182. (debug? tailon-configuration-file-debug?
  1183. (default #f))
  1184. (wrap-lines tailon-configuration-file-wrap-lines
  1185. (default #t))
  1186. (http-auth tailon-configuration-file-http-auth
  1187. (default #f))
  1188. (users tailon-configuration-file-users
  1189. (default #f)))
  1190. (define (tailon-configuration-files-string files)
  1191. (string-append
  1192. "\n"
  1193. (string-join
  1194. (map
  1195. (lambda (x)
  1196. (string-append
  1197. " - "
  1198. (cond
  1199. ((string? x)
  1200. (simple-format #f "'~A'" x))
  1201. ((list? x)
  1202. (string-join
  1203. (cons (simple-format #f "'~A':" (car x))
  1204. (map
  1205. (lambda (x) (simple-format #f " - '~A'" x))
  1206. (cdr x)))
  1207. "\n"))
  1208. (else (error x)))))
  1209. files)
  1210. "\n")))
  1211. (define-gexp-compiler (tailon-configuration-file-compiler
  1212. (file <tailon-configuration-file>) system target)
  1213. (match file
  1214. (($ <tailon-configuration-file> files bind relative-root
  1215. allow-transfers? follow-names?
  1216. tail-lines allowed-commands debug?
  1217. wrap-lines http-auth users)
  1218. (text-file
  1219. "tailon-config.yaml"
  1220. (string-concatenate
  1221. (filter-map
  1222. (match-lambda
  1223. ((key . #f) #f)
  1224. ((key . value) (string-append key ": " value "\n")))
  1225. `(("files" . ,(tailon-configuration-files-string files))
  1226. ("bind" . ,bind)
  1227. ("relative-root" . ,relative-root)
  1228. ("allow-transfers" . ,(if allow-transfers? "true" "false"))
  1229. ("follow-names" . ,(if follow-names? "true" "false"))
  1230. ("tail-lines" . ,(number->string tail-lines))
  1231. ("commands" . ,(string-append "["
  1232. (string-join allowed-commands ", ")
  1233. "]"))
  1234. ("debug" . ,(if debug? "true" #f))
  1235. ("wrap-lines" . ,(if wrap-lines "true" "false"))
  1236. ("http-auth" . ,http-auth)
  1237. ("users" . ,(if users
  1238. (string-concatenate
  1239. (cons "\n"
  1240. (map (match-lambda
  1241. ((user . pass)
  1242. (string-append
  1243. " " user ":" pass)))
  1244. users)))
  1245. #f)))))))))
  1246. (define-record-type* <tailon-configuration>
  1247. tailon-configuration make-tailon-configuration
  1248. tailon-configuration?
  1249. (config-file tailon-configuration-config-file
  1250. (default (tailon-configuration-file)))
  1251. (package tailon-configuration-package
  1252. (default tailon)))
  1253. (define tailon-shepherd-service
  1254. (match-lambda
  1255. (($ <tailon-configuration> config-file package)
  1256. (list (shepherd-service
  1257. (provision '(tailon))
  1258. (documentation "Run the tailon daemon.")
  1259. (start #~(make-forkexec-constructor
  1260. `(,(string-append #$package "/bin/tailon")
  1261. "-c" ,#$config-file)
  1262. #:user "tailon"
  1263. #:group "tailon"))
  1264. (stop #~(make-kill-destructor)))))))
  1265. (define %tailon-accounts
  1266. (list (user-group (name "tailon") (system? #t))
  1267. (user-account
  1268. (name "tailon")
  1269. (group "tailon")
  1270. (system? #t)
  1271. (comment "tailon")
  1272. (home-directory "/var/empty")
  1273. (shell (file-append shadow "/sbin/nologin")))))
  1274. (define tailon-service-type
  1275. (service-type
  1276. (name 'tailon)
  1277. (description
  1278. "Run Tailon, a Web application for monitoring, viewing, and searching log
  1279. files.")
  1280. (extensions
  1281. (list (service-extension shepherd-root-service-type
  1282. tailon-shepherd-service)
  1283. (service-extension account-service-type
  1284. (const %tailon-accounts))))
  1285. (compose concatenate)
  1286. (extend (lambda (parameter files)
  1287. (tailon-configuration
  1288. (inherit parameter)
  1289. (config-file
  1290. (let ((old-config-file
  1291. (tailon-configuration-config-file parameter)))
  1292. (tailon-configuration-file
  1293. (inherit old-config-file)
  1294. (files (append (tailon-configuration-file-files old-config-file)
  1295. files))))))))
  1296. (default-value (tailon-configuration))))
  1297. ;;;
  1298. ;;; Log anonymization
  1299. ;;;
  1300. (define-record-type* <anonip-configuration>
  1301. anonip-configuration make-anonip-configuration
  1302. anonip-configuration?
  1303. (anonip anonip-configuration-anonip ;file-like
  1304. (default anonip))
  1305. (input anonip-configuration-input) ;string
  1306. (output anonip-configuration-output) ;string
  1307. (skip-private? anonip-configuration-skip-private? ;boolean
  1308. (default #f))
  1309. (column anonip-configuration-column ;number
  1310. (default #f))
  1311. (replacement anonip-configuration-replacement ;string
  1312. (default #f))
  1313. (ipv4mask anonip-configuration-ipv4mask ;number
  1314. (default #f))
  1315. (ipv6mask anonip-configuration-ipv6mask ;number
  1316. (default #f))
  1317. (increment anonip-configuration-increment ;number
  1318. (default #f))
  1319. (delimiter anonip-configuration-delimiter ;string
  1320. (default #f))
  1321. (regex anonip-configuration-regex ;string
  1322. (default #f)))
  1323. (define (anonip-activation config)
  1324. (with-imported-modules '((guix build utils))
  1325. #~(begin
  1326. (use-modules (guix build utils))
  1327. (for-each
  1328. (lambda (directory)
  1329. (mkdir-p directory)
  1330. (chmod directory #o755))
  1331. (list (dirname #$(anonip-configuration-input config))
  1332. (dirname #$(anonip-configuration-output config)))))))
  1333. (define (anonip-shepherd-service config)
  1334. (let ((input (anonip-configuration-input config))
  1335. (output (anonip-configuration-output config))
  1336. (optional
  1337. (lambda (accessor option)
  1338. (or (and=> (accessor config)
  1339. (lambda (value)
  1340. (list
  1341. (format #false "~a=~a"
  1342. option value))))
  1343. (list)))))
  1344. (list
  1345. (shepherd-service
  1346. (provision
  1347. (list (symbol-append 'anonip- (string->symbol output))))
  1348. (requirement '(user-processes))
  1349. (documentation
  1350. "Anonimyze the given log file location with anonip.")
  1351. (start
  1352. #~(lambda ()
  1353. (define (spawn)
  1354. (fork+exec-command
  1355. (append
  1356. (list #$(file-append (anonip-configuration-anonip config)
  1357. "/bin/anonip")
  1358. (string-append "--input=" #$input)
  1359. (string-append "--output=" #$output))
  1360. (if #$(anonip-configuration-skip-private? config)
  1361. '("--skip-private") (list))
  1362. '#$(optional anonip-configuration-column "--column")
  1363. '#$(optional anonip-configuration-ipv4mask "--ipv4mask")
  1364. '#$(optional anonip-configuration-ipv6mask "--ipv6mask")
  1365. '#$(optional anonip-configuration-increment "--increment")
  1366. '#$(optional anonip-configuration-replacement
  1367. "--replacement")
  1368. '#$(optional anonip-configuration-delimiter "--delimiter")
  1369. '#$(optional anonip-configuration-regex "--regex"))
  1370. ;; Run in a UTF-8 locale
  1371. #:environment-variables
  1372. (list (string-append "GUIX_LOCPATH=" #$glibc-utf8-locales
  1373. "/lib/locale")
  1374. "LC_ALL=en_US.utf8")))
  1375. (let ((stat (stat #$input #f)))
  1376. (cond ((not stat)
  1377. (mknod #$input 'fifo #o600 0)
  1378. (spawn))
  1379. ((eq? 'fifo (stat:type stat))
  1380. (spawn))
  1381. (else
  1382. (format #t "'~a' is not a FIFO; bailing out~%"
  1383. #$input)
  1384. #f)))))
  1385. (stop #~(make-kill-destructor))))))
  1386. (define anonip-service-type
  1387. (service-type
  1388. (name 'anonip)
  1389. (extensions
  1390. (list (service-extension shepherd-root-service-type
  1391. anonip-shepherd-service)
  1392. (service-extension activation-service-type
  1393. anonip-activation)))
  1394. (description
  1395. "Provide web server log anonymization with @command{anonip}.")))
  1396. ;;;
  1397. ;;; Varnish
  1398. ;;;
  1399. (define-record-type* <varnish-configuration>
  1400. varnish-configuration make-varnish-configuration
  1401. varnish-configuration?
  1402. (package varnish-configuration-package ;file-like
  1403. (default varnish))
  1404. (name varnish-configuration-name ;string
  1405. (default "default"))
  1406. (backend varnish-configuration-backend ;string
  1407. (default "localhost:8080"))
  1408. (vcl varnish-configuration-vcl ;#f | <file-like>
  1409. (default #f))
  1410. (listen varnish-configuration-listen ;list of strings
  1411. (default '("localhost:80")))
  1412. (storage varnish-configuration-storage ;list of strings
  1413. (default '("malloc,128m")))
  1414. (parameters varnish-configuration-parameters ;list of string pairs
  1415. (default '()))
  1416. (extra-options varnish-configuration-extra-options ;list of strings
  1417. (default '())))
  1418. (define %varnish-accounts
  1419. (list (user-group
  1420. (name "varnish")
  1421. (system? #t))
  1422. (user-account
  1423. (name "varnish")
  1424. (group "varnish")
  1425. (system? #t)
  1426. (comment "Varnish Cache User")
  1427. (home-directory "/var/varnish")
  1428. (shell (file-append shadow "/sbin/nologin")))))
  1429. (define varnish-shepherd-service
  1430. (match-lambda
  1431. (($ <varnish-configuration> package name backend vcl listen storage
  1432. parameters extra-options)
  1433. (list (shepherd-service
  1434. (provision (list (symbol-append 'varnish- (string->symbol name))))
  1435. (documentation (string-append "The Varnish Web Accelerator"
  1436. " (" name ")"))
  1437. (requirement '(networking))
  1438. (start #~(make-forkexec-constructor
  1439. (list #$(file-append package "/sbin/varnishd")
  1440. "-n" #$name
  1441. #$@(if vcl
  1442. #~("-f" #$vcl)
  1443. #~("-b" #$backend))
  1444. #$@(append-map (lambda (a) (list "-a" a)) listen)
  1445. #$@(append-map (lambda (s) (list "-s" s)) storage)
  1446. #$@(append-map (lambda (p)
  1447. (list "-p" (format #f "~a=~a"
  1448. (car p) (cdr p))))
  1449. parameters)
  1450. #$@extra-options)
  1451. ;; Varnish will drop privileges to the "varnish" user when
  1452. ;; it exists. Not passing #:user here allows the service
  1453. ;; to bind to ports < 1024.
  1454. #:pid-file (if (string-prefix? "/" #$name)
  1455. (string-append #$name "/_.pid")
  1456. (string-append "/var/varnish/" #$name "/_.pid"))))
  1457. (stop #~(make-kill-destructor)))))))
  1458. (define varnish-service-type
  1459. (service-type
  1460. (name 'varnish)
  1461. (description "Run the Varnish cache server.")
  1462. (extensions
  1463. (list (service-extension account-service-type
  1464. (const %varnish-accounts))
  1465. (service-extension shepherd-root-service-type
  1466. varnish-shepherd-service)))
  1467. (default-value
  1468. (varnish-configuration))))
  1469. ;;;
  1470. ;;; Patchwork
  1471. ;;;
  1472. (define-record-type* <patchwork-database-configuration>
  1473. patchwork-database-configuration make-patchwork-database-configuration
  1474. patchwork-database-configuration?
  1475. (engine patchwork-database-configuration-engine
  1476. (default "django.db.backends.postgresql_psycopg2"))
  1477. (name patchwork-database-configuration-name
  1478. (default "patchwork"))
  1479. (user patchwork-database-configuration-user
  1480. (default "httpd"))
  1481. (password patchwork-database-configuration-password
  1482. (default ""))
  1483. (host patchwork-database-configuration-host
  1484. (default ""))
  1485. (port patchwork-database-configuration-port
  1486. (default "")))
  1487. (define-record-type* <patchwork-settings-module>
  1488. patchwork-settings-module make-patchwork-settings-module
  1489. patchwork-settings-module?
  1490. (database-configuration patchwork-settings-module-database-configuration
  1491. (default (patchwork-database-configuration)))
  1492. (secret-key-file patchwork-settings-module-secret-key-file
  1493. (default "/etc/patchwork/django-secret-key"))
  1494. (allowed-hosts patchwork-settings-module-allowed-hosts)
  1495. (default-from-email patchwork-settings-module-default-from-email)
  1496. (static-url patchwork-settings-module-static-url
  1497. (default "/static/"))
  1498. (admins patchwork-settings-module-admins
  1499. (default '()))
  1500. (debug? patchwork-settings-module-debug?
  1501. (default #f))
  1502. (enable-rest-api? patchwork-settings-module-enable-rest-api?
  1503. (default #t))
  1504. (enable-xmlrpc? patchwork-settings-module-enable-xmlrpc?
  1505. (default #t))
  1506. (force-https-links? patchwork-settings-module-force-https-links?
  1507. (default #t))
  1508. (extra-settings patchwork-settings-module-extra-settings
  1509. (default "")))
  1510. (define-record-type* <patchwork-configuration>
  1511. patchwork-configuration make-patchwork-configuration
  1512. patchwork-configuration?
  1513. (patchwork patchwork-configuration-patchwork
  1514. (default patchwork))
  1515. (domain patchwork-configuration-domain)
  1516. (settings-module patchwork-configuration-settings-module)
  1517. (static-path patchwork-configuration-static-url
  1518. (default "/static/"))
  1519. (getmail-retriever-config getmail-retriever-config))
  1520. ;; Django uses a Python module for configuration, so this compiler generates a
  1521. ;; Python module from the configuration record.
  1522. (define-gexp-compiler (patchwork-settings-module-compiler
  1523. (file <patchwork-settings-module>) system target)
  1524. (match file
  1525. (($ <patchwork-settings-module> database-configuration secret-key-file
  1526. allowed-hosts default-from-email
  1527. static-url admins debug? enable-rest-api?
  1528. enable-xmlrpc? force-https-links?
  1529. extra-configuration)
  1530. (gexp->derivation
  1531. "patchwork-settings"
  1532. (with-imported-modules '((guix build utils))
  1533. #~(let ((output #$output))
  1534. (define (create-__init__.py filename)
  1535. (call-with-output-file filename
  1536. (lambda (port) (display "" port))))
  1537. (use-modules (guix build utils)
  1538. (srfi srfi-1))
  1539. (mkdir-p (string-append output "/guix/patchwork"))
  1540. (create-__init__.py
  1541. (string-append output "/guix/__init__.py"))
  1542. (create-__init__.py
  1543. (string-append output "/guix/patchwork/__init__.py"))
  1544. (call-with-output-file
  1545. (string-append output "/guix/patchwork/settings.py")
  1546. (lambda (port)
  1547. (display
  1548. (string-append "from patchwork.settings.base import *
  1549. # Configuration from Guix
  1550. with open('" #$secret-key-file "') as f:
  1551. SECRET_KEY = f.read().strip()
  1552. ALLOWED_HOSTS = [
  1553. " #$(string-concatenate
  1554. (map (lambda (allowed-host)
  1555. (string-append " '" allowed-host "'\n"))
  1556. allowed-hosts))
  1557. "]
  1558. DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
  1559. DEFAULT_FROM_EMAIL = '" #$default-from-email "'
  1560. SERVER_EMAIL = DEFAULT_FROM_EMAIL
  1561. NOTIFICATION_FROM_EMAIL = DEFAULT_FROM_EMAIL
  1562. ADMINS = [
  1563. " #$(string-concatenate
  1564. (map (match-lambda
  1565. ((name email-address)
  1566. (string-append
  1567. "('" name "','" email-address "'),")))
  1568. admins))
  1569. "]
  1570. DEBUG = " #$(if debug? "True" "False") "
  1571. ENABLE_REST_API = " #$(if enable-rest-api? "True" "False") "
  1572. ENABLE_XMLRPC = " #$(if enable-xmlrpc? "True" "False") "
  1573. FORCE_HTTPS_LINKS = " #$(if force-https-links? "True" "False") "
  1574. DATABASES = {
  1575. 'default': {
  1576. " #$(match database-configuration
  1577. (($ <patchwork-database-configuration>
  1578. engine name user password host port)
  1579. (string-append
  1580. " 'ENGINE': '" engine "',\n"
  1581. " 'NAME': '" name "',\n"
  1582. " 'USER': '" user "',\n"
  1583. " 'PASSWORD': '" password "',\n"
  1584. " 'HOST': '" host "',\n"
  1585. " 'PORT': '" port "',\n"))) "
  1586. },
  1587. }
  1588. " #$(if debug?
  1589. #~(string-append "STATIC_ROOT = '"
  1590. #$(file-append patchwork "/share/patchwork/htdocs")
  1591. "'")
  1592. #~(string-append "STATIC_URL = '" #$static-url "'")) "
  1593. STATICFILES_STORAGE = (
  1594. 'django.contrib.staticfiles.storage.StaticFilesStorage'
  1595. )
  1596. # Guix Extra Configuration
  1597. " #$extra-configuration "
  1598. ") port)))
  1599. #t))
  1600. #:local-build? #t))))
  1601. (define patchwork-virtualhost
  1602. (match-lambda
  1603. (($ <patchwork-configuration> patchwork domain
  1604. settings-module static-path
  1605. getmail-retriever-config)
  1606. (define wsgi.py
  1607. (file-append patchwork
  1608. (string-append
  1609. "/lib/python"
  1610. (version-major+minor
  1611. (package-version python))
  1612. "/site-packages/patchwork/wsgi.py")))
  1613. (httpd-virtualhost
  1614. "*:8080"
  1615. `("ServerAdmin admin@example.com`
  1616. ServerName " ,domain "
  1617. LogFormat \"%v %h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\"\" customformat
  1618. LogLevel info
  1619. CustomLog \"/var/log/httpd/" ,domain "-access_log\" customformat
  1620. ErrorLog /var/log/httpd/error.log
  1621. WSGIScriptAlias / " ,wsgi.py "
  1622. WSGIDaemonProcess " ,(package-name patchwork) " user=httpd group=httpd processes=1 threads=2 display-name=%{GROUP} lang='en_US.UTF-8' locale='en_US.UTF-8' python-path=" ,settings-module "
  1623. WSGIProcessGroup " ,(package-name patchwork) "
  1624. WSGIPassAuthorization On
  1625. <Files " ,wsgi.py ">
  1626. Require all granted
  1627. </Files>
  1628. " ,@(if static-path
  1629. `("Alias " ,static-path " " ,patchwork "/share/patchwork/htdocs/")
  1630. '())
  1631. "
  1632. <Directory \"/srv/http/" ,domain "/\">
  1633. AllowOverride None
  1634. Options MultiViews Indexes SymlinksIfOwnerMatch IncludesNoExec
  1635. Require method GET POST OPTIONS
  1636. </Directory>")))))
  1637. (define (patchwork-httpd-configuration patchwork-configuration)
  1638. (list "WSGISocketPrefix /var/run/mod_wsgi"
  1639. (list "LoadModule wsgi_module "
  1640. (file-append mod-wsgi "/modules/mod_wsgi.so"))
  1641. (patchwork-virtualhost patchwork-configuration)))
  1642. (define (patchwork-django-admin-gexp patchwork settings-module)
  1643. #~(lambda command
  1644. (let ((pid (primitive-fork))
  1645. (user (getpwnam "httpd")))
  1646. (if (eq? pid 0)
  1647. (dynamic-wind
  1648. (const #t)
  1649. (lambda ()
  1650. (setgid (passwd:gid user))
  1651. (setuid (passwd:uid user))
  1652. (setenv "DJANGO_SETTINGS_MODULE" "guix.patchwork.settings")
  1653. (setenv "PYTHONPATH" #$settings-module)
  1654. (primitive-exit
  1655. (if (zero?
  1656. (apply system*
  1657. #$(file-append patchwork "/bin/patchwork-admin")
  1658. command))
  1659. 0
  1660. 1)))
  1661. (lambda ()
  1662. (primitive-exit 1)))
  1663. (zero? (cdr (waitpid pid)))))))
  1664. (define (patchwork-django-admin-action patchwork settings-module)
  1665. (shepherd-action
  1666. (name 'django-admin)
  1667. (documentation
  1668. "Run a django admin command for patchwork")
  1669. (procedure (patchwork-django-admin-gexp patchwork settings-module))))
  1670. (define patchwork-shepherd-services
  1671. (match-lambda
  1672. (($ <patchwork-configuration> patchwork domain
  1673. settings-module static-path
  1674. getmail-retriever-config)
  1675. (define secret-key-file-creation-gexp
  1676. (if (patchwork-settings-module? settings-module)
  1677. (with-extensions (list guile-gcrypt)
  1678. #~(let ((secret-key-file
  1679. #$(patchwork-settings-module-secret-key-file
  1680. settings-module)))
  1681. (use-modules (guix build utils)
  1682. (gcrypt random))
  1683. (unless (file-exists? secret-key-file)
  1684. (mkdir-p (dirname secret-key-file))
  1685. (call-with-output-file secret-key-file
  1686. (lambda (port)
  1687. (display (random-token 30 'very-strong) port)))
  1688. (let* ((pw (getpwnam "httpd"))
  1689. (uid (passwd:uid pw))
  1690. (gid (passwd:gid pw)))
  1691. (chown secret-key-file uid gid)
  1692. (chmod secret-key-file #o400)))))
  1693. #~()))
  1694. (list (shepherd-service
  1695. (requirement '(postgres))
  1696. (provision (list (string->symbol
  1697. (string-append (package-name patchwork)
  1698. "-setup"))))
  1699. (start
  1700. #~(lambda ()
  1701. (define run-django-admin-command
  1702. #$(patchwork-django-admin-gexp patchwork
  1703. settings-module))
  1704. #$secret-key-file-creation-gexp
  1705. (run-django-admin-command "migrate")))
  1706. (stop #~(const #f))
  1707. (actions
  1708. (list (patchwork-django-admin-action patchwork
  1709. settings-module)))
  1710. (respawn? #f)
  1711. (documentation "Setup Patchwork."))))))
  1712. (define patchwork-getmail-configs
  1713. (match-lambda
  1714. (($ <patchwork-configuration> patchwork domain
  1715. settings-module static-path
  1716. getmail-retriever-config)
  1717. (list
  1718. (getmail-configuration
  1719. (name (string->symbol (package-name patchwork)))
  1720. (user "httpd")
  1721. (directory (string-append
  1722. "/var/lib/getmail/" (package-name patchwork)))
  1723. (rcfile
  1724. (getmail-configuration-file
  1725. (retriever getmail-retriever-config)
  1726. (destination
  1727. (getmail-destination-configuration
  1728. (type "MDA_external")
  1729. (path (file-append patchwork "/bin/patchwork-admin"))
  1730. (extra-parameters
  1731. '((arguments . ("parsemail"))))))
  1732. (options
  1733. (getmail-options-configuration
  1734. (read-all #f)
  1735. (delivered-to #f)
  1736. (received #f)))))
  1737. (idle (assq-ref
  1738. (getmail-retriever-configuration-extra-parameters
  1739. getmail-retriever-config)
  1740. 'mailboxes))
  1741. (environment-variables
  1742. (list "DJANGO_SETTINGS_MODULE=guix.patchwork.settings"
  1743. #~(string-append "PYTHONPATH=" #$settings-module))))))))
  1744. (define patchwork-service-type
  1745. (service-type
  1746. (name 'patchwork-setup)
  1747. (extensions
  1748. (list (service-extension httpd-service-type
  1749. patchwork-httpd-configuration)
  1750. (service-extension shepherd-root-service-type
  1751. patchwork-shepherd-services)
  1752. (service-extension getmail-service-type
  1753. patchwork-getmail-configs)))
  1754. (description
  1755. "Patchwork patch tracking system.")))
  1756. ;;;
  1757. ;;; Mumi.
  1758. ;;;
  1759. (define-record-type* <mumi-configuration>
  1760. mumi-configuration make-mumi-configuration
  1761. mumi-configuration?
  1762. (mumi mumi-configuration-mumi (default mumi))
  1763. (mailer? mumi-configuration-mailer? (default #t))
  1764. (sender mumi-configuration-sender (default #f))
  1765. (smtp mumi-configuration-smtp (default #f)))
  1766. (define %mumi-activation
  1767. (with-imported-modules '((guix build utils))
  1768. #~(begin
  1769. (use-modules (guix build utils))
  1770. (mkdir-p "/var/mumi/db")
  1771. (mkdir-p "/var/mumi/mails")
  1772. (let* ((pw (getpwnam "mumi"))
  1773. (uid (passwd:uid pw))
  1774. (gid (passwd:gid pw)))
  1775. (chown "/var/mumi" uid gid)
  1776. (chown "/var/mumi/mails" uid gid)
  1777. (chown "/var/mumi/db" uid gid)))))
  1778. (define %mumi-accounts
  1779. (list (user-group (name "mumi") (system? #t))
  1780. (user-account
  1781. (name "mumi")
  1782. (group "mumi")
  1783. (system? #t)
  1784. (comment "Mumi web server")
  1785. (home-directory "/var/empty")
  1786. (shell (file-append shadow "/sbin/nologin")))))
  1787. (define %mumi-log "/var/log/mumi.log")
  1788. (define %mumi-mailer-log "/var/log/mumi.mailer.log")
  1789. (define %mumi-worker-log "/var/log/mumi.worker.log")
  1790. (define (mumi-shepherd-services config)
  1791. (define environment
  1792. #~(list "LC_ALL=en_US.utf8"
  1793. (string-append "GUIX_LOCPATH=" #$glibc-utf8-locales
  1794. "/lib/locale")))
  1795. (match config
  1796. (($ <mumi-configuration> mumi mailer? sender smtp)
  1797. (list (shepherd-service
  1798. (provision '(mumi))
  1799. (documentation "Mumi bug-tracking web interface.")
  1800. (requirement '(networking))
  1801. (start #~(make-forkexec-constructor
  1802. `(#$(file-append mumi "/bin/mumi") "web"
  1803. ,@(if #$mailer? '() '("--disable-mailer")))
  1804. #:environment-variables #$environment
  1805. #:user "mumi" #:group "mumi"
  1806. #:log-file #$%mumi-log))
  1807. (stop #~(make-kill-destructor)))
  1808. (shepherd-service
  1809. (provision '(mumi-worker))
  1810. (documentation "Mumi bug-tracking web interface database worker.")
  1811. (requirement '(networking))
  1812. (start #~(make-forkexec-constructor
  1813. '(#$(file-append mumi "/bin/mumi") "worker")
  1814. #:environment-variables #$environment
  1815. #:user "mumi" #:group "mumi"
  1816. #:log-file #$%mumi-worker-log))
  1817. (stop #~(make-kill-destructor)))
  1818. (shepherd-service
  1819. (provision '(mumi-mailer))
  1820. (documentation "Mumi bug-tracking web interface mailer.")
  1821. (requirement '(networking))
  1822. (start #~(make-forkexec-constructor
  1823. `(#$(file-append mumi "/bin/mumi") "mailer"
  1824. ,@(if #$sender
  1825. (list (string-append "--sender=" #$sender))
  1826. '())
  1827. ,@(if #$smtp
  1828. (list (string-append "--smtp=" #$smtp))
  1829. '()))
  1830. #:environment-variables #$environment
  1831. #:user "mumi" #:group "mumi"
  1832. #:log-file #$%mumi-mailer-log))
  1833. (stop #~(make-kill-destructor)))))))
  1834. (define %mumi-log-rotations
  1835. (list (log-rotation
  1836. (files (list %mumi-log
  1837. %mumi-mailer-log
  1838. %mumi-worker-log)))))
  1839. (define mumi-service-type
  1840. (service-type
  1841. (name 'mumi)
  1842. (extensions
  1843. (list (service-extension activation-service-type
  1844. (const %mumi-activation))
  1845. (service-extension account-service-type
  1846. (const %mumi-accounts))
  1847. (service-extension shepherd-root-service-type
  1848. mumi-shepherd-services)
  1849. (service-extension rottlog-service-type
  1850. (const %mumi-log-rotations))))
  1851. (description
  1852. "Run Mumi, a Web interface to the Debbugs bug-tracking server.")
  1853. (default-value
  1854. (mumi-configuration))))
  1855. (define %default-gmnisrv-config-file
  1856. (plain-file "gmnisrv.ini" "
  1857. listen=0.0.0.0:1965 [::]:1965
  1858. [:tls]
  1859. store=/var/lib/gemini/certs
  1860. organization=gmnisrv on Guix user
  1861. [localhost]
  1862. root=/srv/gemini
  1863. "))
  1864. (define-record-type* <gmnisrv-configuration>
  1865. gmnisrv-configuration make-gmnisrv-configuration
  1866. gmnisrv-configuration?
  1867. (package gmnisrv-configuration-package
  1868. (default gmnisrv))
  1869. (config-file gmnisrv-configuration-config-file
  1870. (default %default-gmnisrv-config-file)))
  1871. (define gmnisrv-shepherd-service
  1872. (match-lambda
  1873. (($ <gmnisrv-configuration> package config-file)
  1874. (list (shepherd-service
  1875. (provision '(gmnisrv))
  1876. (requirement '(networking))
  1877. (documentation "Run the gmnisrv Gemini server.")
  1878. (start (let ((gmnisrv (file-append package "/bin/gmnisrv")))
  1879. #~(make-forkexec-constructor
  1880. (list #$gmnisrv "-C" #$config-file)
  1881. #:user "gmnisrv" #:group "gmnisrv"
  1882. #:log-file "/var/log/gmnisrv.log")))
  1883. (stop #~(make-kill-destructor)))))))
  1884. (define %gmnisrv-accounts
  1885. (list (user-group (name "gmnisrv") (system? #t))
  1886. (user-account
  1887. (name "gmnisrv")
  1888. (group "gmnisrv")
  1889. (system? #t)
  1890. (comment "gmnisrv Gemini server")
  1891. (home-directory "/var/empty")
  1892. (shell (file-append shadow "/sbin/nologin")))))
  1893. (define %gmnisrv-activation
  1894. (with-imported-modules '((guix build utils))
  1895. #~(begin
  1896. (use-modules (guix build utils))
  1897. (mkdir-p "/var/lib/gemini/certs")
  1898. (let* ((pw (getpwnam "gmnisrv"))
  1899. (uid (passwd:uid pw))
  1900. (gid (passwd:gid pw)))
  1901. (chown "/var/lib/gemini" uid gid)
  1902. (chown "/var/lib/gemini/certs" uid gid)))))
  1903. (define gmnisrv-service-type
  1904. (service-type
  1905. (name 'guix)
  1906. (extensions
  1907. (list (service-extension activation-service-type
  1908. (const %gmnisrv-activation))
  1909. (service-extension account-service-type
  1910. (const %gmnisrv-accounts))
  1911. (service-extension shepherd-root-service-type
  1912. gmnisrv-shepherd-service)))
  1913. (description
  1914. "Run the gmnisrv Gemini server.")
  1915. (default-value
  1916. (gmnisrv-configuration))))
  1917. (define-record-type* <agate-configuration>
  1918. agate-configuration make-agate-configuration
  1919. agate-configuration?
  1920. (package agate-configuration-package
  1921. (default agate))
  1922. (content agate-configuration-content
  1923. (default "/srv/gemini"))
  1924. (cert agate-configuration-cert
  1925. (default #f))
  1926. (key agate-configuration-key
  1927. (default #f))
  1928. (addr agate-configuration-addr
  1929. (default '("0.0.0.0:1965" "[::]:1965")))
  1930. (hostname agate-configuration-hostname
  1931. (default #f))
  1932. (lang agate-configuration-lang
  1933. (default #f))
  1934. (silent? agate-configuration-silent
  1935. (default #f))
  1936. (serve-secret? agate-configuration-serve-secret
  1937. (default #f))
  1938. (log-ip? agate-configuration-log-ip
  1939. (default #t))
  1940. (user agate-configuration-user
  1941. (default "agate"))
  1942. (group agate-configuration-group
  1943. (default "agate"))
  1944. (log-file agate-configuration-log
  1945. (default "/var/log/agate.log")))
  1946. (define agate-shepherd-service
  1947. (match-lambda
  1948. (($ <agate-configuration> package content cert key addr
  1949. hostname lang silent? serve-secret?
  1950. log-ip? user group log-file)
  1951. (list (shepherd-service
  1952. (provision '(agate))
  1953. (requirement '(networking))
  1954. (documentation "Run the agate Gemini server.")
  1955. (start (let ((agate (file-append package "/bin/agate")))
  1956. #~(make-forkexec-constructor
  1957. (list #$agate
  1958. "--content" #$content
  1959. "--cert" #$cert
  1960. "--key" #$key
  1961. "--addr" #$@addr
  1962. #$@(if lang
  1963. (list "--lang" lang)
  1964. '())
  1965. #$@(if hostname
  1966. (list "--hostname" hostname)
  1967. '())
  1968. #$@(if silent? '("--silent") '())
  1969. #$@(if serve-secret? '("--serve-secret") '())
  1970. #$@(if log-ip? '("--log-ip") '()))
  1971. #:user #$user #:group #$group
  1972. #:log-file #$log-file)))
  1973. (stop #~(make-kill-destructor)))))))
  1974. (define agate-accounts
  1975. (lambda (config)
  1976. (let ((group (agate-configuration-group config))
  1977. (user (agate-configuration-user config)))
  1978. `(,@(if (equal? group "agate")
  1979. '()
  1980. (list (user-group (name "agate") (system? #t))))
  1981. ,(user-group
  1982. (name group)
  1983. (system? #t))
  1984. ,(user-account
  1985. (name user)
  1986. (group group)
  1987. (supplementary-groups '("agate"))
  1988. (system? #t)
  1989. (comment "agate server user")
  1990. (home-directory "/var/empty")
  1991. (shell (file-append shadow "/sbin/nologin")))))))
  1992. (define agate-service-type
  1993. (service-type
  1994. (name 'agate)
  1995. (extensions
  1996. (list (service-extension account-service-type
  1997. agate-accounts)
  1998. (service-extension shepherd-root-service-type
  1999. agate-shepherd-service)))
  2000. (default-value (agate-configuration))
  2001. (description "Run Agate, a simple Gemini protocol server written in
  2002. Rust.")))