| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | |
| 37 | |
| 38 | |
| 39 |
|
| 40 | (define-module (gnu services web)
|
| 41 | #:use-module (gnu services)
|
| 42 | #:use-module (gnu services shepherd)
|
| 43 | #:use-module (gnu services admin)
|
| 44 | #:use-module (gnu services configuration)
|
| 45 | #:use-module (gnu services databases)
|
| 46 | #:use-module (gnu services getmail)
|
| 47 | #:use-module (gnu services mail)
|
| 48 | #:use-module (gnu system file-systems)
|
| 49 | #:use-module (gnu system pam)
|
| 50 | #:use-module (gnu system shadow)
|
| 51 | #:use-module (gnu packages admin)
|
| 52 | #:use-module (gnu packages base)
|
| 53 | #:use-module (gnu packages databases)
|
| 54 | #:use-module (gnu packages web)
|
| 55 | #:use-module (gnu packages patchutils)
|
| 56 | #:use-module (gnu packages php)
|
| 57 | #:use-module (gnu packages python)
|
| 58 | #:use-module (gnu packages python-web)
|
| 59 | #:use-module (gnu packages rsync)
|
| 60 | #:use-module (gnu packages gnupg)
|
| 61 | #:use-module (gnu packages golang-xyz)
|
| 62 | #:use-module (gnu packages guile)
|
| 63 | #:use-module (gnu packages logging)
|
| 64 | #:use-module (gnu packages mail)
|
| 65 | #:use-module (gnu packages rust-apps)
|
| 66 | #:autoload (guix i18n) (G_)
|
| 67 | #:autoload (gnu build linux-container) (%namespaces)
|
| 68 | #:use-module (guix diagnostics)
|
| 69 | #:use-module (guix gexp)
|
| 70 | #:use-module (guix least-authority)
|
| 71 | #:use-module (guix modules)
|
| 72 | #:use-module (guix packages)
|
| 73 | #:use-module (guix profiles)
|
| 74 | #:use-module (guix records)
|
| 75 | #:use-module (guix search-paths)
|
| 76 | #:use-module (guix utils)
|
| 77 | #:use-module ((guix store) #:select (text-file))
|
| 78 | #:use-module ((guix utils) #:select (version-major))
|
| 79 | #:use-module ((guix packages) #:select (package-version))
|
| 80 | #:use-module (srfi srfi-1)
|
| 81 | #:use-module (srfi srfi-9)
|
| 82 | #:use-module (srfi srfi-26)
|
| 83 | #:use-module (srfi srfi-34)
|
| 84 | #:use-module (ice-9 match)
|
| 85 | #:use-module (ice-9 format)
|
| 86 | #:use-module (ice-9 regex)
|
| 87 | #:use-module (web uri)
|
| 88 | #:export (httpd-configuration
|
| 89 | httpd-configuration?
|
| 90 | httpd-configuration-package
|
| 91 | httpd-configuration-pid-file
|
| 92 | httpd-configuration-config
|
| 93 |
|
| 94 | httpd-virtualhost
|
| 95 | httpd-virtualhost?
|
| 96 | httpd-virtualhost-addresses-and-ports
|
| 97 | httpd-virtualhost-contents
|
| 98 |
|
| 99 | httpd-config-file
|
| 100 | httpd-config-file?
|
| 101 | httpd-config-file-modules
|
| 102 | httpd-config-file-server-root
|
| 103 | httpd-config-file-server-name
|
| 104 | httpd-config-file-listen
|
| 105 | httpd-config-file-pid-file
|
| 106 | httpd-config-file-error-log
|
| 107 | httpd-config-file-user
|
| 108 | httpd-config-file-group
|
| 109 |
|
| 110 | httpd-module
|
| 111 | httpd-module?
|
| 112 | %default-httpd-modules
|
| 113 |
|
| 114 | httpd-service-type
|
| 115 |
|
| 116 | nginx-configuration
|
| 117 | nginx-configuration?
|
| 118 | nginx-configuration-nginx
|
| 119 | nginx-configuration-shepherd-requirement
|
| 120 | nginx-configuration-log-directory
|
| 121 | nginx-configuration-log-format
|
| 122 | nginx-configuration-log-formats
|
| 123 | nginx-configuration-log-level
|
| 124 | nginx-configuration-run-directory
|
| 125 | nginx-configuration-server-blocks
|
| 126 | nginx-configuration-upstream-blocks
|
| 127 | nginx-configuration-server-names-hash-bucket-size
|
| 128 | nginx-configuration-server-names-hash-bucket-max-size
|
| 129 | nginx-configuration-stream
|
| 130 | nginx-configuration-modules
|
| 131 | nginx-configuration-global-directives
|
| 132 | nginx-configuration-extra-content
|
| 133 | nginx-configuration-file
|
| 134 |
|
| 135 | nginx-log-format-configuration
|
| 136 | nginx-log-format-configuration?
|
| 137 | nginx-log-format-configuration-name
|
| 138 | nginx-log-format-configuration-escape
|
| 139 | nginx-log-format-configuration-format
|
| 140 |
|
| 141 | nginx-server-configuration
|
| 142 | nginx-server-configuration?
|
| 143 | nginx-server-configuration-listen
|
| 144 | nginx-server-configuration-server-name
|
| 145 | nginx-server-configuration-root
|
| 146 | nginx-server-configuration-locations
|
| 147 | nginx-server-configuration-index
|
| 148 | nginx-server-configuration-try-files
|
| 149 | nginx-server-configuration-ssl-certificate
|
| 150 | nginx-server-configuration-ssl-certificate-key
|
| 151 | nginx-server-configuration-server-tokens?
|
| 152 | nginx-server-configuration-raw-content
|
| 153 |
|
| 154 | nginx-upstream-configuration
|
| 155 | nginx-upstream-configuration?
|
| 156 | nginx-upstream-configuration-name
|
| 157 | nginx-upstream-configuration-servers
|
| 158 | nginx-upstream-configuration-extra-content
|
| 159 |
|
| 160 | nginx-location-configuration
|
| 161 | nginx-location-configuration?
|
| 162 | nginx-location-configuration-uri
|
| 163 | nginx-location-configuration-body
|
| 164 |
|
| 165 | nginx-named-location-configuration
|
| 166 | nginx-named-location-configuration?
|
| 167 | nginx-named-location-configuration-name
|
| 168 | nginx-named-location-configuration-body
|
| 169 |
|
| 170 | nginx-stream-configuration
|
| 171 | nginx-stream-configuration-server-blocks
|
| 172 | nginx-stream-configuraiton-upstream-blocks
|
| 173 | nginx-stream-configuration-extra-content
|
| 174 |
|
| 175 | nginx-service
|
| 176 | nginx-service-type
|
| 177 |
|
| 178 | gunicorn-app
|
| 179 | gunicorn-app-environment-variables
|
| 180 | gunicorn-app-extra-cli-arguments
|
| 181 | gunicorn-app-group
|
| 182 | gunicorn-app-mappings
|
| 183 | gunicorn-app-name
|
| 184 | gunicorn-app-package
|
| 185 | gunicorn-app-control-socket
|
| 186 | gunicorn-app-sockets
|
| 187 | gunicorn-app-timeout
|
| 188 | gunicorn-app-user
|
| 189 | gunicorn-app-workers
|
| 190 | gunicorn-app-wsgi-app-module
|
| 191 | gunicorn-app?
|
| 192 | gunicorn-configuration
|
| 193 | gunicorn-configuration-apps
|
| 194 | gunicorn-configuration-package
|
| 195 | gunicorn-configuration?
|
| 196 | gunicorn-service-type
|
| 197 |
|
| 198 | fcgiwrap-configuration
|
| 199 | fcgiwrap-configuration?
|
| 200 | fcgiwrap-service-type
|
| 201 |
|
| 202 | php-fpm-configuration
|
| 203 | make-php-fpm-configuration
|
| 204 | php-fpm-configuration?
|
| 205 | php-fpm-configuration-php
|
| 206 | php-fpm-configuration-socket
|
| 207 | php-fpm-configuration-user
|
| 208 | php-fpm-configuration-group
|
| 209 | php-fpm-configuration-socket-user
|
| 210 | php-fpm-configuration-socket-group
|
| 211 | php-fpm-configuration-pid-file
|
| 212 | php-fpm-configuration-log-file
|
| 213 | php-fpm-configuration-process-manager
|
| 214 | php-fpm-configuration-display-errors
|
| 215 | php-fpm-configuration-timezone
|
| 216 | php-fpm-configuration-workers-log-file
|
| 217 | php-fpm-configuration-file
|
| 218 | php-fpm-configuration-php-ini-file
|
| 219 |
|
| 220 | php-fpm-dynamic-process-manager-configuration
|
| 221 | make-php-fpm-dynamic-process-manager-configuration
|
| 222 | php-fpm-dynamic-process-manager-configuration?
|
| 223 | php-fpm-dynamic-process-manager-configuration-max-children
|
| 224 | php-fpm-dynamic-process-manager-configuration-start-servers
|
| 225 | php-fpm-dynamic-process-manager-configuration-min-spare-servers
|
| 226 | php-fpm-dynamic-process-manager-configuration-max-spare-servers
|
| 227 |
|
| 228 | php-fpm-static-process-manager-configuration
|
| 229 | make-php-fpm-static-process-manager-configuration
|
| 230 | php-fpm-static-process-manager-configuration?
|
| 231 | php-fpm-static-process-manager-configuration-max-children
|
| 232 |
|
| 233 | php-fpm-on-demand-process-manager-configuration
|
| 234 | make-php-fpm-on-demand-process-manager-configuration
|
| 235 | php-fpm-on-demand-process-manager-configuration?
|
| 236 | php-fpm-on-demand-process-manager-configuration-max-children
|
| 237 | php-fpm-on-demand-process-manager-configuration-process-idle-timeout
|
| 238 |
|
| 239 | php-fpm-service-type
|
| 240 | nginx-php-location
|
| 241 |
|
| 242 | cat-avatar-generator-service
|
| 243 |
|
| 244 | hpcguix-web-configuration
|
| 245 | hpcguix-web-configuration?
|
| 246 | hpcguix-web-service-type
|
| 247 |
|
| 248 | anonip-configuration
|
| 249 | anonip-configuration?
|
| 250 | anonip-configuration-anonip
|
| 251 | anonip-configuration-input
|
| 252 | anonip-configuration-output
|
| 253 | anonip-configuration-debug?
|
| 254 | anonip-configuration-skip-private?
|
| 255 | anonip-configuration-column
|
| 256 | anonip-configuration-replacement
|
| 257 | anonip-configuration-ipv4mask
|
| 258 | anonip-configuration-ipv6mask
|
| 259 | anonip-configuration-increment
|
| 260 | anonip-configuration-delimiter
|
| 261 | anonip-configuration-regex
|
| 262 | anonip-service-type
|
| 263 |
|
| 264 | varnish-configuration
|
| 265 | varnish-configuration?
|
| 266 | varnish-configuration-package
|
| 267 | varnish-configuration-name
|
| 268 | varnish-configuration-backend
|
| 269 | varnish-configuration-vcl
|
| 270 | varnish-configuration-listen
|
| 271 | varnish-configuration-storage
|
| 272 | varnish-configuration-parameters
|
| 273 | varnish-configuration-extra-options
|
| 274 |
|
| 275 | varnish-service-type
|
| 276 |
|
| 277 | whoogle-service-type
|
| 278 | whoogle-configuration
|
| 279 | whoogle-configuration-package
|
| 280 | whoogle-configuration-host
|
| 281 | whoogle-configuration-port
|
| 282 | whoogle-configuration-environment-variables
|
| 283 |
|
| 284 | go-webdav-service-type
|
| 285 |
|
| 286 | patchwork-database-configuration
|
| 287 | patchwork-database-configuration?
|
| 288 | patchwork-database-configuration-engine
|
| 289 | patchwork-database-configuration-name
|
| 290 | patchwork-database-configuration-user
|
| 291 | patchwork-database-configuration-password
|
| 292 | patchwork-database-configuration-host
|
| 293 | patchwork-database-configuration-port
|
| 294 |
|
| 295 | patchwork-settings-module
|
| 296 | patchwork-settings-module?
|
| 297 | patchwork-settings-module-database-configuration
|
| 298 | patchwork-settings-module-secret-key
|
| 299 | patchwork-settings-module-allowed-hosts
|
| 300 | patchwork-settings-module-default-from-email
|
| 301 | patchwork-settings-module-static-url
|
| 302 | patchwork-settings-module-admins
|
| 303 | patchwork-settings-module-debug?
|
| 304 | patchwork-settings-module-enable-rest-api?
|
| 305 | patchwork-settings-module-enable-xmlrpc?
|
| 306 | patchwork-settings-module-force-https-links?
|
| 307 | patchwork-settings-module-extra-settings
|
| 308 |
|
| 309 | patchwork-configuration
|
| 310 | patchwork-configuration?
|
| 311 | patchwork-configuration-patchwork
|
| 312 | patchwork-configuration-settings-module
|
| 313 | patchwork-configuration-domain
|
| 314 |
|
| 315 | patchwork-virtualhost
|
| 316 | patchwork-service-type
|
| 317 |
|
| 318 | sogogi-service-type
|
| 319 | sogogi-configuration
|
| 320 | sogogi-config-file
|
| 321 | sogogi-configuration?
|
| 322 | sogogi-user
|
| 323 | sogogi-user?
|
| 324 | sogogi-location
|
| 325 | sogogi-location?
|
| 326 |
|
| 327 | mumi-configuration
|
| 328 | mumi-configuration?
|
| 329 | mumi-configuration-mumi
|
| 330 | mumi-configuration-data-directory
|
| 331 | mumi-configuration-rsync-remote
|
| 332 | mumi-configuration-rsync-flags
|
| 333 | mumi-configuration-rsync-and-index-event
|
| 334 | mumi-configuration-mailer?
|
| 335 | mumi-configuration-sender
|
| 336 | mumi-configuration-smtp
|
| 337 | mumi-configuration-packages
|
| 338 |
|
| 339 | mumi-package-configuration
|
| 340 | mumi-package-configuration?
|
| 341 | mumi-package-configuration-name
|
| 342 | mumi-package-configuration-display-name
|
| 343 | mumi-package-configuration-debbugs-packages
|
| 344 | mumi-package-configuration-bug-email-address
|
| 345 | mumi-package-configuration-patch-email-address
|
| 346 | mumi-package-configuration-file-tags
|
| 347 |
|
| 348 | mumi-service-type
|
| 349 |
|
| 350 | gmnisrv-configuration
|
| 351 | gmnisrv-configuration?
|
| 352 | gmnisrv-configuration-package
|
| 353 | gmnisrv-configuration-config-file
|
| 354 |
|
| 355 | gmnisrv-service-type
|
| 356 |
|
| 357 | agate-configuration
|
| 358 | agate-configuration?
|
| 359 | agate-configuration-package
|
| 360 | agate-configuration-content
|
| 361 | agate-configuration-certs
|
| 362 | agate-configuration-addr
|
| 363 | agate-configuration-hostname
|
| 364 | agate-configuration-lang
|
| 365 | agate-configuration-only-tls13
|
| 366 | agate-configuration-serve-secret
|
| 367 | agate-configuration-central-conf
|
| 368 | agate-configuration-ed25519
|
| 369 | agate-configuration-skip-port-check
|
| 370 | agate-configuration-log-ip
|
| 371 | agate-configuration-user
|
| 372 | agate-configuration-group
|
| 373 | agate-configuration-log-file
|
| 374 |
|
| 375 | agate-service-type
|
| 376 |
|
| 377 | miniflux-configuration
|
| 378 | miniflux-configuration?
|
| 379 | miniflux-configuration-listen-address
|
| 380 | miniflux-configuration-base-url
|
| 381 | miniflux-configuration-create-administrator-account?
|
| 382 | miniflux-configuration-administrator-account-name
|
| 383 | miniflux-configuration-administrator-account-password
|
| 384 | miniflux-configuration-run-migrations?
|
| 385 | miniflux-configuration-database-url
|
| 386 | miniflux-configuration-user
|
| 387 | miniflux-configuration-group
|
| 388 | miniflux-configuration-log-file
|
| 389 | miniflux-configuration-extra-settings
|
| 390 |
|
| 391 | miniflux-service-type))
|
| 392 |
|
| 393 | |
| 394 | |
| 395 | |
| 396 | |
| 397 | |
| 398 |
|
| 399 | (define-record-type* <httpd-module>
|
| 400 | httpd-module make-httpd-module
|
| 401 | httpd-module?
|
| 402 | (name httpd-load-module-name)
|
| 403 | (file httpd-load-module-file))
|
| 404 |
|
| 405 | |
| 406 | |
| 407 | (define %default-httpd-modules
|
| 408 | (map (match-lambda
|
| 409 | ((name file)
|
| 410 | (httpd-module
|
| 411 | (name name)
|
| 412 | (file file))))
|
| 413 | '(("authn_file_module" "modules/mod_authn_file.so")
|
| 414 | ("authn_core_module" "modules/mod_authn_core.so")
|
| 415 | ("authz_host_module" "modules/mod_authz_host.so")
|
| 416 | ("authz_groupfile_module" "modules/mod_authz_groupfile.so")
|
| 417 | ("authz_user_module" "modules/mod_authz_user.so")
|
| 418 | ("authz_core_module" "modules/mod_authz_core.so")
|
| 419 | ("access_compat_module" "modules/mod_access_compat.so")
|
| 420 | ("auth_basic_module" "modules/mod_auth_basic.so")
|
| 421 | ("reqtimeout_module" "modules/mod_reqtimeout.so")
|
| 422 | ("filter_module" "modules/mod_filter.so")
|
| 423 | ("mime_module" "modules/mod_mime.so")
|
| 424 | ("log_config_module" "modules/mod_log_config.so")
|
| 425 | ("env_module" "modules/mod_env.so")
|
| 426 | ("headers_module" "modules/mod_headers.so")
|
| 427 | ("setenvif_module" "modules/mod_setenvif.so")
|
| 428 | ("version_module" "modules/mod_version.so")
|
| 429 | ("unixd_module" "modules/mod_unixd.so")
|
| 430 | ("status_module" "modules/mod_status.so")
|
| 431 | ("autoindex_module" "modules/mod_autoindex.so")
|
| 432 | ("dir_module" "modules/mod_dir.so")
|
| 433 | ("alias_module" "modules/mod_alias.so"))))
|
| 434 |
|
| 435 | (define-record-type* <httpd-config-file>
|
| 436 | httpd-config-file make-httpd-config-file
|
| 437 | httpd-config-file?
|
| 438 | (modules httpd-config-file-modules
|
| 439 | (default %default-httpd-modules))
|
| 440 | (server-root httpd-config-file-server-root
|
| 441 | (default httpd))
|
| 442 | (server-name httpd-config-file-server-name
|
| 443 | (default #f))
|
| 444 | (document-root httpd-config-file-document-root
|
| 445 | (default "/srv/http"))
|
| 446 | (listen httpd-config-file-listen
|
| 447 | (default '("80")))
|
| 448 | (pid-file httpd-config-file-pid-file
|
| 449 | (default "/var/run/httpd"))
|
| 450 | (error-log httpd-config-file-error-log
|
| 451 | (default "/var/log/httpd/error_log"))
|
| 452 | (user httpd-config-file-user
|
| 453 | (default "httpd"))
|
| 454 | (group httpd-config-file-group
|
| 455 | (default "httpd"))
|
| 456 | (extra-config httpd-config-file-extra-config
|
| 457 | (default
|
| 458 | (list "TypesConfig etc/httpd/mime.types"))))
|
| 459 |
|
| 460 | (define-gexp-compiler (httpd-config-file-compiler
|
| 461 | (file <httpd-config-file>) system target)
|
| 462 | (match file
|
| 463 | (($ <httpd-config-file> load-modules server-root server-name
|
| 464 | document-root listen pid-file error-log
|
| 465 | user group extra-config)
|
| 466 | (gexp->derivation
|
| 467 | "httpd.conf"
|
| 468 | #~(call-with-output-file (ungexp output "out")
|
| 469 | (lambda (port)
|
| 470 | (display
|
| 471 | (string-append
|
| 472 | (ungexp-splicing
|
| 473 | `(,@(append-map
|
| 474 | (match-lambda
|
| 475 | (($ <httpd-module> name module)
|
| 476 | `("LoadModule " ,name " " ,module "\n")))
|
| 477 | load-modules)
|
| 478 | ,@`("ServerRoot " ,server-root "\n")
|
| 479 | ,@(if server-name
|
| 480 | `("ServerName " ,server-name "\n")
|
| 481 | '())
|
| 482 | ,@`("DocumentRoot " ,document-root "\n")
|
| 483 | ,@(append-map
|
| 484 | (lambda (listen-value)
|
| 485 | `("Listen " ,listen-value "\n"))
|
| 486 | listen)
|
| 487 | ,@(if pid-file
|
| 488 | `("Pidfile " ,pid-file "\n")
|
| 489 | '())
|
| 490 | ,@(if error-log
|
| 491 | `("ErrorLog " ,error-log "\n")
|
| 492 | '())
|
| 493 | ,@(if user
|
| 494 | `("User " ,user "\n")
|
| 495 | '())
|
| 496 | ,@(if group
|
| 497 | `("Group " ,group "\n")
|
| 498 | '())
|
| 499 | "\n\n"
|
| 500 | ,@extra-config)))
|
| 501 | port)))
|
| 502 | #:local-build? #t))))
|
| 503 |
|
| 504 | (define-record-type <httpd-virtualhost>
|
| 505 | (httpd-virtualhost addresses-and-ports contents)
|
| 506 | httpd-virtualhost?
|
| 507 | (addresses-and-ports httpd-virtualhost-addresses-and-ports)
|
| 508 | (contents httpd-virtualhost-contents))
|
| 509 |
|
| 510 | (define-record-type* <httpd-configuration>
|
| 511 | httpd-configuration make-httpd-configuration
|
| 512 | httpd-configuration?
|
| 513 | (package httpd-configuration-package
|
| 514 | (default httpd))
|
| 515 | (pid-file httpd-configuration-pid-file
|
| 516 | (default "/var/run/httpd"))
|
| 517 | (config httpd-configuration-config
|
| 518 | (default (httpd-config-file))))
|
| 519 |
|
| 520 | (define %httpd-accounts
|
| 521 | (list (user-group (name "httpd") (system? #t))
|
| 522 | (user-account
|
| 523 | (name "httpd")
|
| 524 | (group "httpd")
|
| 525 | (system? #t)
|
| 526 | (comment "Apache HTTPD server user")
|
| 527 | (home-directory "/var/empty")
|
| 528 | (shell (file-append shadow "/sbin/nologin")))))
|
| 529 |
|
| 530 | (define httpd-shepherd-services
|
| 531 | (match-lambda
|
| 532 | (($ <httpd-configuration> package pid-file config)
|
| 533 | (list (shepherd-service
|
| 534 | (provision '(httpd))
|
| 535 | (documentation "The Apache HTTP Server")
|
| 536 | (requirement '(user-processes networking))
|
| 537 | (start #~(make-forkexec-constructor
|
| 538 | `(#$(file-append package "/bin/httpd")
|
| 539 | #$@(if config
|
| 540 | (list "-f" config)
|
| 541 | '()))
|
| 542 | #:pid-file #$pid-file))
|
| 543 | (stop #~(make-kill-destructor)))))))
|
| 544 |
|
| 545 | (define httpd-activation
|
| 546 | (match-lambda
|
| 547 | (($ <httpd-configuration> package pid-file config)
|
| 548 | (match-record
|
| 549 | config
|
| 550 | <httpd-config-file>
|
| 551 | (error-log document-root)
|
| 552 | #~(begin
|
| 553 | (use-modules (guix build utils))
|
| 554 |
|
| 555 | (mkdir-p #$(dirname error-log))
|
| 556 | (mkdir-p #$document-root))))))
|
| 557 |
|
| 558 | (define (httpd-process-extensions original-config extension-configs)
|
| 559 | (let ((config (httpd-configuration-config
|
| 560 | original-config)))
|
| 561 | (if (httpd-config-file? config)
|
| 562 | (httpd-configuration
|
| 563 | (inherit original-config)
|
| 564 | (config
|
| 565 | (httpd-config-file
|
| 566 | (inherit config)
|
| 567 | (extra-config
|
| 568 | (append (httpd-config-file-extra-config config)
|
| 569 | (append-map
|
| 570 | (match-lambda
|
| 571 | (($ <httpd-virtualhost>
|
| 572 | addresses-and-ports
|
| 573 | contents)
|
| 574 | `(,(string-append
|
| 575 | "\n<VirtualHost " addresses-and-ports ">\n")
|
| 576 | ,@contents
|
| 577 | "\n</VirtualHost>\n"))
|
| 578 | ((? string? x)
|
| 579 | `("\n" ,x "\n"))
|
| 580 | ((? list? x)
|
| 581 | `("\n" ,@x "\n")))
|
| 582 | extension-configs)))))))))
|
| 583 |
|
| 584 | (define httpd-service-type
|
| 585 | (service-type (name 'httpd)
|
| 586 | (extensions
|
| 587 | (list (service-extension shepherd-root-service-type
|
| 588 | httpd-shepherd-services)
|
| 589 | (service-extension activation-service-type
|
| 590 | httpd-activation)
|
| 591 | (service-extension account-service-type
|
| 592 | (const %httpd-accounts))))
|
| 593 | (compose concatenate)
|
| 594 | (extend httpd-process-extensions)
|
| 595 | (default-value
|
| 596 | (httpd-configuration))
|
| 597 | (description "Run the Apache httpd Web server.")))
|
| 598 |
|
| 599 | (define-record-type* <nginx-log-format-configuration>
|
| 600 | nginx-log-format-configuration make-nginx-log-format-configuration
|
| 601 | nginx-log-format-configuration?
|
| 602 | (name nginx-log-format-configuration-name)
|
| 603 | (escape nginx-log-format-configuration-escape
|
| 604 | (sanitize assert-valid-log-format-escape)
|
| 605 | (default 'default))
|
| 606 | (format nginx-log-format-configuration-format))
|
| 607 |
|
| 608 | (define (assert-valid-log-format-escape escape)
|
| 609 | "Ensure @var{escape} is one of @code{'default}, @code{'json}, or
|
| 610 | @code{'none}."
|
| 611 | (unless (memq escape '(default json none))
|
| 612 | (raise
|
| 613 | (formatted-message (G_ "unknown log format escape '~a'~%") escape)))
|
| 614 | escape)
|
| 615 |
|
| 616 | (define-record-type* <nginx-server-configuration>
|
| 617 | nginx-server-configuration make-nginx-server-configuration
|
| 618 | nginx-server-configuration?
|
| 619 | (listen nginx-server-configuration-listen
|
| 620 | (default '("80" "443 ssl")))
|
| 621 | (server-name nginx-server-configuration-server-name
|
| 622 | (default (list 'default)))
|
| 623 | (root nginx-server-configuration-root
|
| 624 | (default "/srv/http"))
|
| 625 | (locations nginx-server-configuration-locations
|
| 626 | (default '()))
|
| 627 | (index nginx-server-configuration-index
|
| 628 | (default (list "index.html")))
|
| 629 | (try-files nginx-server-configuration-try-files
|
| 630 | (default '()))
|
| 631 | (ssl-certificate nginx-server-configuration-ssl-certificate
|
| 632 | (default #f))
|
| 633 | (ssl-certificate-key nginx-server-configuration-ssl-certificate-key
|
| 634 | (default #f))
|
| 635 | (server-tokens? nginx-server-configuration-server-tokens?
|
| 636 | (default #f))
|
| 637 | (raw-content nginx-server-configuration-raw-content
|
| 638 | (default '())))
|
| 639 |
|
| 640 | (define-record-type* <nginx-upstream-configuration>
|
| 641 | nginx-upstream-configuration make-nginx-upstream-configuration
|
| 642 | nginx-upstream-configuration?
|
| 643 | (name nginx-upstream-configuration-name)
|
| 644 | (servers nginx-upstream-configuration-servers)
|
| 645 | (extra-content nginx-upstream-configuration-extra-content
|
| 646 | (default '())))
|
| 647 |
|
| 648 | (define-record-type* <nginx-location-configuration>
|
| 649 | nginx-location-configuration make-nginx-location-configuration
|
| 650 | nginx-location-configuration?
|
| 651 | (uri nginx-location-configuration-uri
|
| 652 | (default #f))
|
| 653 | (body nginx-location-configuration-body))
|
| 654 |
|
| 655 | (define-record-type* <nginx-named-location-configuration>
|
| 656 | nginx-named-location-configuration make-nginx-named-location-configuration
|
| 657 | nginx-named-location-configuration?
|
| 658 | (name nginx-named-location-configuration-name
|
| 659 | (default #f))
|
| 660 | (body nginx-named-location-configuration-body))
|
| 661 |
|
| 662 | (define-record-type* <nginx-stream-configuration>
|
| 663 | nginx-stream-configuration make-nginx-stream-configuration
|
| 664 | nginx-stream-configuration?
|
| 665 | (upstream-blocks nginx-stream-configuration-upstream-blocks
|
| 666 | (default '())) |
| 667 | (server-blocks nginx-stream-configuration-server-blocks
|
| 668 | (default '())) |
| 669 | (extra-content nginx-stream-configuration-extra-content
|
| 670 | (default '())))
|
| 671 |
|
| 672 | (define-record-type* <nginx-configuration>
|
| 673 | nginx-configuration make-nginx-configuration
|
| 674 | nginx-configuration?
|
| 675 | (nginx nginx-configuration-nginx |
| 676 | (default nginx))
|
| 677 | (shepherd-requirement nginx-configuration-shepherd-requirement
|
| 678 | (default '())) |
| 679 | (log-directory nginx-configuration-log-directory |
| 680 | (default "/var/log/nginx"))
|
| 681 | (log-level nginx-configuration-log-level
|
| 682 | (sanitize assert-valid-log-level)
|
| 683 | (default 'error))
|
| 684 | (log-format nginx-configuration-log-format |
| 685 | (default 'combined))
|
| 686 | (log-formats nginx-configuration-log-formats |
| 687 | (default '()))
|
| 688 | (run-directory nginx-configuration-run-directory |
| 689 | (default "/var/run/nginx"))
|
| 690 | (server-blocks nginx-configuration-server-blocks
|
| 691 | (default '())) |
| 692 | (upstream-blocks nginx-configuration-upstream-blocks
|
| 693 | (default '())) |
| 694 | (server-names-hash-bucket-size nginx-configuration-server-names-hash-bucket-size
|
| 695 | (default #f))
|
| 696 | (server-names-hash-bucket-max-size nginx-configuration-server-names-hash-bucket-max-size
|
| 697 | (default #f))
|
| 698 | (stream nginx-configuration-stream
|
| 699 | (default #f)) |
| 700 | (modules nginx-configuration-modules (default '()))
|
| 701 | (global-directives nginx-configuration-global-directives
|
| 702 | (default '((events . ()))))
|
| 703 | (lua-package-path nginx-lua-package-path |
| 704 | (default #f))
|
| 705 | (lua-package-cpath nginx-lua-package-cpath |
| 706 | (default #f))
|
| 707 | (extra-content nginx-configuration-extra-content
|
| 708 | (default ""))
|
| 709 | (file nginx-configuration-file |
| 710 | (default #f)))
|
| 711 |
|
| 712 | (define (assert-valid-log-level level)
|
| 713 | "Ensure @var{level} is one of @code{'debug}, @code{'info}, @code{'notice},
|
| 714 | @code{'warn}, @code{'error}, @code{'crit}, @code{'alert}, or @code{'emerg}."
|
| 715 | (unless (memq level '(debug info notice warn error crit alert emerg))
|
| 716 | (raise
|
| 717 | (formatted-message (G_ "unknown log level '~a'~%") level)))
|
| 718 | level)
|
| 719 |
|
| 720 | (define (config-domain-strings names)
|
| 721 | "Return a string denoting the nginx config representation of NAMES, a list
|
| 722 | of domain names."
|
| 723 | (map (match-lambda
|
| 724 | ('default "_ ")
|
| 725 | ((? string? str) (list str " ")))
|
| 726 | names))
|
| 727 |
|
| 728 | (define (config-index-strings names)
|
| 729 | "Return a string denoting the nginx config representation of NAMES, a list
|
| 730 | of index files."
|
| 731 | (map (match-lambda
|
| 732 | ((? string? str) (list str " ")))
|
| 733 | names))
|
| 734 |
|
| 735 | (define (emit-load-module module)
|
| 736 | (list "load_module " module ";\n"))
|
| 737 |
|
| 738 | (define emit-global-directive
|
| 739 | (match-lambda
|
| 740 | ((key . (? list? alist))
|
| 741 | (format #f "~a { ~{~a~}}~%" key (map emit-global-directive alist)))
|
| 742 | ((key . value)
|
| 743 | (format #f "~a ~a;~%" key value))))
|
| 744 |
|
| 745 | (define emit-nginx-log-format-config
|
| 746 | (match-lambda
|
| 747 | (($ <nginx-log-format-configuration> name escape format)
|
| 748 | (list " log_format " (symbol->string name) " escape="
|
| 749 | (symbol->string escape) " " format ";\n"))))
|
| 750 |
|
| 751 | (define emit-nginx-location-config
|
| 752 | (match-lambda
|
| 753 | (($ <nginx-location-configuration> uri body)
|
| 754 | (list
|
| 755 | " location " uri " {\n"
|
| 756 | (map (lambda (x) (list " " x "\n")) body)
|
| 757 | " }\n"))
|
| 758 | (($ <nginx-named-location-configuration> name body)
|
| 759 | (list
|
| 760 | " location @" name " {\n"
|
| 761 | (map (lambda (x) (list " " x "\n")) body)
|
| 762 | " }\n"))))
|
| 763 |
|
| 764 | (define* (emit-nginx-server-config server #:optional (context 'http))
|
| 765 | (let ((listen (nginx-server-configuration-listen server))
|
| 766 | (server-name (nginx-server-configuration-server-name server))
|
| 767 | (ssl-certificate (nginx-server-configuration-ssl-certificate server))
|
| 768 | (ssl-certificate-key
|
| 769 | (nginx-server-configuration-ssl-certificate-key server))
|
| 770 | (root (nginx-server-configuration-root server))
|
| 771 | (index (nginx-server-configuration-index server))
|
| 772 | (try-files (nginx-server-configuration-try-files server))
|
| 773 | (server-tokens? (nginx-server-configuration-server-tokens? server))
|
| 774 | (locations (nginx-server-configuration-locations server))
|
| 775 | (raw-content (nginx-server-configuration-raw-content server)))
|
| 776 | (define-syntax-parameter <> (syntax-rules ()))
|
| 777 | (define-syntax-rule (and/l x tail ...)
|
| 778 | (let ((x* x))
|
| 779 | (if x*
|
| 780 | (syntax-parameterize ((<> (identifier-syntax x*)))
|
| 781 | (list tail ...))
|
| 782 | '())))
|
| 783 | (list
|
| 784 | " server {\n"
|
| 785 | (map (lambda (directive) (list " listen " directive ";\n")) listen)
|
| 786 | " server_name " (config-domain-strings server-name) ";\n"
|
| 787 | (and/l ssl-certificate " ssl_certificate " <> ";\n")
|
| 788 | (and/l ssl-certificate-key " ssl_certificate_key " <> ";\n")
|
| 789 | (if (and (eq? context 'http)
|
| 790 | (not (equal? "" root)))
|
| 791 | (list " root " root ";\n")
|
| 792 | "")
|
| 793 | (if (and (eq? context 'http)
|
| 794 | (not (null? index)))
|
| 795 | (list " index " (config-index-strings index) ";\n")
|
| 796 | "")
|
| 797 | (if (not (nil? try-files))
|
| 798 | (and/l (config-index-strings try-files) " try_files " <> ";\n")
|
| 799 | "")
|
| 800 | (if (eq? context 'http)
|
| 801 | (list " server_tokens " (if server-tokens? "on" "off") ";\n")
|
| 802 | "")
|
| 803 | "\n"
|
| 804 | (map emit-nginx-location-config locations)
|
| 805 | "\n"
|
| 806 | (map (lambda (x) (list " " x "\n")) raw-content)
|
| 807 | " }\n")))
|
| 808 |
|
| 809 | (define (emit-nginx-upstream-config upstream)
|
| 810 | (list
|
| 811 | " upstream " (nginx-upstream-configuration-name upstream) " {\n"
|
| 812 | (map (lambda (server)
|
| 813 | (simple-format #f " server ~A;\n" server))
|
| 814 | (nginx-upstream-configuration-servers upstream))
|
| 815 | (let ((extra-content
|
| 816 | (nginx-upstream-configuration-extra-content upstream)))
|
| 817 | (if (and extra-content (not (null? extra-content)))
|
| 818 | (cons
|
| 819 | "\n"
|
| 820 | (map (lambda (line)
|
| 821 | `(" " ,line "\n"))
|
| 822 | (if (list? extra-content)
|
| 823 | extra-content
|
| 824 | (list extra-content))))
|
| 825 | '()))
|
| 826 | " }\n"))
|
| 827 |
|
| 828 | (define (flatten . lst)
|
| 829 | "Return a list that recursively concatenates all sub-lists of LST."
|
| 830 | (define (flatten1 head out)
|
| 831 | (if (list? head)
|
| 832 | (fold-right flatten1 out head)
|
| 833 | (cons head out)))
|
| 834 | (fold-right flatten1 '() lst))
|
| 835 |
|
| 836 | (define (nginx-access-log-file config)
|
| 837 | (string-append (nginx-configuration-log-directory config)
|
| 838 | "/access.log"))
|
| 839 |
|
| 840 | (define (nginx-error-log-file config)
|
| 841 | (string-append (nginx-configuration-log-directory config)
|
| 842 | "/error.log"))
|
| 843 |
|
| 844 | (define (default-nginx-config config)
|
| 845 | (match-record config
|
| 846 | <nginx-configuration>
|
| 847 | (nginx log-directory run-directory
|
| 848 | log-level log-format log-formats
|
| 849 | server-blocks upstream-blocks
|
| 850 | server-names-hash-bucket-size
|
| 851 | server-names-hash-bucket-max-size
|
| 852 | stream
|
| 853 | modules
|
| 854 | global-directives
|
| 855 | lua-package-path
|
| 856 | lua-package-cpath
|
| 857 | extra-content)
|
| 858 | (apply mixed-text-file "nginx.conf"
|
| 859 | (flatten
|
| 860 | "user nginx nginx;\n"
|
| 861 | "pid " run-directory "/pid;\n"
|
| 862 | "error_log " (nginx-error-log-file config) " " (symbol->string log-level) ";\n"
|
| 863 | (map emit-load-module modules)
|
| 864 | (map emit-global-directive global-directives)
|
| 865 | (match stream
|
| 866 | (#f "")
|
| 867 | (_
|
| 868 | (list "stream {\n"
|
| 869 | (map emit-nginx-upstream-config
|
| 870 | (nginx-stream-configuration-upstream-blocks stream))
|
| 871 | (map (cut emit-nginx-server-config <> 'stream)
|
| 872 | (nginx-stream-configuration-server-blocks stream))
|
| 873 | (let ((extra-content (nginx-stream-configuration-extra-content stream)))
|
| 874 | (if (list? extra-content)
|
| 875 | (map (cut list " " <> "\n")
|
| 876 | extra-content)
|
| 877 | extra-content))
|
| 878 | "}\n")))
|
| 879 | "http {\n"
|
| 880 | " client_body_temp_path " run-directory "/client_body_temp;\n"
|
| 881 | " proxy_temp_path " run-directory "/proxy_temp;\n"
|
| 882 | " fastcgi_temp_path " run-directory "/fastcgi_temp;\n"
|
| 883 | " uwsgi_temp_path " run-directory "/uwsgi_temp;\n"
|
| 884 | " scgi_temp_path " run-directory "/scgi_temp;\n"
|
| 885 | (map emit-nginx-log-format-config log-formats)
|
| 886 | " access_log " (nginx-access-log-file config) " " (symbol->string log-format) ";\n"
|
| 887 | " include " nginx "/share/nginx/conf/mime.types;\n"
|
| 888 | (if lua-package-path
|
| 889 | #~(format #f " lua_package_path ~s;~%"
|
| 890 | (string-join (map (lambda (path)
|
| 891 | (string-append path "/lib/?.lua"))
|
| 892 | '#$lua-package-path)
|
| 893 | ";"))
|
| 894 | "")
|
| 895 | (if lua-package-cpath
|
| 896 | #~(format #f " lua_package_cpath ~s;~%"
|
| 897 | (string-join (map (lambda (cpath)
|
| 898 | (string-append cpath "/lib/lua/?.lua"))
|
| 899 | '#$lua-package-cpath)
|
| 900 | ";"))
|
| 901 | "")
|
| 902 | (if server-names-hash-bucket-size
|
| 903 | (string-append
|
| 904 | " server_names_hash_bucket_size "
|
| 905 | (number->string server-names-hash-bucket-size)
|
| 906 | ";\n")
|
| 907 | "")
|
| 908 | (if server-names-hash-bucket-max-size
|
| 909 | (string-append
|
| 910 | " server_names_hash_bucket_max_size "
|
| 911 | (number->string server-names-hash-bucket-max-size)
|
| 912 | ";\n")
|
| 913 | "")
|
| 914 | (match extra-content
|
| 915 | ((? list? extra-content)
|
| 916 | (map (lambda (line)
|
| 917 | `(" " ,line "\n"))
|
| 918 | extra-content))
|
| 919 | |
| 920 | |
| 921 | (_ extra-content))
|
| 922 | "\n"
|
| 923 | (map emit-nginx-upstream-config upstream-blocks)
|
| 924 | (map emit-nginx-server-config server-blocks)
|
| 925 | "}\n"))))
|
| 926 |
|
| 927 | (define %nginx-accounts
|
| 928 | (list (user-group (name "nginx") (system? #t))
|
| 929 | (user-account
|
| 930 | (name "nginx")
|
| 931 | (group "nginx")
|
| 932 | (system? #t)
|
| 933 | (comment "nginx server user")
|
| 934 | (home-directory "/var/empty")
|
| 935 | (shell (file-append shadow "/sbin/nologin")))))
|
| 936 |
|
| 937 | (define %nginx-configuration-file
|
| 938 | |
| 939 | |
| 940 | |
| 941 | |
| 942 | "/etc/nginx/nginx.conf")
|
| 943 |
|
| 944 | (define (nginx-activation config)
|
| 945 | (match-record config
|
| 946 | <nginx-configuration>
|
| 947 | (nginx log-directory run-directory file)
|
| 948 | #~(begin
|
| 949 | (use-modules (guix build utils))
|
| 950 |
|
| 951 | (format #t "creating nginx log directory '~a'~%" #$log-directory)
|
| 952 | (mkdir-p #$log-directory)
|
| 953 | (format #t "creating nginx run directory '~a'~%" #$run-directory)
|
| 954 | (mkdir-p #$run-directory)
|
| 955 | (format #t "creating nginx temp directories '~a/{client_body,proxy,fastcgi,uwsgi,scgi}_temp'~%" #$run-directory)
|
| 956 | (mkdir-p (string-append #$run-directory "/client_body_temp"))
|
| 957 | (mkdir-p (string-append #$run-directory "/proxy_temp"))
|
| 958 | (mkdir-p (string-append #$run-directory "/fastcgi_temp"))
|
| 959 | (mkdir-p (string-append #$run-directory "/uwsgi_temp"))
|
| 960 | (mkdir-p (string-append #$run-directory "/scgi_temp"))
|
| 961 | |
| 962 | |
| 963 | (mkdir-p (string-append #$run-directory "/logs")))))
|
| 964 |
|
| 965 | (define (nginx-shepherd-service config)
|
| 966 | (match-record config <nginx-configuration>
|
| 967 | (nginx file run-directory shepherd-requirement)
|
| 968 | (let* ((nginx-binary (file-append nginx "/sbin/nginx"))
|
| 969 | (pid-file (in-vicinity run-directory "pid"))
|
| 970 | (nginx-action
|
| 971 | (lambda args
|
| 972 | #~(lambda _
|
| 973 | (invoke #$nginx-binary "-c" #$%nginx-configuration-file
|
| 974 | #$@args)
|
| 975 | (match '#$args
|
| 976 | (("-s" "stop") #f)
|
| 977 | (("-s" . _) #t)
|
| 978 | (_
|
| 979 | |
| 980 | |
| 981 | |
| 982 | #$(if file
|
| 983 | #~#t
|
| 984 | #~(read-pid-file #$pid-file))))))))
|
| 985 |
|
| 986 | (list (shepherd-service
|
| 987 | (documentation "Run nginx pre-start actions.")
|
| 988 | (requirement '(user-processes loopback))
|
| 989 | (provision '(nginx-init))
|
| 990 | (one-shot? #t)
|
| 991 | (start
|
| 992 | #~(lambda _
|
| 993 | |
| 994 | (invoke #$nginx-binary
|
| 995 | "-c" #$%nginx-configuration-file
|
| 996 | "-p" #$run-directory
|
| 997 | "-t"))))
|
| 998 | (shepherd-service
|
| 999 | (provision '(nginx))
|
| 1000 | (documentation "Run the nginx daemon.")
|
| 1001 | (requirement `( user-processes loopback nginx-init
|
| 1002 | ,@shepherd-requirement))
|
| 1003 | (modules `((ice-9 match)
|
| 1004 | ,@%default-modules))
|
| 1005 | (start (nginx-action "-p" run-directory))
|
| 1006 | (stop #~(lambda (value)
|
| 1007 | |
| 1008 | |
| 1009 | |
| 1010 | |
| 1011 | |
| 1012 | (if (process? value)
|
| 1013 | (terminate-process (process-id value) SIGTERM)
|
| 1014 | (#$(nginx-action "-s" "stop")))))
|
| 1015 |
|
| 1016 | (actions
|
| 1017 | (list
|
| 1018 | (shepherd-configuration-action %nginx-configuration-file)
|
| 1019 | (shepherd-action
|
| 1020 | (name 'reload)
|
| 1021 | (documentation "Reload the nginx configuration file and
|
| 1022 | restart worker processes. This has the effect of killing old worker processes
|
| 1023 | and starting new ones, using the same configuration file. This is useful when
|
| 1024 | either the configuration files itself, or any files it refers to or includes
|
| 1025 | changed (for example, TLS certificates).")
|
| 1026 | (procedure (nginx-action "-p" run-directory "-s" "reload")))
|
| 1027 | (shepherd-action
|
| 1028 | (name 'reopen)
|
| 1029 | (documentation "Re-open log files.")
|
| 1030 | (procedure (nginx-action "-p" run-directory "-s" "reopen"))))))))))
|
| 1031 |
|
| 1032 | (define (nginx-log-files config)
|
| 1033 | (list (nginx-access-log-file config)
|
| 1034 | (nginx-error-log-file config)))
|
| 1035 |
|
| 1036 | (define (nginx-conf-files config)
|
| 1037 | |
| 1038 | (match-record config <nginx-configuration>
|
| 1039 | (nginx file)
|
| 1040 | (computed-file
|
| 1041 | "nginx-conf-files"
|
| 1042 | #~(begin
|
| 1043 | (use-modules (ice-9 ftw)
|
| 1044 | (srfi srfi-26))
|
| 1045 | (mkdir #$output)
|
| 1046 | (define nginx-conf #$(file-append nginx "/share/nginx/conf"))
|
| 1047 | (for-each
|
| 1048 | (lambda (x)
|
| 1049 | (symlink x (string-append #$output "/" (basename x))))
|
| 1050 | (map (cut string-append nginx-conf "/" <>)
|
| 1051 | (scandir nginx-conf
|
| 1052 | (negate (lambda (name)
|
| 1053 | (or (string-suffix? ".default" name)
|
| 1054 | (member name '("." ".."
|
| 1055 | "nginx.conf"))))))))
|
| 1056 | (symlink #$(or file (default-nginx-config config))
|
| 1057 | (string-append #$output "/nginx.conf"))))))
|
| 1058 |
|
| 1059 | (define (nginx-etc-directory config)
|
| 1060 | `(("nginx" ,(nginx-conf-files config))))
|
| 1061 |
|
| 1062 | (define nginx-service-type
|
| 1063 | (service-type
|
| 1064 | (name 'nginx)
|
| 1065 | (extensions
|
| 1066 | (list (service-extension shepherd-root-service-type
|
| 1067 | nginx-shepherd-service)
|
| 1068 | (service-extension log-rotation-service-type
|
| 1069 | nginx-log-files)
|
| 1070 | (service-extension activation-service-type
|
| 1071 | nginx-activation)
|
| 1072 | (service-extension account-service-type
|
| 1073 | (const %nginx-accounts))
|
| 1074 | (service-extension etc-service-type
|
| 1075 | nginx-etc-directory)
|
| 1076 | |
| 1077 | (service-extension profile-service-type
|
| 1078 | (compose list nginx-configuration-nginx))))
|
| 1079 | (compose concatenate)
|
| 1080 | (extend (lambda (config servers)
|
| 1081 | (nginx-configuration
|
| 1082 | (inherit config)
|
| 1083 | (server-blocks
|
| 1084 | (append (nginx-configuration-server-blocks config)
|
| 1085 | servers)))))
|
| 1086 | (default-value (nginx-configuration))
|
| 1087 | (description "Run the nginx Web server.")))
|
| 1088 |
|
| 1089 | (define-record-type* <gunicorn-configuration>
|
| 1090 | gunicorn-configuration make-gunicorn-configuration
|
| 1091 | gunicorn-configuration?
|
| 1092 | (package gunicorn-configuration-package
|
| 1093 | (default gunicorn))
|
| 1094 | (apps gunicorn-configuration-apps
|
| 1095 | (default '())))
|
| 1096 |
|
| 1097 | (define (sanitize-gunicorn-app-sockets value)
|
| 1098 | (unless (and (list? value)
|
| 1099 | (not (null? value)))
|
| 1100 | (leave (G_ "gunicorn: '~a' is invalid; must be a non-empty list~%") value))
|
| 1101 | value)
|
| 1102 |
|
| 1103 | (define-record-type* <gunicorn-app>
|
| 1104 | gunicorn-app make-gunicorn-app
|
| 1105 | gunicorn-app?
|
| 1106 | this-gunicorn-app
|
| 1107 | (name gunicorn-app-name)
|
| 1108 | (package gunicorn-app-package)
|
| 1109 | (wsgi-app-module gunicorn-app-wsgi-app-module)
|
| 1110 | (user gunicorn-app-user)
|
| 1111 | (group gunicorn-app-group)
|
| 1112 | (socket-user gunicorn-app-socket-user
|
| 1113 | (default (gunicorn-app-user this-gunicorn-app))
|
| 1114 | (thunked))
|
| 1115 | (socket-group gunicorn-app-socket-group
|
| 1116 | (default (gunicorn-app-group this-gunicorn-app))
|
| 1117 | (thunked))
|
| 1118 | (socket-mode gunicorn-app-socket-mode
|
| 1119 | (default #o750))
|
| 1120 | (control-socket gunicorn-app-control-socket
|
| 1121 | (default #f))
|
| 1122 | (sockets gunicorn-app-sockets
|
| 1123 | (default (list (string-append "unix:/var/run/gunicorn/"
|
| 1124 | (gunicorn-app-name this-gunicorn-app)
|
| 1125 | "/socket")))
|
| 1126 | (sanitize sanitize-gunicorn-app-sockets)
|
| 1127 | (thunked))
|
| 1128 | (workers gunicorn-app-workers
|
| 1129 | (default 1))
|
| 1130 | (extra-cli-arguments gunicorn-app-extra-cli-arguments
|
| 1131 | (default '()))
|
| 1132 | (environment-variables gunicorn-app-environment-variables
|
| 1133 | (default '()))
|
| 1134 | (timeout gunicorn-app-timeout
|
| 1135 | (default 30))
|
| 1136 | (mappings gunicorn-app-mappings
|
| 1137 | (default '())))
|
| 1138 |
|
| 1139 | (define (unix-socket? string)
|
| 1140 | "Whether STRING indicates a Unix socket."
|
| 1141 | (let ((uri (string->uri string)))
|
| 1142 | (and uri (eq? 'unix (uri-scheme uri)))))
|
| 1143 |
|
| 1144 | (define (socket-dir string)
|
| 1145 | "Return the socket directory."
|
| 1146 | (dirname (uri-path (string->uri string))))
|
| 1147 |
|
| 1148 | (define (gunicorn-activation config)
|
| 1149 | (with-imported-modules '((guix build utils))
|
| 1150 | #~(begin
|
| 1151 | (use-modules (guix build utils)
|
| 1152 | (ice-9 match))
|
| 1153 |
|
| 1154 | |
| 1155 | (for-each (match-lambda
|
| 1156 | ((user group mode socket-directories ...)
|
| 1157 | (for-each (lambda (socket-directory)
|
| 1158 | (mkdir-p socket-directory)
|
| 1159 | (chmod socket-directory mode)
|
| 1160 | (chown socket-directory
|
| 1161 | (passwd:uid (getpw user))
|
| 1162 | (group:gid (getgrnam group))))
|
| 1163 | socket-directories)))
|
| 1164 | '#$(map (lambda (app)
|
| 1165 | (cons* (gunicorn-app-socket-user app)
|
| 1166 | (gunicorn-app-socket-group app)
|
| 1167 | (gunicorn-app-socket-mode app)
|
| 1168 | (filter-map (lambda (socket)
|
| 1169 | (and
|
| 1170 | (unix-socket? socket)
|
| 1171 | (socket-dir socket)))
|
| 1172 | (gunicorn-app-sockets app))))
|
| 1173 | (gunicorn-configuration-apps config))))))
|
| 1174 |
|
| 1175 | (define (gunicorn-shepherd-services config)
|
| 1176 | (map (lambda (app)
|
| 1177 | (let ((name (string-append "gunicorn-" (gunicorn-app-name app)))
|
| 1178 | (user (gunicorn-app-user app))
|
| 1179 | (group (gunicorn-app-group app)))
|
| 1180 | (shepherd-service
|
| 1181 | (documentation (string-append "Run gunicorn for app "
|
| 1182 | (gunicorn-app-name app)
|
| 1183 | "."))
|
| 1184 | (provision (list (string->symbol name)))
|
| 1185 | (requirement '(networking))
|
| 1186 | (modules '((guix search-paths)
|
| 1187 | (ice-9 match)))
|
| 1188 | (start
|
| 1189 | (let* ((app-manifest (packages->manifest
|
| 1190 | |
| 1191 | |
| 1192 | |
| 1193 | (list python
|
| 1194 | (gunicorn-app-package app))))
|
| 1195 | (app-profile (profile
|
| 1196 | (content app-manifest)
|
| 1197 | (allow-collisions? #t))))
|
| 1198 | (with-imported-modules
|
| 1199 | (source-module-closure '((guix search-paths)))
|
| 1200 | #~(make-forkexec-constructor
|
| 1201 | (cons*
|
| 1202 | #$(least-authority-wrapper
|
| 1203 | (file-append (gunicorn-configuration-package config)
|
| 1204 | "/bin/gunicorn")
|
| 1205 | #:name (string-append name "-pola-wrapper")
|
| 1206 | #:mappings
|
| 1207 | (cons (file-system-mapping
|
| 1208 | |
| 1209 | (source app-profile)
|
| 1210 | (target source))
|
| 1211 | (append
|
| 1212 | |
| 1213 | (filter-map
|
| 1214 | (lambda (socket)
|
| 1215 | (and (unix-socket? socket)
|
| 1216 | (file-system-mapping
|
| 1217 | (source (socket-dir socket))
|
| 1218 | (target source)
|
| 1219 | (writable? #t))))
|
| 1220 | (gunicorn-app-sockets app))
|
| 1221 | |
| 1222 | (gunicorn-app-mappings app)))
|
| 1223 | #:preserved-environment-variables
|
| 1224 | (map search-path-specification-variable
|
| 1225 | (manifest-search-paths app-manifest))
|
| 1226 | #:namespaces (delq 'net %namespaces))
|
| 1227 | "--workers" #$(number->string (gunicorn-app-workers app))
|
| 1228 | "--timeout" #$(number->string (gunicorn-app-timeout app))
|
| 1229 | #$(let ((ctrl-socket (gunicorn-app-control-socket app)))
|
| 1230 | (if ctrl-socket
|
| 1231 | (string-append "--control-socket=" ctrl-socket)
|
| 1232 | "--no-control-socket"))
|
| 1233 | (list
|
| 1234 | #$@(append
|
| 1235 | (append-map (lambda (socket)
|
| 1236 | (list "--bind" socket))
|
| 1237 | (gunicorn-app-sockets app))
|
| 1238 | (append-map
|
| 1239 | (lambda (pair)
|
| 1240 | (list "--env"
|
| 1241 | #~(string-append
|
| 1242 | #$(car pair) "=" #$(cdr pair))))
|
| 1243 | (gunicorn-app-environment-variables app))
|
| 1244 | (gunicorn-app-extra-cli-arguments app)
|
| 1245 | (list (gunicorn-app-wsgi-app-module app)))))
|
| 1246 | #:user #$user
|
| 1247 | #:group #$group
|
| 1248 | #:environment-variables
|
| 1249 | (map (match-lambda
|
| 1250 | ((spec . value)
|
| 1251 | (string-append
|
| 1252 | (search-path-specification-variable spec)
|
| 1253 | "="
|
| 1254 | value)))
|
| 1255 | (evaluate-search-paths
|
| 1256 | (map sexp->search-path-specification
|
| 1257 | '#$(map search-path-specification->sexp
|
| 1258 | (manifest-search-paths app-manifest)))
|
| 1259 | (list #$app-profile)))
|
| 1260 | #:log-file #$(string-append "/var/log/" name ".log")))))
|
| 1261 | (stop #~(make-kill-destructor)))))
|
| 1262 | (gunicorn-configuration-apps config)))
|
| 1263 |
|
| 1264 | (define gunicorn-service-type
|
| 1265 | (service-type
|
| 1266 | (name 'gunicorn)
|
| 1267 | (description "Run gunicorn.")
|
| 1268 | (extensions (list (service-extension activation-service-type
|
| 1269 | gunicorn-activation)
|
| 1270 | (service-extension shepherd-root-service-type
|
| 1271 | gunicorn-shepherd-services)))
|
| 1272 | (compose concatenate)
|
| 1273 | (extend (lambda (config apps)
|
| 1274 | (gunicorn-configuration
|
| 1275 | (inherit config)
|
| 1276 | (apps (append (gunicorn-configuration-apps config)
|
| 1277 | apps)))))
|
| 1278 | (default-value (gunicorn-configuration))))
|
| 1279 |
|
| 1280 | (define-record-type* <fcgiwrap-configuration> fcgiwrap-configuration
|
| 1281 | make-fcgiwrap-configuration
|
| 1282 | fcgiwrap-configuration?
|
| 1283 | (package fcgiwrap-configuration-package |
| 1284 | (default fcgiwrap))
|
| 1285 | (socket fcgiwrap-configuration-socket
|
| 1286 | (default "tcp:127.0.0.1:9000"))
|
| 1287 | (user fcgiwrap-configuration-user
|
| 1288 | (default "fcgiwrap"))
|
| 1289 | (group fcgiwrap-configuration-group
|
| 1290 | (default "fcgiwrap")))
|
| 1291 |
|
| 1292 | (define fcgiwrap-accounts
|
| 1293 | (match-lambda
|
| 1294 | (($ <fcgiwrap-configuration> package socket user group)
|
| 1295 | (filter identity
|
| 1296 | (list
|
| 1297 | (and (equal? group "fcgiwrap")
|
| 1298 | (user-group
|
| 1299 | (name "fcgiwrap")
|
| 1300 | (system? #t)))
|
| 1301 | (and (equal? user "fcgiwrap")
|
| 1302 | (user-account
|
| 1303 | (name "fcgiwrap")
|
| 1304 | (group group)
|
| 1305 | (system? #t)
|
| 1306 | (comment "Fcgiwrap Daemon")
|
| 1307 | (home-directory "/var/empty")
|
| 1308 | (shell (file-append shadow "/sbin/nologin")))))))))
|
| 1309 |
|
| 1310 | (define fcgiwrap-shepherd-service
|
| 1311 | (match-lambda
|
| 1312 | (($ <fcgiwrap-configuration> package socket user group)
|
| 1313 | (list (shepherd-service
|
| 1314 | (provision '(fcgiwrap))
|
| 1315 | (documentation "Run the fcgiwrap daemon.")
|
| 1316 | (requirement '(user-processes networking))
|
| 1317 | (start #~(make-forkexec-constructor
|
| 1318 | '(#$(file-append package "/sbin/fcgiwrap")
|
| 1319 | "-s" #$socket)
|
| 1320 | #:user #$user #:group #$group
|
| 1321 | #:log-file "/var/log/fcgiwrap.log"))
|
| 1322 | (stop #~(make-kill-destructor)))))))
|
| 1323 |
|
| 1324 | (define fcgiwrap-activation
|
| 1325 | (match-lambda
|
| 1326 | (($ <fcgiwrap-configuration> package socket user group)
|
| 1327 | #~(begin
|
| 1328 | |
| 1329 | |
| 1330 | (when (string-prefix? "unix:" #$socket)
|
| 1331 | (let ((run-directory
|
| 1332 | (dirname (substring #$socket (string-length "unix:")))))
|
| 1333 | (mkdir-p run-directory)
|
| 1334 | (chown run-directory
|
| 1335 | (passwd:uid (getpw #$user))
|
| 1336 | (group:gid (getgr #$group)))))))))
|
| 1337 |
|
| 1338 | (define fcgiwrap-service-type
|
| 1339 | (service-type (name 'fcgiwrap)
|
| 1340 | (extensions
|
| 1341 | (list (service-extension shepherd-root-service-type
|
| 1342 | fcgiwrap-shepherd-service)
|
| 1343 | (service-extension account-service-type
|
| 1344 | fcgiwrap-accounts)
|
| 1345 | (service-extension activation-service-type
|
| 1346 | fcgiwrap-activation)))
|
| 1347 | (default-value (fcgiwrap-configuration))
|
| 1348 | (description "Run FastCGI, an interface between the front-end
|
| 1349 | and the back-end of a Web service.")))
|
| 1350 |
|
| 1351 | (define-record-type* <php-fpm-configuration> php-fpm-configuration
|
| 1352 | make-php-fpm-configuration
|
| 1353 | php-fpm-configuration?
|
| 1354 | (php php-fpm-configuration-php |
| 1355 | (default php))
|
| 1356 | (socket php-fpm-configuration-socket
|
| 1357 | (default (string-append "/var/run/php"
|
| 1358 | (version-major (package-version php))
|
| 1359 | "-fpm.sock")))
|
| 1360 | (user php-fpm-configuration-user
|
| 1361 | (default "php-fpm"))
|
| 1362 | (group php-fpm-configuration-group
|
| 1363 | (default "php-fpm"))
|
| 1364 | (socket-user php-fpm-configuration-socket-user
|
| 1365 | (default "php-fpm"))
|
| 1366 | (socket-group php-fpm-configuration-socket-group
|
| 1367 | (default "nginx"))
|
| 1368 | (pid-file php-fpm-configuration-pid-file
|
| 1369 | (default (string-append "/var/run/php"
|
| 1370 | (version-major (package-version php))
|
| 1371 | "-fpm.pid")))
|
| 1372 | (log-file php-fpm-configuration-log-file
|
| 1373 | (default (string-append "/var/log/php"
|
| 1374 | (version-major (package-version php))
|
| 1375 | "-fpm.log")))
|
| 1376 | (process-manager php-fpm-configuration-process-manager
|
| 1377 | (default (php-fpm-dynamic-process-manager-configuration)))
|
| 1378 | (display-errors php-fpm-configuration-display-errors
|
| 1379 | (default #f))
|
| 1380 | (timezone php-fpm-configuration-timezone
|
| 1381 | (default #f))
|
| 1382 | (workers-log-file php-fpm-configuration-workers-log-file
|
| 1383 | (default (string-append "/var/log/php"
|
| 1384 | (version-major (package-version php))
|
| 1385 | "-fpm.www.log")))
|
| 1386 | (file php-fpm-configuration-file |
| 1387 | (default #f))
|
| 1388 | (php-ini-file php-fpm-configuration-php-ini-file |
| 1389 | (default #f)))
|
| 1390 |
|
| 1391 | (define-record-type* <php-fpm-dynamic-process-manager-configuration>
|
| 1392 | php-fpm-dynamic-process-manager-configuration
|
| 1393 | make-php-fpm-dynamic-process-manager-configuration
|
| 1394 | php-fpm-dynamic-process-manager-configuration?
|
| 1395 | (max-children php-fpm-dynamic-process-manager-configuration-max-children
|
| 1396 | (default 5))
|
| 1397 | (start-servers php-fpm-dynamic-process-manager-configuration-start-servers
|
| 1398 | (default 2))
|
| 1399 | (min-spare-servers php-fpm-dynamic-process-manager-configuration-min-spare-servers
|
| 1400 | (default 1))
|
| 1401 | (max-spare-servers php-fpm-dynamic-process-manager-configuration-max-spare-servers
|
| 1402 | (default 3)))
|
| 1403 |
|
| 1404 | (define-record-type* <php-fpm-static-process-manager-configuration>
|
| 1405 | php-fpm-static-process-manager-configuration
|
| 1406 | make-php-fpm-static-process-manager-configuration
|
| 1407 | php-fpm-static-process-manager-configuration?
|
| 1408 | (max-children php-fpm-static-process-manager-configuration-max-children
|
| 1409 | (default 5)))
|
| 1410 |
|
| 1411 | (define-record-type* <php-fpm-on-demand-process-manager-configuration>
|
| 1412 | php-fpm-on-demand-process-manager-configuration
|
| 1413 | make-php-fpm-on-demand-process-manager-configuration
|
| 1414 | php-fpm-on-demand-process-manager-configuration?
|
| 1415 | (max-children php-fpm-on-demand-process-manager-configuration-max-children
|
| 1416 | (default 5))
|
| 1417 | (process-idle-timeout php-fpm-on-demand-process-manager-configuration-process-idle-timeout
|
| 1418 | (default 10)))
|
| 1419 |
|
| 1420 | (define php-fpm-accounts
|
| 1421 | (match-lambda
|
| 1422 | (($ <php-fpm-configuration> php socket user group socket-user socket-group)
|
| 1423 | `(,@(if (equal? group "php-fpm")
|
| 1424 | '()
|
| 1425 | (list (user-group (name "php-fpm") (system? #t))))
|
| 1426 | ,(user-group
|
| 1427 | (name group)
|
| 1428 | (system? #t))
|
| 1429 | ,(user-account
|
| 1430 | (name user)
|
| 1431 | (group group)
|
| 1432 | (supplementary-groups '("php-fpm"))
|
| 1433 | (system? #t)
|
| 1434 | (comment "php-fpm daemon user")
|
| 1435 | (home-directory "/var/empty")
|
| 1436 | (shell (file-append shadow "/sbin/nologin")))))))
|
| 1437 |
|
| 1438 | (define (default-php-fpm-config socket user group socket-user socket-group
|
| 1439 | pid-file log-file pm display-errors timezone workers-log-file)
|
| 1440 | (apply mixed-text-file "php-fpm.conf"
|
| 1441 | (flatten
|
| 1442 | "[global]\n"
|
| 1443 | "pid =" pid-file "\n"
|
| 1444 | "error_log =" log-file "\n"
|
| 1445 | "[www]\n"
|
| 1446 | "user =" user "\n"
|
| 1447 | "group =" group "\n"
|
| 1448 | "listen =" socket "\n"
|
| 1449 | "listen.owner =" socket-user "\n"
|
| 1450 | "listen.group =" socket-group "\n"
|
| 1451 |
|
| 1452 | (if timezone
|
| 1453 | (string-append "php_admin_value[date.timezone] = \"" timezone "\"\n")
|
| 1454 | "")
|
| 1455 |
|
| 1456 | (match pm
|
| 1457 | (($ <php-fpm-dynamic-process-manager-configuration>
|
| 1458 | pm.max-children
|
| 1459 | pm.start-servers
|
| 1460 | pm.min-spare-servers
|
| 1461 | pm.max-spare-servers)
|
| 1462 | (list
|
| 1463 | "pm = dynamic\n"
|
| 1464 | "pm.max_children =" (number->string pm.max-children) "\n"
|
| 1465 | "pm.start_servers =" (number->string pm.start-servers) "\n"
|
| 1466 | "pm.min_spare_servers =" (number->string pm.min-spare-servers) "\n"
|
| 1467 | "pm.max_spare_servers =" (number->string pm.max-spare-servers) "\n"))
|
| 1468 |
|
| 1469 | (($ <php-fpm-static-process-manager-configuration>
|
| 1470 | pm.max-children)
|
| 1471 | (list
|
| 1472 | "pm = static\n"
|
| 1473 | "pm.max_children =" (number->string pm.max-children) "\n"))
|
| 1474 |
|
| 1475 | (($ <php-fpm-on-demand-process-manager-configuration>
|
| 1476 | pm.max-children
|
| 1477 | pm.process-idle-timeout)
|
| 1478 | (list
|
| 1479 | "pm = ondemand\n"
|
| 1480 | "pm.max_children =" (number->string pm.max-children) "\n"
|
| 1481 | "pm.process_idle_timeout =" (number->string pm.process-idle-timeout) "s\n")))
|
| 1482 |
|
| 1483 |
|
| 1484 | "php_flag[display_errors] = " (if display-errors "on" "off") "\n"
|
| 1485 |
|
| 1486 | (if workers-log-file
|
| 1487 | (list "catch_workers_output = yes\n"
|
| 1488 | "php_admin_value[error_log] =" workers-log-file "\n"
|
| 1489 | "php_admin_flag[log_errors] = on\n")
|
| 1490 | (list "catch_workers_output = no\n")))))
|
| 1491 |
|
| 1492 | (define php-fpm-shepherd-service
|
| 1493 | (match-lambda
|
| 1494 | (($ <php-fpm-configuration> php socket user group socket-user socket-group
|
| 1495 | pid-file log-file pm display-errors
|
| 1496 | timezone workers-log-file file php-ini-file)
|
| 1497 | (list (shepherd-service
|
| 1498 | (provision '(php-fpm))
|
| 1499 | (documentation "Run the php-fpm daemon.")
|
| 1500 | (requirement '(user-processes networking))
|
| 1501 | (start #~(make-forkexec-constructor
|
| 1502 | '(#$(file-append php "/sbin/php-fpm")
|
| 1503 | "--fpm-config"
|
| 1504 | #$(or file
|
| 1505 | (default-php-fpm-config socket user group
|
| 1506 | socket-user socket-group pid-file log-file
|
| 1507 | pm display-errors timezone workers-log-file))
|
| 1508 | #$@(if php-ini-file
|
| 1509 | `("-c" ,php-ini-file)
|
| 1510 | '()))
|
| 1511 | #:pid-file #$pid-file))
|
| 1512 | (stop #~(make-kill-destructor)))))))
|
| 1513 |
|
| 1514 | (define (php-fpm-activation config)
|
| 1515 | #~(begin
|
| 1516 | (use-modules (guix build utils))
|
| 1517 | (let* ((user (getpwnam #$(php-fpm-configuration-user config)))
|
| 1518 | (touch (lambda (file-name)
|
| 1519 | (call-with-output-file file-name (const #t))))
|
| 1520 | (workers-log-file
|
| 1521 | #$(php-fpm-configuration-workers-log-file config))
|
| 1522 | (init-log-file
|
| 1523 | (lambda (file-name)
|
| 1524 | (when workers-log-file
|
| 1525 | (when (not (file-exists? file-name))
|
| 1526 | (touch file-name))
|
| 1527 | (chown file-name (passwd:uid user) (passwd:gid user))
|
| 1528 | (chmod file-name #o660)))))
|
| 1529 | (init-log-file #$(php-fpm-configuration-log-file config))
|
| 1530 | (init-log-file workers-log-file))))
|
| 1531 |
|
| 1532 |
|
| 1533 | (define php-fpm-service-type
|
| 1534 | (service-type
|
| 1535 | (name 'php-fpm)
|
| 1536 | (description
|
| 1537 | "Run @command{php-fpm} to provide a fastcgi socket for calling php through
|
| 1538 | a webserver.")
|
| 1539 | (extensions
|
| 1540 | (list (service-extension shepherd-root-service-type
|
| 1541 | php-fpm-shepherd-service)
|
| 1542 | (service-extension activation-service-type
|
| 1543 | php-fpm-activation)
|
| 1544 | (service-extension account-service-type
|
| 1545 | php-fpm-accounts)))
|
| 1546 | (default-value (php-fpm-configuration))))
|
| 1547 |
|
| 1548 | (define* (nginx-php-location
|
| 1549 | #:key
|
| 1550 | (nginx-package nginx)
|
| 1551 | (socket (string-append "/var/run/php"
|
| 1552 | (version-major (package-version php))
|
| 1553 | "-fpm.sock")))
|
| 1554 | "Return a nginx-location-configuration that makes nginx run .php files."
|
| 1555 | (nginx-location-configuration
|
| 1556 | (uri "~ \\.php$")
|
| 1557 | (body (list
|
| 1558 | "fastcgi_split_path_info ^(.+\\.php)(/.+)$;"
|
| 1559 |
|
| 1560 | |
| 1561 | |
| 1562 | |
| 1563 | "fastcgi_param HTTP_PROXY \"\";"
|
| 1564 | |
| 1565 | "if (!-f $document_root$fastcgi_script_name) { return 404; }"
|
| 1566 |
|
| 1567 | (string-append "fastcgi_pass unix:" socket ";")
|
| 1568 | "fastcgi_index index.php;"
|
| 1569 | (list "include " nginx-package "/share/nginx/conf/fastcgi.conf;")))))
|
| 1570 |
|
| 1571 | (define* (cat-avatar-generator-service
|
| 1572 | #:key
|
| 1573 | (cache-dir "/var/cache/cat-avatar-generator/")
|
| 1574 | (package cat-avatar-generator)
|
| 1575 | (configuration (nginx-server-configuration)))
|
| 1576 | (simple-service
|
| 1577 | 'cat-http-server nginx-service-type
|
| 1578 | (list (nginx-server-configuration
|
| 1579 | (inherit configuration)
|
| 1580 | (locations
|
| 1581 | (cons
|
| 1582 | (let ((base (nginx-php-location)))
|
| 1583 | (nginx-location-configuration
|
| 1584 | (inherit base)
|
| 1585 | (body (list (string-append "fastcgi_param CACHE_DIR \""
|
| 1586 | cache-dir "\";")
|
| 1587 | (nginx-location-configuration-body base)))))
|
| 1588 | (nginx-server-configuration-locations configuration)))
|
| 1589 | (root #~(string-append #$package
|
| 1590 | "/share/web/cat-avatar-generator"))))))
|
| 1591 |
|
| 1592 |
|
| 1593 | (define-record-type* <hpcguix-web-configuration>
|
| 1594 | hpcguix-web-configuration make-hpcguix-web-configuration
|
| 1595 | hpcguix-web-configuration?
|
| 1596 |
|
| 1597 | (package hpcguix-web-package (default hpcguix-web)) |
| 1598 |
|
| 1599 | (specs hpcguix-web-configuration-specs (default #f)) |
| 1600 | (address hpcguix-web-configuration-address (default "127.0.0.1"))
|
| 1601 | (port hpcguix-web-configuration-port (default 5000)))
|
| 1602 |
|
| 1603 | (define %hpcguix-web-accounts
|
| 1604 | (list (user-group
|
| 1605 | (name "hpcguix-web")
|
| 1606 | (system? #t))
|
| 1607 | (user-account
|
| 1608 | (name "hpcguix-web")
|
| 1609 | (group "hpcguix-web")
|
| 1610 | (system? #t)
|
| 1611 | (comment "hpcguix-web")
|
| 1612 | (home-directory "/var/empty")
|
| 1613 | (shell (file-append shadow "/sbin/nologin")))))
|
| 1614 |
|
| 1615 | (define %hpcguix-web-activation
|
| 1616 | (with-imported-modules '((guix build utils))
|
| 1617 | #~(begin
|
| 1618 | (use-modules (guix build utils)
|
| 1619 | (ice-9 ftw))
|
| 1620 |
|
| 1621 | (let ((home-dir "/var/cache/guix/web")
|
| 1622 | (user (getpwnam "hpcguix-web")))
|
| 1623 | (mkdir-p home-dir)
|
| 1624 | (chown home-dir (passwd:uid user) (passwd:gid user))
|
| 1625 | (chmod home-dir #o755)
|
| 1626 |
|
| 1627 | |
| 1628 | |
| 1629 | (for-each (lambda (lock)
|
| 1630 | (delete-file (string-append home-dir "/" lock)))
|
| 1631 | (scandir home-dir
|
| 1632 | (lambda (file)
|
| 1633 | (string-suffix? ".lock" file))))))))
|
| 1634 |
|
| 1635 | (define %hpcguix-web-log-file
|
| 1636 | "/var/log/hpcguix-web.log")
|
| 1637 |
|
| 1638 | (define (hpcguix-web-shepherd-service config)
|
| 1639 | (let* ((specs (hpcguix-web-configuration-specs config))
|
| 1640 | (config-file (and specs (scheme-file "hpcguix-web.scm" specs)))
|
| 1641 | (hpcguix-web (hpcguix-web-package config)))
|
| 1642 | (shepherd-service
|
| 1643 | (documentation "hpcguix-web daemon")
|
| 1644 | (provision '(hpcguix-web))
|
| 1645 | (requirement '(user-processes networking))
|
| 1646 | (start #~(make-forkexec-constructor
|
| 1647 | (list #$(file-append hpcguix-web "/bin/hpcguix-web")
|
| 1648 | (string-append "--listen="
|
| 1649 | #$(hpcguix-web-configuration-address
|
| 1650 | config))
|
| 1651 | "-p"
|
| 1652 | #$(number->string
|
| 1653 | (hpcguix-web-configuration-port config))
|
| 1654 | #$@(if specs
|
| 1655 | #~((string-append "--config=" #$config-file))
|
| 1656 | #~()))
|
| 1657 | #:user "hpcguix-web"
|
| 1658 | #:group "hpcguix-web"
|
| 1659 | #:environment-variables
|
| 1660 | (list "XDG_CACHE_HOME=/var/cache/guix/web"
|
| 1661 | "SSL_CERT_DIR=/etc/ssl/certs")
|
| 1662 | #:log-file #$%hpcguix-web-log-file))
|
| 1663 | (stop #~(make-kill-destructor))
|
| 1664 | (actions (list (shepherd-configuration-action config-file))))))
|
| 1665 |
|
| 1666 | (define hpcguix-web-service-type
|
| 1667 | (service-type
|
| 1668 | (name 'hpcguix-web)
|
| 1669 | (description "Run the hpcguix-web server.")
|
| 1670 | (extensions
|
| 1671 | (list (service-extension account-service-type
|
| 1672 | (const %hpcguix-web-accounts))
|
| 1673 | (service-extension activation-service-type
|
| 1674 | (const %hpcguix-web-activation))
|
| 1675 | (service-extension shepherd-root-service-type
|
| 1676 | (compose list hpcguix-web-shepherd-service))))
|
| 1677 | (default-value (hpcguix-web-configuration))))
|
| 1678 |
|
| 1679 |
|
| 1680 | |
| 1681 | |
| 1682 | |
| 1683 |
|
| 1684 | (define-record-type* <anonip-configuration>
|
| 1685 | anonip-configuration make-anonip-configuration
|
| 1686 | anonip-configuration?
|
| 1687 | (anonip anonip-configuration-anonip |
| 1688 | (default anonip))
|
| 1689 | (input anonip-configuration-input) |
| 1690 | (output anonip-configuration-output) |
| 1691 | (debug? anonip-configuration-debug? |
| 1692 | (default #f))
|
| 1693 | (skip-private? anonip-configuration-skip-private? |
| 1694 | (default #f))
|
| 1695 | (column anonip-configuration-column |
| 1696 | (default #f))
|
| 1697 | (replacement anonip-configuration-replacement |
| 1698 | (default #f))
|
| 1699 | (ipv4mask anonip-configuration-ipv4mask |
| 1700 | (default #f))
|
| 1701 | (ipv6mask anonip-configuration-ipv6mask |
| 1702 | (default #f))
|
| 1703 | (increment anonip-configuration-increment |
| 1704 | (default #f))
|
| 1705 | (delimiter anonip-configuration-delimiter |
| 1706 | (default #f))
|
| 1707 | (regex anonip-configuration-regex |
| 1708 | (default #f)))
|
| 1709 |
|
| 1710 | (define (anonip-activation config)
|
| 1711 | (with-imported-modules '((guix build utils))
|
| 1712 | #~(begin
|
| 1713 | (use-modules (guix build utils))
|
| 1714 | (for-each
|
| 1715 | (lambda (directory)
|
| 1716 | (mkdir-p directory)
|
| 1717 | (chmod directory #o755))
|
| 1718 | (list (dirname #$(anonip-configuration-input config))
|
| 1719 | (dirname #$(anonip-configuration-output config)))))))
|
| 1720 |
|
| 1721 | (define (anonip-shepherd-service config)
|
| 1722 | (let ((input (anonip-configuration-input config))
|
| 1723 | (output (anonip-configuration-output config))
|
| 1724 | (optional
|
| 1725 | (lambda (accessor option)
|
| 1726 | (or (and=> (accessor config)
|
| 1727 | (lambda (value)
|
| 1728 | (list
|
| 1729 | (format #false "~a=~a"
|
| 1730 | option value))))
|
| 1731 | (list)))))
|
| 1732 | (list
|
| 1733 | (shepherd-service
|
| 1734 | (provision
|
| 1735 | (list (symbol-append 'anonip- (string->symbol output))))
|
| 1736 | (requirement '(user-processes))
|
| 1737 | (documentation
|
| 1738 | "Anonimyze the given log file location with anonip.")
|
| 1739 | (start
|
| 1740 | #~(lambda ()
|
| 1741 | |
| 1742 | |
| 1743 | |
| 1744 | (false-if-exception (delete-file #$input))
|
| 1745 | (mknod #$input 'fifo #o600 0)
|
| 1746 |
|
| 1747 | (fork+exec-command
|
| 1748 | (append
|
| 1749 | (list #$(file-append (anonip-configuration-anonip config)
|
| 1750 | "/bin/anonip")
|
| 1751 | (string-append "--input=" #$input)
|
| 1752 | (string-append "--output=" #$output))
|
| 1753 | (if #$(anonip-configuration-debug? config)
|
| 1754 | '("--debug") (list))
|
| 1755 | (if #$(anonip-configuration-skip-private? config)
|
| 1756 | '("--skip-private") (list))
|
| 1757 | '#$(optional anonip-configuration-column "--column")
|
| 1758 | '#$(optional anonip-configuration-ipv4mask "--ipv4mask")
|
| 1759 | '#$(optional anonip-configuration-ipv6mask "--ipv6mask")
|
| 1760 | '#$(optional anonip-configuration-increment "--increment")
|
| 1761 | '#$(optional anonip-configuration-replacement "--replacement")
|
| 1762 | '#$(optional anonip-configuration-delimiter "--delimiter")
|
| 1763 | '#$(optional anonip-configuration-regex "--regex"))
|
| 1764 | |
| 1765 | #:environment-variables
|
| 1766 | (list (string-append "GUIX_LOCPATH="
|
| 1767 | #$(libc-utf8-locales-for-target)
|
| 1768 | "/lib/locale")
|
| 1769 | "LC_ALL=en_US.utf8"))))
|
| 1770 | (stop #~(make-kill-destructor))))))
|
| 1771 |
|
| 1772 | (define (anonip-log-files config)
|
| 1773 | "Return the list of log files produced by @command{anonip}."
|
| 1774 | (list (anonip-configuration-output config)))
|
| 1775 |
|
| 1776 | (define anonip-service-type
|
| 1777 | (service-type
|
| 1778 | (name 'anonip)
|
| 1779 | (extensions
|
| 1780 | (list (service-extension shepherd-root-service-type
|
| 1781 | anonip-shepherd-service)
|
| 1782 | (service-extension log-rotation-service-type
|
| 1783 | anonip-log-files)
|
| 1784 | (service-extension activation-service-type
|
| 1785 | anonip-activation)))
|
| 1786 | (description
|
| 1787 | "Provide web server log anonymization with @command{anonip}.")))
|
| 1788 |
|
| 1789 |
|
| 1790 | |
| 1791 | |
| 1792 | |
| 1793 |
|
| 1794 | (define-record-type* <varnish-configuration>
|
| 1795 | varnish-configuration make-varnish-configuration
|
| 1796 | varnish-configuration?
|
| 1797 | (package varnish-configuration-package |
| 1798 | (default varnish))
|
| 1799 | (name varnish-configuration-name |
| 1800 | (default "default"))
|
| 1801 | (backend varnish-configuration-backend |
| 1802 | (default "localhost:8080"))
|
| 1803 | (vcl varnish-configuration-vcl |
| 1804 | (default #f))
|
| 1805 | (listen varnish-configuration-listen |
| 1806 | (default '("localhost:80")))
|
| 1807 | (storage varnish-configuration-storage |
| 1808 | (default '("malloc,128m")))
|
| 1809 | (parameters varnish-configuration-parameters |
| 1810 | (default '()))
|
| 1811 | (extra-options varnish-configuration-extra-options |
| 1812 | (default '())))
|
| 1813 |
|
| 1814 | (define %varnish-accounts
|
| 1815 | (list (user-group
|
| 1816 | (name "varnish")
|
| 1817 | (system? #t))
|
| 1818 | (user-account
|
| 1819 | (name "varnish")
|
| 1820 | (group "varnish")
|
| 1821 | (system? #t)
|
| 1822 | (comment "Varnish Cache User")
|
| 1823 | (home-directory "/var/varnish")
|
| 1824 | (shell (file-append shadow "/sbin/nologin")))))
|
| 1825 |
|
| 1826 | (define varnish-shepherd-service
|
| 1827 | (match-lambda
|
| 1828 | (($ <varnish-configuration> package name backend vcl listen storage
|
| 1829 | parameters extra-options)
|
| 1830 | (list (shepherd-service
|
| 1831 | (provision (list (symbol-append 'varnish- (string->symbol name))))
|
| 1832 | (documentation (string-append "The Varnish Web Accelerator"
|
| 1833 | " (" name ")"))
|
| 1834 | (requirement '(user-processes networking))
|
| 1835 | (start #~(make-forkexec-constructor
|
| 1836 | (list #$(file-append package "/sbin/varnishd")
|
| 1837 | "-n" #$name
|
| 1838 | #$@(if vcl
|
| 1839 | #~("-f" #$vcl)
|
| 1840 | #~("-b" #$backend))
|
| 1841 | #$@(append-map (lambda (a) (list "-a" a)) listen)
|
| 1842 | #$@(append-map (lambda (s) (list "-s" s)) storage)
|
| 1843 | #$@(append-map (lambda (p)
|
| 1844 | (list "-p" (format #f "~a=~a"
|
| 1845 | (car p) (cdr p))))
|
| 1846 | parameters)
|
| 1847 | #$@extra-options)
|
| 1848 | |
| 1849 | |
| 1850 | |
| 1851 | #:pid-file (if (string-prefix? "/" #$name)
|
| 1852 | (string-append #$name "/_.pid")
|
| 1853 | (string-append "/var/varnish/" #$name "/_.pid"))))
|
| 1854 | (stop #~(make-kill-destructor)))))))
|
| 1855 |
|
| 1856 | (define varnish-service-type
|
| 1857 | (service-type
|
| 1858 | (name 'varnish)
|
| 1859 | (description "Run the Varnish cache server.")
|
| 1860 | (extensions
|
| 1861 | (list (service-extension account-service-type
|
| 1862 | (const %varnish-accounts))
|
| 1863 | (service-extension shepherd-root-service-type
|
| 1864 | varnish-shepherd-service)))
|
| 1865 | (default-value
|
| 1866 | (varnish-configuration))))
|
| 1867 |
|
| 1868 |
|
| 1869 | |
| 1870 | |
| 1871 | |
| 1872 |
|
| 1873 | (define-configuration/no-serialization whoogle-configuration
|
| 1874 | (package
|
| 1875 | (package whoogle-search)
|
| 1876 | "The @code{whoogle-search} package to use.")
|
| 1877 | (host
|
| 1878 | (string "127.0.0.1")
|
| 1879 | "The host address to run Whoogle on.")
|
| 1880 | (port
|
| 1881 | (integer 5000)
|
| 1882 | "The port to run Whoogle on.")
|
| 1883 | (environment-variables
|
| 1884 | (list-of-strings '())
|
| 1885 | "A list of strings specifying environment variables used to configure
|
| 1886 | Whoogle."))
|
| 1887 |
|
| 1888 | (define (whoogle-shepherd-service config)
|
| 1889 | (match-record config <whoogle-configuration>
|
| 1890 | (package host port environment-variables)
|
| 1891 | (list
|
| 1892 | (shepherd-service
|
| 1893 | (provision '(whoogle-search))
|
| 1894 | (requirement '(user-processes))
|
| 1895 | (start #~(make-forkexec-constructor
|
| 1896 | (list (string-append #$package "/bin/whoogle-search")
|
| 1897 | "--host" #$host "--port" #$(number->string port))
|
| 1898 | #:environment-variables
|
| 1899 | (append (list "CONFIG_VOLUME=/var/cache/whoogle-search")
|
| 1900 | '#$environment-variables)))
|
| 1901 | (stop #~(make-kill-destructor))
|
| 1902 | (documentation "Run a @code{whoogle-search} instance.")))))
|
| 1903 |
|
| 1904 | (define whoogle-service-type
|
| 1905 | (service-type
|
| 1906 | (name 'whoogle-search)
|
| 1907 | (extensions
|
| 1908 | (list (service-extension shepherd-root-service-type
|
| 1909 | whoogle-shepherd-service)
|
| 1910 | (service-extension profile-service-type
|
| 1911 | (compose list whoogle-configuration-package))))
|
| 1912 | (default-value (whoogle-configuration))
|
| 1913 | (description "Set up the @code{whoogle-search} metasearch engine.")))
|
| 1914 |
|
| 1915 |
|
| 1916 | |
| 1917 | |
| 1918 | |
| 1919 |
|
| 1920 | (define (go-webdav-shepherd-service args)
|
| 1921 | (list (shepherd-service
|
| 1922 | (documentation "go-webdav daemon.")
|
| 1923 | (provision '(go-webdav))
|
| 1924 | |
| 1925 | |
| 1926 | (requirement '(user-processes networking))
|
| 1927 | (start #~(make-forkexec-constructor
|
| 1928 | (list (string-append #$go-webdav "/bin/webdav-server")
|
| 1929 | #$@args)
|
| 1930 | #:user "go-webdav" #:group "go-webdav"))
|
| 1931 | (stop #~(make-kill-destructor)))))
|
| 1932 |
|
| 1933 | (define go-webdav-account-service
|
| 1934 | (list (user-group (name "go-webdav") (system? #t))
|
| 1935 | (user-account
|
| 1936 | (name "go-webdav")
|
| 1937 | (group "go-webdav")
|
| 1938 | (system? #t)
|
| 1939 | (comment "go-webdav daemon user")
|
| 1940 | (home-directory "/var/empty")
|
| 1941 | (shell (file-append shadow "/sbin/nologin")))))
|
| 1942 |
|
| 1943 | (define-public go-webdav-service-type
|
| 1944 | (service-type (name 'go-webdav)
|
| 1945 | (description "Run the go-webdav WebDAV server.")
|
| 1946 | (extensions
|
| 1947 | (list (service-extension account-service-type
|
| 1948 | (const go-webdav-account-service))
|
| 1949 | (service-extension shepherd-root-service-type
|
| 1950 | go-webdav-shepherd-service)))
|
| 1951 | (compose concatenate)
|
| 1952 | (default-value '("-addr" "127.0.0.1:8080"))))
|
| 1953 |
|
| 1954 |
|
| 1955 | |
| 1956 | |
| 1957 | |
| 1958 |
|
| 1959 | (define-record-type* <patchwork-database-configuration>
|
| 1960 | patchwork-database-configuration make-patchwork-database-configuration
|
| 1961 | patchwork-database-configuration?
|
| 1962 | (engine patchwork-database-configuration-engine
|
| 1963 | (default "django.db.backends.postgresql_psycopg2"))
|
| 1964 | (name patchwork-database-configuration-name
|
| 1965 | (default "patchwork"))
|
| 1966 | (user patchwork-database-configuration-user
|
| 1967 | (default "httpd"))
|
| 1968 | (password patchwork-database-configuration-password
|
| 1969 | (default ""))
|
| 1970 | (host patchwork-database-configuration-host
|
| 1971 | (default ""))
|
| 1972 | (port patchwork-database-configuration-port
|
| 1973 | (default "")))
|
| 1974 |
|
| 1975 | (define-record-type* <patchwork-settings-module>
|
| 1976 | patchwork-settings-module make-patchwork-settings-module
|
| 1977 | patchwork-settings-module?
|
| 1978 | (database-configuration patchwork-settings-module-database-configuration
|
| 1979 | (default (patchwork-database-configuration)))
|
| 1980 | (secret-key-file patchwork-settings-module-secret-key-file
|
| 1981 | (default "/etc/patchwork/django-secret-key"))
|
| 1982 | (allowed-hosts patchwork-settings-module-allowed-hosts)
|
| 1983 | (default-from-email patchwork-settings-module-default-from-email)
|
| 1984 | (static-url patchwork-settings-module-static-url
|
| 1985 | (default "/static/"))
|
| 1986 | (admins patchwork-settings-module-admins
|
| 1987 | (default '()))
|
| 1988 | (debug? patchwork-settings-module-debug?
|
| 1989 | (default #f))
|
| 1990 | (enable-rest-api? patchwork-settings-module-enable-rest-api?
|
| 1991 | (default #t))
|
| 1992 | (enable-xmlrpc? patchwork-settings-module-enable-xmlrpc?
|
| 1993 | (default #t))
|
| 1994 | (force-https-links? patchwork-settings-module-force-https-links?
|
| 1995 | (default #t))
|
| 1996 | (extra-settings patchwork-settings-module-extra-settings
|
| 1997 | (default "")))
|
| 1998 |
|
| 1999 | (define-record-type* <patchwork-configuration>
|
| 2000 | patchwork-configuration make-patchwork-configuration
|
| 2001 | patchwork-configuration?
|
| 2002 | (patchwork patchwork-configuration-patchwork
|
| 2003 | (default patchwork))
|
| 2004 | (domain patchwork-configuration-domain)
|
| 2005 | (settings-module patchwork-configuration-settings-module)
|
| 2006 | (static-path patchwork-configuration-static-url
|
| 2007 | (default "/static/"))
|
| 2008 | (getmail-retriever-config getmail-retriever-config))
|
| 2009 |
|
| 2010 | |
| 2011 | |
| 2012 | (define-gexp-compiler (patchwork-settings-module-compiler
|
| 2013 | (file <patchwork-settings-module>) system target)
|
| 2014 | (match file
|
| 2015 | (($ <patchwork-settings-module> database-configuration secret-key-file
|
| 2016 | allowed-hosts default-from-email
|
| 2017 | static-url admins debug? enable-rest-api?
|
| 2018 | enable-xmlrpc? force-https-links?
|
| 2019 | extra-configuration)
|
| 2020 | (gexp->derivation
|
| 2021 | "patchwork-settings"
|
| 2022 | (with-imported-modules '((guix build utils))
|
| 2023 | #~(let ((output #$output))
|
| 2024 | (define (create-__init__.py filename)
|
| 2025 | (call-with-output-file filename
|
| 2026 | (lambda (port) (display "" port))))
|
| 2027 |
|
| 2028 | (use-modules (guix build utils)
|
| 2029 | (srfi srfi-1))
|
| 2030 |
|
| 2031 | (mkdir-p (string-append output "/guix/patchwork"))
|
| 2032 | (create-__init__.py
|
| 2033 | (string-append output "/guix/__init__.py"))
|
| 2034 | (create-__init__.py
|
| 2035 | (string-append output "/guix/patchwork/__init__.py"))
|
| 2036 |
|
| 2037 | (call-with-output-file
|
| 2038 | (string-append output "/guix/patchwork/settings.py")
|
| 2039 | (lambda (port)
|
| 2040 | (display
|
| 2041 | (string-append "from patchwork.settings.base import *
|
| 2042 |
|
| 2043 | # Configuration from Guix
|
| 2044 | with open('" #$secret-key-file "') as f:
|
| 2045 | SECRET_KEY = f.read().strip()
|
| 2046 |
|
| 2047 | ALLOWED_HOSTS = [
|
| 2048 | " #$(string-concatenate
|
| 2049 | (map (lambda (allowed-host)
|
| 2050 | (string-append " '" allowed-host "'\n"))
|
| 2051 | allowed-hosts))
|
| 2052 | "]
|
| 2053 |
|
| 2054 | DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
|
| 2055 |
|
| 2056 | DEFAULT_FROM_EMAIL = '" #$default-from-email "'
|
| 2057 | SERVER_EMAIL = DEFAULT_FROM_EMAIL
|
| 2058 | NOTIFICATION_FROM_EMAIL = DEFAULT_FROM_EMAIL
|
| 2059 |
|
| 2060 | ADMINS = [
|
| 2061 | " #$(string-concatenate
|
| 2062 | (map (match-lambda
|
| 2063 | ((name email-address)
|
| 2064 | (string-append
|
| 2065 | "('" name "','" email-address "'),")))
|
| 2066 | admins))
|
| 2067 | "]
|
| 2068 |
|
| 2069 | DEBUG = " #$(if debug? "True" "False") "
|
| 2070 |
|
| 2071 | ENABLE_REST_API = " #$(if enable-rest-api? "True" "False") "
|
| 2072 | ENABLE_XMLRPC = " #$(if enable-xmlrpc? "True" "False") "
|
| 2073 |
|
| 2074 | FORCE_HTTPS_LINKS = " #$(if force-https-links? "True" "False") "
|
| 2075 |
|
| 2076 | DATABASES = {
|
| 2077 | 'default': {
|
| 2078 | " #$(match database-configuration
|
| 2079 | (($ <patchwork-database-configuration>
|
| 2080 | engine name user password host port)
|
| 2081 | (string-append
|
| 2082 | " 'ENGINE': '" engine "',\n"
|
| 2083 | " 'NAME': '" name "',\n"
|
| 2084 | " 'USER': '" user "',\n"
|
| 2085 | " 'PASSWORD': '" password "',\n"
|
| 2086 | " 'HOST': '" host "',\n"
|
| 2087 | " 'PORT': '" port "',\n"))) "
|
| 2088 | },
|
| 2089 | }
|
| 2090 |
|
| 2091 | " #$(if static-url
|
| 2092 | #~(string-append "STATIC_URL = '" #$static-url "'")
|
| 2093 | "") "
|
| 2094 |
|
| 2095 | STATICFILES_STORAGE = (
|
| 2096 | 'django.contrib.staticfiles.storage.StaticFilesStorage'
|
| 2097 | )
|
| 2098 |
|
| 2099 | # Guix Extra Configuration
|
| 2100 | " #$extra-configuration "
|
| 2101 | ") port)))
|
| 2102 | #t))
|
| 2103 | #:local-build? #t))))
|
| 2104 |
|
| 2105 | (define patchwork-virtualhost
|
| 2106 | (match-lambda
|
| 2107 | (($ <patchwork-configuration> patchwork domain
|
| 2108 | settings-module static-path
|
| 2109 | getmail-retriever-config)
|
| 2110 | (define wsgi.py
|
| 2111 | (file-append patchwork
|
| 2112 | (string-append
|
| 2113 | "/lib/python"
|
| 2114 | (version-major+minor
|
| 2115 | (package-version python))
|
| 2116 | "/site-packages/patchwork/wsgi.py")))
|
| 2117 |
|
| 2118 | (httpd-virtualhost
|
| 2119 | "*:8080"
|
| 2120 | `("ServerAdmin [email protected]`
|
| 2121 | ServerName " ,domain "
|
| 2122 |
|
| 2123 | LogFormat \"%v %h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-Agent}i\\\"\" customformat
|
| 2124 | LogLevel info
|
| 2125 | CustomLog \"/var/log/httpd/" ,domain "-access_log\" customformat
|
| 2126 |
|
| 2127 | ErrorLog /var/log/httpd/error.log
|
| 2128 |
|
| 2129 | WSGIScriptAlias / " ,wsgi.py "
|
| 2130 | 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 "
|
| 2131 | WSGIProcessGroup " ,(package-name patchwork) "
|
| 2132 | WSGIPassAuthorization On
|
| 2133 |
|
| 2134 | <Files " ,wsgi.py ">
|
| 2135 | Require all granted
|
| 2136 | </Files>
|
| 2137 |
|
| 2138 | " ,@(if static-path
|
| 2139 | `("Alias " ,static-path " " ,patchwork "/share/patchwork/htdocs/")
|
| 2140 | '())
|
| 2141 | "
|
| 2142 | <Directory \"/srv/http/" ,domain "/\">
|
| 2143 | AllowOverride None
|
| 2144 | Options MultiViews Indexes SymlinksIfOwnerMatch IncludesNoExec
|
| 2145 | Require method GET POST OPTIONS
|
| 2146 | </Directory>")))))
|
| 2147 |
|
| 2148 | (define (patchwork-httpd-configuration patchwork-configuration)
|
| 2149 | (list "WSGISocketPrefix /var/run/mod_wsgi"
|
| 2150 | (list "LoadModule wsgi_module "
|
| 2151 | (file-append mod-wsgi "/modules/mod_wsgi.so"))
|
| 2152 | (patchwork-virtualhost patchwork-configuration)))
|
| 2153 |
|
| 2154 | (define (patchwork-django-admin-gexp patchwork settings-module)
|
| 2155 | #~(lambda command
|
| 2156 | (zero? (spawn-command
|
| 2157 | `(#$(file-append patchwork "/bin/patchwork-admin")
|
| 2158 | ,@command)
|
| 2159 | #:user "httpd"
|
| 2160 | #:group "httpd"
|
| 2161 | #:environment-variables
|
| 2162 | `("DJANGO_SETTINGS_MODULE=guix.patchwork.settings"
|
| 2163 | ,(string-append "PYTHONPATH=" #$settings-module))))))
|
| 2164 |
|
| 2165 | (define (patchwork-django-admin-action patchwork settings-module)
|
| 2166 | (shepherd-action
|
| 2167 | (name 'django-admin)
|
| 2168 | (documentation
|
| 2169 | "Run a django admin command for patchwork")
|
| 2170 | (procedure (patchwork-django-admin-gexp patchwork settings-module))))
|
| 2171 |
|
| 2172 | (define patchwork-shepherd-services
|
| 2173 | (match-lambda
|
| 2174 | (($ <patchwork-configuration> patchwork domain
|
| 2175 | settings-module static-path
|
| 2176 | getmail-retriever-config)
|
| 2177 | (define secret-key-file-creation-gexp
|
| 2178 | (if (patchwork-settings-module? settings-module)
|
| 2179 | (with-extensions (list guile-gcrypt)
|
| 2180 | #~(let ((secret-key-file
|
| 2181 | #$(patchwork-settings-module-secret-key-file
|
| 2182 | settings-module))
|
| 2183 | (random-token
|
| 2184 | (@ (gcrypt random) random-token)))
|
| 2185 | (unless (file-exists? secret-key-file)
|
| 2186 | (mkdir-p (dirname secret-key-file))
|
| 2187 | (call-with-output-file secret-key-file
|
| 2188 | (lambda (port)
|
| 2189 | (display (random-token 30 'very-strong) port)))
|
| 2190 | (let* ((pw (getpwnam "httpd"))
|
| 2191 | (uid (passwd:uid pw))
|
| 2192 | (gid (passwd:gid pw)))
|
| 2193 | (chown secret-key-file uid gid)
|
| 2194 | (chmod secret-key-file #o400)))))
|
| 2195 | #~()))
|
| 2196 |
|
| 2197 | (list (shepherd-service
|
| 2198 | (requirement '(postgres))
|
| 2199 | (provision (list (string->symbol
|
| 2200 | (string-append (package-name patchwork)
|
| 2201 | "-setup"))))
|
| 2202 | (start
|
| 2203 | #~(lambda ()
|
| 2204 | (define run-django-admin-command
|
| 2205 | #$(patchwork-django-admin-gexp patchwork
|
| 2206 | settings-module))
|
| 2207 |
|
| 2208 | #$secret-key-file-creation-gexp
|
| 2209 |
|
| 2210 | (run-django-admin-command "migrate")))
|
| 2211 | (stop #~(const #f))
|
| 2212 | (actions
|
| 2213 | (list (patchwork-django-admin-action patchwork
|
| 2214 | settings-module)))
|
| 2215 | (respawn? #f)
|
| 2216 | (documentation "Setup Patchwork."))))))
|
| 2217 |
|
| 2218 | (define patchwork-getmail-configs
|
| 2219 | (match-lambda
|
| 2220 | (($ <patchwork-configuration> patchwork domain
|
| 2221 | settings-module static-path
|
| 2222 | getmail-retriever-config)
|
| 2223 | (list
|
| 2224 | (getmail-configuration
|
| 2225 | (name (string->symbol (package-name patchwork)))
|
| 2226 | (user "httpd")
|
| 2227 | (directory (string-append
|
| 2228 | "/var/lib/getmail/" (package-name patchwork)))
|
| 2229 | (rcfile
|
| 2230 | (getmail-configuration-file
|
| 2231 | (retriever getmail-retriever-config)
|
| 2232 | (destination
|
| 2233 | (getmail-destination-configuration
|
| 2234 | (type "MDA_external")
|
| 2235 | (path (file-append patchwork "/bin/patchwork-admin"))
|
| 2236 | (extra-parameters
|
| 2237 | '((arguments . ("parsemail"))))))
|
| 2238 | (options
|
| 2239 | (getmail-options-configuration
|
| 2240 | (read-all #f)
|
| 2241 | (delivered-to #f)
|
| 2242 | (received #f)))))
|
| 2243 | (idle (assq-ref
|
| 2244 | (getmail-retriever-configuration-extra-parameters
|
| 2245 | getmail-retriever-config)
|
| 2246 | 'mailboxes))
|
| 2247 | (environment-variables
|
| 2248 | (list "DJANGO_SETTINGS_MODULE=guix.patchwork.settings"
|
| 2249 | #~(string-append "PYTHONPATH=" #$settings-module))))))))
|
| 2250 |
|
| 2251 | (define patchwork-service-type
|
| 2252 | (service-type
|
| 2253 | (name 'patchwork-setup)
|
| 2254 | (extensions
|
| 2255 | (list (service-extension httpd-service-type
|
| 2256 | patchwork-httpd-configuration)
|
| 2257 | (service-extension shepherd-root-service-type
|
| 2258 | patchwork-shepherd-services)
|
| 2259 | (service-extension getmail-service-type
|
| 2260 | patchwork-getmail-configs)))
|
| 2261 | (description
|
| 2262 | "Patchwork patch tracking system.")))
|
| 2263 |
|
| 2264 |
|
| 2265 | |
| 2266 | |
| 2267 | |
| 2268 |
|
| 2269 | (define (sogogi-serialize-section section-name value fields)
|
| 2270 | (let ((first-field (car fields)))
|
| 2271 | #~(format #f "~a ~a {~%~a}~%"
|
| 2272 | #$(object->string section-name)
|
| 2273 | #$((configuration-field-getter first-field) value)
|
| 2274 | #$(serialize-configuration value (cdr fields)))))
|
| 2275 |
|
| 2276 | (define (sogogi-serialize-field field-name value)
|
| 2277 | (let ((field (object->string field-name)))
|
| 2278 | #~(format #f "~a ~a~%" #$field #$value)))
|
| 2279 |
|
| 2280 | (define sogogi-serialize-string sogogi-serialize-field)
|
| 2281 | (define (sogogi-serialize-list-of-strings field-name value)
|
| 2282 | #~(string-append
|
| 2283 | #$@(map (cut sogogi-serialize-string field-name <>)
|
| 2284 | value)))
|
| 2285 |
|
| 2286 | (define-maybe string (prefix sogogi-))
|
| 2287 | (define-maybe list-of-strings (prefix sogogi-))
|
| 2288 |
|
| 2289 | (define-configuration sogogi-user
|
| 2290 | (name
|
| 2291 | maybe-string
|
| 2292 | "Name of the user.")
|
| 2293 |
|
| 2294 | (password
|
| 2295 | maybe-string
|
| 2296 | "Password of the user.")
|
| 2297 |
|
| 2298 | (prefix sogogi-))
|
| 2299 |
|
| 2300 | (define (sogogi-serialize-sogogi-user field-name value)
|
| 2301 | (sogogi-serialize-section field-name value sogogi-user-fields))
|
| 2302 |
|
| 2303 | (define-configuration sogogi-location
|
| 2304 | (path
|
| 2305 | string
|
| 2306 | "HTTP path at which the directory will be exposed.")
|
| 2307 |
|
| 2308 | (dir
|
| 2309 | string
|
| 2310 | "Path to local directory to serve.")
|
| 2311 |
|
| 2312 | (grant
|
| 2313 | maybe-list-of-strings
|
| 2314 | "Grant remote users access to the directory.")
|
| 2315 |
|
| 2316 | (prefix sogogi-))
|
| 2317 |
|
| 2318 | (define (sogogi-serialize-sogogi-location field-name value)
|
| 2319 | (sogogi-serialize-section field-name value sogogi-location-fields))
|
| 2320 |
|
| 2321 | (define (sogogi-serialize-list-of-sogogi-location field-name value)
|
| 2322 | #~(string-append #$@(map (cut sogogi-serialize-sogogi-location field-name <>) value)))
|
| 2323 |
|
| 2324 | (define (sogogi-serialize-list-of-sogogi-user field-name value)
|
| 2325 | #~(string-append #$@(map (cut sogogi-serialize-sogogi-user field-name <>) value)))
|
| 2326 |
|
| 2327 | (define list-of-sogogi-user? (list-of sogogi-user?))
|
| 2328 | (define list-of-sogogi-location? (list-of sogogi-location?))
|
| 2329 |
|
| 2330 | (define-configuration sogogi-configuration
|
| 2331 | (listen
|
| 2332 | (string "localhost:8080")
|
| 2333 | "Listening address.")
|
| 2334 |
|
| 2335 | (location
|
| 2336 | (list-of-sogogi-location '())
|
| 2337 | "Local directories to expose via a HTTP path.")
|
| 2338 |
|
| 2339 | (user
|
| 2340 | (list-of-sogogi-user '())
|
| 2341 | "Users with access to the location.")
|
| 2342 |
|
| 2343 | (prefix sogogi-))
|
| 2344 |
|
| 2345 | (define (sogogi-config-file config)
|
| 2346 | (mixed-text-file "sogogi.conf"
|
| 2347 | (serialize-configuration
|
| 2348 | config
|
| 2349 | sogogi-configuration-fields)))
|
| 2350 |
|
| 2351 | (define (sogogi-shepherd-service config)
|
| 2352 | (let ((config-file (sogogi-config-file config)))
|
| 2353 | (list (shepherd-service
|
| 2354 | (documentation "Sogogi daemon.")
|
| 2355 | (provision '(sogogi))
|
| 2356 | |
| 2357 | |
| 2358 | (requirement '(user-processes networking))
|
| 2359 | (actions (list (shepherd-configuration-action config-file)))
|
| 2360 | (start #~(make-forkexec-constructor
|
| 2361 | (list (string-append #$sogogi "/bin/sogogi")
|
| 2362 | "-config" #$config-file)
|
| 2363 | #:user "sogogi" #:group "sogogi"))
|
| 2364 | (stop #~(make-kill-destructor))))))
|
| 2365 |
|
| 2366 | (define sogogi-account-service
|
| 2367 | (list (user-group (name "sogogi") (system? #t))
|
| 2368 | (user-account
|
| 2369 | (name "sogogi")
|
| 2370 | (group "sogogi")
|
| 2371 | (system? #t)
|
| 2372 | (comment "Sogogi daemon user")
|
| 2373 | (home-directory "/var/empty")
|
| 2374 | (shell (file-append shadow "/sbin/nologin")))))
|
| 2375 |
|
| 2376 | (define sogogi-service-type
|
| 2377 | (service-type (name 'sogogi)
|
| 2378 | (description "Run the sogogi WebDAV server.")
|
| 2379 | (extensions
|
| 2380 | (list (service-extension account-service-type
|
| 2381 | (const sogogi-account-service))
|
| 2382 | (service-extension shepherd-root-service-type
|
| 2383 | sogogi-shepherd-service)))
|
| 2384 | (compose concatenate)
|
| 2385 | (default-value (sogogi-configuration))))
|
| 2386 |
|
| 2387 |
|
| 2388 | |
| 2389 | |
| 2390 | |
| 2391 |
|
| 2392 | (define-record-type* <mumi-configuration>
|
| 2393 | mumi-configuration make-mumi-configuration
|
| 2394 | mumi-configuration?
|
| 2395 | (mumi mumi-configuration-mumi (default mumi))
|
| 2396 | (data-directory mumi-configuration-data-directory
|
| 2397 | (default "/var/mumi/data"))
|
| 2398 | (rsync-remote mumi-configuration-rsync-remote)
|
| 2399 | (rsync-flags mumi-configuration-rsync-flags
|
| 2400 | (default '()))
|
| 2401 | (rsync-and-index-event mumi-configuration-rsync-and-index-event
|
| 2402 | |
| 2403 | (default #~(calendar-event #:minutes '#$(iota 12 0 5))))
|
| 2404 | (mailer? mumi-configuration-mailer? (default #t))
|
| 2405 | (sender mumi-configuration-sender (default #f))
|
| 2406 | (smtp mumi-configuration-smtp (default #f))
|
| 2407 | (packages mumi-configuration-packages (default '())))
|
| 2408 |
|
| 2409 | (define-record-type* <mumi-package-configuration>
|
| 2410 | mumi-package-configuration make-mumi-package-configuration
|
| 2411 | mumi-package-configuration?
|
| 2412 | (name mumi-package-configuration-name)
|
| 2413 | (display-name mumi-package-configuration-display-name
|
| 2414 | (default #f))
|
| 2415 | (debbugs-packages mumi-package-configuration-debbugs-packages)
|
| 2416 | (bug-email-address mumi-package-configuration-bug-email-address
|
| 2417 | (default #f))
|
| 2418 | (patch-email-address mumi-package-configuration-patch-email-address
|
| 2419 | (default #f))
|
| 2420 | (file-tags mumi-package-configuration-file-tags
|
| 2421 | (default '())))
|
| 2422 |
|
| 2423 | (define %mumi-activation
|
| 2424 | (with-imported-modules '((guix build utils))
|
| 2425 | #~(begin
|
| 2426 | (use-modules (guix build utils))
|
| 2427 |
|
| 2428 | (mkdir-p "/var/mumi/db")
|
| 2429 | (mkdir-p "/var/mumi/mails")
|
| 2430 | (let* ((pw (getpwnam "mumi"))
|
| 2431 | (uid (passwd:uid pw))
|
| 2432 | (gid (passwd:gid pw)))
|
| 2433 | (chown "/var/mumi" uid gid)
|
| 2434 | (chown "/var/mumi/mails" uid gid)
|
| 2435 | (chown "/var/mumi/db" uid gid)))))
|
| 2436 |
|
| 2437 | (define %mumi-accounts
|
| 2438 | (list (user-group (name "mumi") (system? #t))
|
| 2439 | (user-account
|
| 2440 | (name "mumi")
|
| 2441 | (group "mumi")
|
| 2442 | (system? #t)
|
| 2443 | (comment "Mumi web server")
|
| 2444 | (home-directory "/var/empty")
|
| 2445 | (shell (file-append shadow "/sbin/nologin")))))
|
| 2446 |
|
| 2447 | (define %mumi-log "/var/log/mumi.log")
|
| 2448 |
|
| 2449 | (define %mumi-mailer-log "/var/log/mumi.mailer.log")
|
| 2450 |
|
| 2451 | (define %mumi-rsync-and-index-log "/var/log/mumi.rsync-and-index.log")
|
| 2452 |
|
| 2453 | (define mumi-package-configuration->alist
|
| 2454 | (match-record-lambda <mumi-package-configuration>
|
| 2455 | (name display-name debbugs-packages bug-email-address
|
| 2456 | patch-email-address file-tags)
|
| 2457 | `(,name
|
| 2458 | ,@(if display-name
|
| 2459 | `((display-name . ,display-name))
|
| 2460 | '())
|
| 2461 | ,@(if debbugs-packages
|
| 2462 | `((debbugs-packages . ,debbugs-packages))
|
| 2463 | '())
|
| 2464 | ,@(if bug-email-address
|
| 2465 | `((bug-email-address . ,bug-email-address))
|
| 2466 | '())
|
| 2467 | ,@(if patch-email-address
|
| 2468 | `((patch-email-address . ,patch-email-address))
|
| 2469 | '())
|
| 2470 | ,@(match file-tags
|
| 2471 | (() '())
|
| 2472 | (_ `((file-tags . ,file-tags)))))))
|
| 2473 |
|
| 2474 | (define mumi-config-file
|
| 2475 | (match-record-lambda <mumi-configuration>
|
| 2476 | (mailer? packages)
|
| 2477 | (computed-file "mumi.conf"
|
| 2478 | #~(begin
|
| 2479 | (use-modules (srfi srfi-26))
|
| 2480 |
|
| 2481 | (call-with-output-file #$output
|
| 2482 | (cut write
|
| 2483 | '((mailer-enabled? . #$mailer?)
|
| 2484 | (packages
|
| 2485 | . #$(map mumi-package-configuration->alist
|
| 2486 | packages)))
|
| 2487 | <>))))))
|
| 2488 |
|
| 2489 | (define (mumi-rsync-and-index config)
|
| 2490 | (match-record config <mumi-configuration>
|
| 2491 | (data-directory rsync-remote rsync-flags)
|
| 2492 | (program-file "mumi-rsync-and-index"
|
| 2493 | (with-imported-modules '((guix build utils))
|
| 2494 | #~(begin
|
| 2495 | (use-modules (guix build utils))
|
| 2496 |
|
| 2497 | (invoke #$(file-append rsync "/bin/rsync")
|
| 2498 | "--delete" "--archive" "--verbose"
|
| 2499 | #$@rsync-flags
|
| 2500 | #$rsync-remote
|
| 2501 | #$data-directory)
|
| 2502 | (invoke #$(file-append mumi "/bin/mumi") "fetch"
|
| 2503 | (string-append "--config="
|
| 2504 | #$(mumi-config-file config))))))))
|
| 2505 |
|
| 2506 | (define (mumi-shepherd-services config)
|
| 2507 | (define environment
|
| 2508 | #~(list "LC_ALL=en_US.utf8"
|
| 2509 | (string-append "GUIX_LOCPATH="
|
| 2510 | #$(libc-utf8-locales-for-target)
|
| 2511 | "/lib/locale")))
|
| 2512 |
|
| 2513 | (match-record config <mumi-configuration>
|
| 2514 | (mumi rsync-and-index-event mailer? sender smtp)
|
| 2515 | (list (shepherd-service
|
| 2516 | (provision '(mumi))
|
| 2517 | (documentation "Mumi bug-tracking web interface.")
|
| 2518 | (requirement '(user-processes networking))
|
| 2519 | (start #~(make-forkexec-constructor
|
| 2520 | `(#$(file-append mumi "/bin/mumi") "web"
|
| 2521 | ,(string-append "--config="
|
| 2522 | #$(mumi-config-file config)))
|
| 2523 | #:environment-variables #$environment
|
| 2524 | #:user "mumi" #:group "mumi"
|
| 2525 | #:log-file #$%mumi-log))
|
| 2526 | (stop #~(make-kill-destructor)))
|
| 2527 | (shepherd-service
|
| 2528 | (provision '(mumi-rsync-and-index))
|
| 2529 | (modules '((shepherd service timer)))
|
| 2530 | (start #~(make-timer-constructor
|
| 2531 | #$rsync-and-index-event
|
| 2532 | (command (list #$(mumi-rsync-and-index config)))
|
| 2533 | #:log-file #$%mumi-rsync-and-index-log
|
| 2534 | #:max-duration (* 2 60 60)
|
| 2535 | #:wait-for-termination? #t))
|
| 2536 | (stop #~(make-timer-destructor))
|
| 2537 | (actions (list shepherd-trigger-action))
|
| 2538 | (documentation "Rsync and index the GNU Debbugs data"))
|
| 2539 | (shepherd-service
|
| 2540 | (provision '(mumi-mailer))
|
| 2541 | (documentation "Mumi bug-tracking web interface mailer.")
|
| 2542 | (requirement '(user-processes networking))
|
| 2543 | (start #~(make-forkexec-constructor
|
| 2544 | `(#$(file-append mumi "/bin/mumi") "mailer"
|
| 2545 | ,(string-append "--config="
|
| 2546 | #$(mumi-config-file config))
|
| 2547 | ,@(if #$sender
|
| 2548 | (list (string-append "--sender=" #$sender))
|
| 2549 | '())
|
| 2550 | ,@(if #$smtp
|
| 2551 | (list (string-append "--smtp=" #$smtp))
|
| 2552 | '()))
|
| 2553 | #:environment-variables #$environment
|
| 2554 | #:user "mumi" #:group "mumi"
|
| 2555 | #:log-file #$%mumi-mailer-log))
|
| 2556 | (stop #~(make-kill-destructor))))))
|
| 2557 |
|
| 2558 | (define mumi-service-type
|
| 2559 | (service-type
|
| 2560 | (name 'mumi)
|
| 2561 | (extensions
|
| 2562 | (list (service-extension activation-service-type
|
| 2563 | (const %mumi-activation))
|
| 2564 | (service-extension account-service-type
|
| 2565 | (const %mumi-accounts))
|
| 2566 | (service-extension shepherd-root-service-type
|
| 2567 | mumi-shepherd-services)))
|
| 2568 | (description
|
| 2569 | "Run Mumi, a Web interface to the Debbugs bug-tracking server.")))
|
| 2570 |
|
| 2571 | (define %default-gmnisrv-config-file
|
| 2572 | (plain-file "gmnisrv.ini" "
|
| 2573 | listen=0.0.0.0:1965 [::]:1965
|
| 2574 |
|
| 2575 | [:tls]
|
| 2576 | store=/var/lib/gemini/certs
|
| 2577 |
|
| 2578 | organization=gmnisrv on Guix user
|
| 2579 |
|
| 2580 | [localhost]
|
| 2581 | root=/srv/gemini
|
| 2582 | "))
|
| 2583 |
|
| 2584 | (define-record-type* <gmnisrv-configuration>
|
| 2585 | gmnisrv-configuration make-gmnisrv-configuration
|
| 2586 | gmnisrv-configuration?
|
| 2587 | (package gmnisrv-configuration-package
|
| 2588 | (default gmnisrv))
|
| 2589 | (config-file gmnisrv-configuration-config-file
|
| 2590 | (default %default-gmnisrv-config-file)))
|
| 2591 |
|
| 2592 | (define gmnisrv-shepherd-service
|
| 2593 | (match-lambda
|
| 2594 | (($ <gmnisrv-configuration> package config-file)
|
| 2595 | (list (shepherd-service
|
| 2596 | (provision '(gmnisrv))
|
| 2597 | (requirement '(user-processes networking))
|
| 2598 | (documentation "Run the gmnisrv Gemini server.")
|
| 2599 | (start (let ((gmnisrv (file-append package "/bin/gmnisrv")))
|
| 2600 | #~(make-forkexec-constructor
|
| 2601 | (list #$gmnisrv "-C" #$config-file)
|
| 2602 | #:user "gmnisrv" #:group "gmnisrv"
|
| 2603 | #:log-file "/var/log/gmnisrv.log")))
|
| 2604 | (stop #~(make-kill-destructor)))))))
|
| 2605 |
|
| 2606 | (define %gmnisrv-accounts
|
| 2607 | (list (user-group (name "gmnisrv") (system? #t))
|
| 2608 | (user-account
|
| 2609 | (name "gmnisrv")
|
| 2610 | (group "gmnisrv")
|
| 2611 | (system? #t)
|
| 2612 | (comment "gmnisrv Gemini server")
|
| 2613 | (home-directory "/var/empty")
|
| 2614 | (shell (file-append shadow "/sbin/nologin")))))
|
| 2615 |
|
| 2616 | (define %gmnisrv-activation
|
| 2617 | (with-imported-modules '((guix build utils))
|
| 2618 | #~(begin
|
| 2619 | (use-modules (guix build utils))
|
| 2620 |
|
| 2621 | (mkdir-p "/var/lib/gemini/certs")
|
| 2622 | (let* ((pw (getpwnam "gmnisrv"))
|
| 2623 | (uid (passwd:uid pw))
|
| 2624 | (gid (passwd:gid pw)))
|
| 2625 | (chown "/var/lib/gemini" uid gid)
|
| 2626 | (chown "/var/lib/gemini/certs" uid gid)))))
|
| 2627 |
|
| 2628 | (define gmnisrv-service-type
|
| 2629 | (service-type
|
| 2630 | (name 'gmnisrv)
|
| 2631 | (extensions
|
| 2632 | (list (service-extension activation-service-type
|
| 2633 | (const %gmnisrv-activation))
|
| 2634 | (service-extension account-service-type
|
| 2635 | (const %gmnisrv-accounts))
|
| 2636 | (service-extension shepherd-root-service-type
|
| 2637 | gmnisrv-shepherd-service)))
|
| 2638 | (description
|
| 2639 | "Run the gmnisrv Gemini server.")
|
| 2640 | (default-value
|
| 2641 | (gmnisrv-configuration))))
|
| 2642 |
|
| 2643 | (define-record-type* <agate-configuration>
|
| 2644 | agate-configuration make-agate-configuration
|
| 2645 | agate-configuration?
|
| 2646 | (package agate-configuration-package
|
| 2647 | (default agate))
|
| 2648 | (content agate-configuration-content
|
| 2649 | (default "/srv/gemini"))
|
| 2650 | (certificates agate-configuration-certificates
|
| 2651 | (default "/srv/gemini-certs"))
|
| 2652 | (addresses agate-configuration-addresses
|
| 2653 | (default '("[::]:1965" "0.0.0.0:1965")))
|
| 2654 | (hostnames agate-configuration-hostnames
|
| 2655 | (default '()))
|
| 2656 | (languages agate-configuration-languages
|
| 2657 | (default #f))
|
| 2658 | (only-tls13? agate-configuration-only-tls13
|
| 2659 | (default #f))
|
| 2660 | (serve-secret? agate-configuration-serve-secret
|
| 2661 | (default #f))
|
| 2662 | (central-configuration? agate-configuration-central-configuration
|
| 2663 | (default #f))
|
| 2664 | (ed25519? agate-configuration-ed25519
|
| 2665 | (default #f))
|
| 2666 | (skip-port-check? agate-configuration-skip-port-check
|
| 2667 | (default #f))
|
| 2668 | (log-ip? agate-configuration-log-ip
|
| 2669 | (default #t))
|
| 2670 | (user agate-configuration-user
|
| 2671 | (default "agate"))
|
| 2672 | (group agate-configuration-group
|
| 2673 | (default "agate"))
|
| 2674 | (log-file agate-configuration-log
|
| 2675 | (default "/var/log/agate.log")))
|
| 2676 |
|
| 2677 | (define agate-shepherd-service
|
| 2678 | (match-lambda
|
| 2679 | (($ <agate-configuration> package content certificates addresses
|
| 2680 | hostnames languages only-tls13?
|
| 2681 | serve-secret? central-configuration?
|
| 2682 | ed25519? skip-port-check?
|
| 2683 | log-ip? user group log-file)
|
| 2684 | (list (shepherd-service
|
| 2685 | (provision '(agate))
|
| 2686 | (requirement '(user-processes networking))
|
| 2687 | (documentation "Run the agate Gemini server.")
|
| 2688 | (start (let ((agate (file-append package "/bin/agate")))
|
| 2689 | #~(make-forkexec-constructor
|
| 2690 | (list #$agate
|
| 2691 | "--content" #$content
|
| 2692 | "--certs" #$certificates
|
| 2693 | #$@(append-map
|
| 2694 | (lambda x (append '("--addr") x))
|
| 2695 | addresses)
|
| 2696 | #$@(append-map
|
| 2697 | (lambda x (append '("--hostname") x))
|
| 2698 | hostnames)
|
| 2699 | #$@(if languages
|
| 2700 | (list "--lang" languages)
|
| 2701 | '())
|
| 2702 | #$@(if serve-secret? '("--serve-secret") '())
|
| 2703 | #$@(if only-tls13? '("--only-tls13") '())
|
| 2704 | #$@(if central-configuration? '("--central-conf") '())
|
| 2705 | #$@(if ed25519? '("--ed25519") '())
|
| 2706 | #$@(if skip-port-check? '("--skip-port-check") '())
|
| 2707 | #$@(if log-ip? '("--log-ip") '()))
|
| 2708 | #:user #$user #:group #$group
|
| 2709 | #:log-file #$log-file)))
|
| 2710 | (stop #~(make-kill-destructor)))))))
|
| 2711 |
|
| 2712 | (define agate-accounts
|
| 2713 | (lambda (config)
|
| 2714 | (let ((group (agate-configuration-group config))
|
| 2715 | (user (agate-configuration-user config)))
|
| 2716 | `(,@(if (equal? group "agate")
|
| 2717 | '()
|
| 2718 | (list (user-group (name "agate") (system? #t))))
|
| 2719 | ,(user-group
|
| 2720 | (name group)
|
| 2721 | (system? #t))
|
| 2722 | ,(user-account
|
| 2723 | (name user)
|
| 2724 | (group group)
|
| 2725 | (supplementary-groups '("agate"))
|
| 2726 | (system? #t)
|
| 2727 | (comment "agate server user")
|
| 2728 | (home-directory "/var/empty")
|
| 2729 | (shell (file-append shadow "/sbin/nologin")))))))
|
| 2730 |
|
| 2731 | (define agate-service-type
|
| 2732 | (service-type
|
| 2733 | (name 'agate)
|
| 2734 | (extensions
|
| 2735 | (list (service-extension account-service-type
|
| 2736 | agate-accounts)
|
| 2737 | (service-extension shepherd-root-service-type
|
| 2738 | agate-shepherd-service)))
|
| 2739 | (default-value (agate-configuration))
|
| 2740 | (description "Run Agate, a simple Gemini protocol server written in
|
| 2741 | Rust.")))
|
| 2742 |
|
| 2743 | (define (serialize-string field-name val)
|
| 2744 | (format #f "~a=~a\n" field-name val))
|
| 2745 |
|
| 2746 | (define (string-or-file-path? val)
|
| 2747 | (string? val))
|
| 2748 | (define (serialize-string-or-file-path field-name val)
|
| 2749 | (serialize-string (if (absolute-file-name? val)
|
| 2750 | (format #f "~a_FILE" field-name) field-name) val))
|
| 2751 | (define-maybe string-or-file-path)
|
| 2752 |
|
| 2753 | (define (serialize-list field-name val)
|
| 2754 | (string-append (string-join val "\n") "\n"))
|
| 2755 | (define-maybe list)
|
| 2756 |
|
| 2757 | (define (serialize-boolean field-name val)
|
| 2758 | (if val (serialize-string field-name "1") (serialize-string field-name "0")))
|
| 2759 |
|
| 2760 | (define-configuration/no-serialization miniflux-configuration
|
| 2761 | (listen-address
|
| 2762 | (string "127.0.0.1:8080")
|
| 2763 | "Address to listen on.
|
| 2764 | Use absolute path like @code{\"/var/run/miniflux/miniflux.sock\"} for a Unix socket.")
|
| 2765 | (base-url
|
| 2766 | (string "http://127.0.0.1/")
|
| 2767 | "Base URL to generate HTML links and base path for cookies.")
|
| 2768 | (create-administrator-account?
|
| 2769 | (boolean #f)
|
| 2770 | "Create an initial administrator account.")
|
| 2771 | (administrator-account-name
|
| 2772 | maybe-string-or-file-path
|
| 2773 | "Initial administrator account name as a string or an absolute path to a file with a account name inside.")
|
| 2774 | (administrator-account-password
|
| 2775 | maybe-string-or-file-path
|
| 2776 | "Initial administrator account password as a string or an absolute path to a file with a password inside.")
|
| 2777 | (run-migrations?
|
| 2778 | (boolean #t)
|
| 2779 | "Run database migrations during application startup.")
|
| 2780 | (database-url
|
| 2781 | (string "host=/var/run/postgresql")
|
| 2782 | "PostgreSQL connection string.")
|
| 2783 | (user
|
| 2784 | (string "miniflux")
|
| 2785 | "User name for Postgresql and system account.")
|
| 2786 | (group
|
| 2787 | (string "miniflux")
|
| 2788 | "Group for the system account.")
|
| 2789 | (log-file
|
| 2790 | (string "/var/log/miniflux.log")
|
| 2791 | "Path to the log file.")
|
| 2792 | (extra-settings
|
| 2793 | maybe-list
|
| 2794 | "Extra configuration parameters as a list of strings."))
|
| 2795 |
|
| 2796 | (define (miniflux-serialize-configuration config)
|
| 2797 | (match-record config <miniflux-configuration>
|
| 2798 | (listen-address base-url create-administrator-account?
|
| 2799 | administrator-account-name administrator-account-password
|
| 2800 | run-migrations? database-url extra-settings)
|
| 2801 | (string-append (serialize-string "LISTEN_ADDR" listen-address)
|
| 2802 | (serialize-string "BASE_URL" base-url)
|
| 2803 | (serialize-boolean "CREATE_ADMIN" create-administrator-account?)
|
| 2804 | (serialize-maybe-string-or-file-path "ADMIN_USERNAME" administrator-account-name)
|
| 2805 | (serialize-maybe-string-or-file-path "ADMIN_PASSWORD" administrator-account-password)
|
| 2806 | (serialize-boolean "RUN_MIGRATIONS" run-migrations?)
|
| 2807 | (serialize-string "DATABASE_URL" database-url)
|
| 2808 | (serialize-maybe-list #f extra-settings))))
|
| 2809 |
|
| 2810 | (define (miniflux-configuration-file config)
|
| 2811 | (mixed-text-file "miniflux.conf" (miniflux-serialize-configuration config)))
|
| 2812 |
|
| 2813 | (define (pair->file-system-mapping pair previous)
|
| 2814 | (if (pair? pair)
|
| 2815 | (let ((path (car pair))
|
| 2816 | (writable (cdr pair)))
|
| 2817 | (if (or (and (string? path)
|
| 2818 | (absolute-file-name? path))
|
| 2819 | (computed-file? path))
|
| 2820 | (append previous (list (file-system-mapping
|
| 2821 | (source path)
|
| 2822 | (target source)
|
| 2823 | (writable? writable))))
|
| 2824 | previous))
|
| 2825 | previous))
|
| 2826 |
|
| 2827 | (define (miniflux-shepherd-service config)
|
| 2828 | (match-record config <miniflux-configuration>
|
| 2829 | (user group log-file database-url listen-address
|
| 2830 | administrator-account-name administrator-account-password)
|
| 2831 | (let ((config-file (miniflux-configuration-file config)))
|
| 2832 | (list (shepherd-service
|
| 2833 | (documentation "Run Miniflux server")
|
| 2834 | (provision '(miniflux))
|
| 2835 | (requirement '(postgres networking))
|
| 2836 | (start #~(make-forkexec-constructor
|
| 2837 | (list #$(least-authority-wrapper
|
| 2838 | (file-append miniflux "/bin/miniflux")
|
| 2839 | #:name "miniflux"
|
| 2840 | #:user user
|
| 2841 | #:group group
|
| 2842 | #:preserved-environment-variables
|
| 2843 | (append %default-preserved-environment-variables
|
| 2844 | '("SSL_CERT_FILE"))
|
| 2845 | #:mappings
|
| 2846 | (fold pair->file-system-mapping
|
| 2847 | '()
|
| 2848 | `((,log-file . #t)
|
| 2849 | (,config-file . #f)
|
| 2850 | ("/etc/ssl/certs/ca-certificates.crt" . #f)
|
| 2851 | (,administrator-account-name . #f)
|
| 2852 | (,administrator-account-password . #f)
|
| 2853 | (,(dirname listen-address) . #t)
|
| 2854 | ,(let* ((db-socket-match (string-match ".*host=(/[^ ]*).*" database-url))
|
| 2855 | (db-socket (if db-socket-match (match:substring db-socket-match 1) #f)))
|
| 2856 | (if db-socket
|
| 2857 | `(,db-socket . #t)))))
|
| 2858 | #:namespaces
|
| 2859 | (fold delq %namespaces '(net user)))
|
| 2860 | "-config-file"
|
| 2861 | #$config-file)
|
| 2862 | #:log-file #$log-file))
|
| 2863 | (stop #~(make-kill-destructor))
|
| 2864 | (actions
|
| 2865 | (list
|
| 2866 | (shepherd-configuration-action config-file))))))))
|
| 2867 |
|
| 2868 | (define (miniflux-accounts config)
|
| 2869 | (match-record config <miniflux-configuration>
|
| 2870 | (user group)
|
| 2871 | `(,(user-group
|
| 2872 | (name group)
|
| 2873 | (system? #t))
|
| 2874 | ,(user-account
|
| 2875 | (name user)
|
| 2876 | (group group)
|
| 2877 | (system? #t)
|
| 2878 | (comment "miniflux server user")
|
| 2879 | (home-directory "/var/empty")
|
| 2880 | (shell (file-append shadow "/sbin/nologin"))))))
|
| 2881 |
|
| 2882 | (define (miniflux-postgresql-role config)
|
| 2883 | (list (postgresql-role
|
| 2884 | (name (miniflux-configuration-user config))
|
| 2885 | (create-database? #t))))
|
| 2886 |
|
| 2887 | (define (miniflux-log-files config)
|
| 2888 | (list (miniflux-configuration-log-file config)))
|
| 2889 |
|
| 2890 | (define (miniflux-activation-service-type config)
|
| 2891 | (match-record config <miniflux-configuration>
|
| 2892 | (user listen-address)
|
| 2893 | #~(begin
|
| 2894 | (use-modules (gnu build activation))
|
| 2895 | (let ((user (getpwnam #$user)))
|
| 2896 | (if (absolute-file-name? #$listen-address)
|
| 2897 | (mkdir-p/perms (dirname #$listen-address) user #o755))))))
|
| 2898 |
|
| 2899 | (define miniflux-service-type
|
| 2900 | (service-type
|
| 2901 | (name 'miniflux)
|
| 2902 | (default-value (miniflux-configuration))
|
| 2903 | (extensions
|
| 2904 | (list (service-extension account-service-type
|
| 2905 | miniflux-accounts)
|
| 2906 | (service-extension postgresql-role-service-type
|
| 2907 | miniflux-postgresql-role)
|
| 2908 | (service-extension shepherd-root-service-type
|
| 2909 | miniflux-shepherd-service)
|
| 2910 | (service-extension log-rotation-service-type
|
| 2911 | miniflux-log-files)
|
| 2912 | (service-extension activation-service-type
|
| 2913 | miniflux-activation-service-type)))
|
| 2914 | (description "Run Miniflux, minimalist feed reader")))
|