web.scm 77 KB

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