web.scm 79 KB

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