web.scm 70 KB

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