;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu services guix)
+ #:use-module (srfi srfi-1)
#:use-module (ice-9 match)
#:use-module (guix gexp)
#:use-module (guix records)
+ #:use-module (guix packages)
#:use-module ((gnu packages base)
#:select (glibc-utf8-locales))
#:use-module (gnu packages admin)
+ #:use-module (gnu packages databases)
#:use-module (gnu packages web)
+ #:use-module (gnu packages guile)
+ #:use-module (gnu packages guile-xyz)
+ #:use-module (gnu packages package-management)
#:use-module (gnu services)
#:use-module (gnu services base)
#:use-module (gnu services admin)
#:use-module (gnu services shepherd)
#:use-module (gnu services getmail)
#:use-module (gnu system shadow)
- #:export (<guix-data-service-configuration>
+ #:export (guix-build-coordinator-configuration
+ guix-build-coordinator-configuration?
+ guix-build-coordinator-configuration-package
+ guix-build-coordinator-configuration-user
+ guix-build-coordinator-configuration-group
+ guix-build-coordinator-configuration-datastore-uri-string
+ guix-build-coordinator-configuration-agent-communication-uri-string
+ guix-build-coordinator-configuration-client-communication-uri-string
+ guix-build-coordinator-configuration-allocation-strategy
+ guix-build-coordinator-configuration-hooks
+ guix-build-coordinator-configuration-guile
+
+ guix-build-coordinator-service-type
+
+ guix-build-coordinator-agent-configuration
+ guix-build-coordinator-agent-configuration?
+ guix-build-coordinator-agent-configuration-package
+ guix-build-coordinator-agent-configuration-user
+ guix-build-coordinator-agent-configuration-coordinator
+ guix-build-coordinator-agent-configuration-authentication
+ guix-build-coordinator-agent-configuration-systems
+ guix-build-coordinator-agent-configuration-max-parallel-builds
+ guix-build-coordinator-agent-configuration-max-1min-load-average
+ guix-build-coordinator-agent-configuration-derivation-substitute-urls
+ guix-build-coordinator-agent-configuration-non-derivation-substitute-urls
+
+ guix-build-coordinator-agent-password-auth
+ guix-build-coordinator-agent-password-auth?
+ guix-build-coordinator-agent-password-auth-uuid
+ guix-build-coordinator-agent-password-auth-password
+
+ guix-build-coordinator-agent-password-file-auth
+ guix-build-coordinator-agent-password-file-auth?
+ guix-build-coordinator-agent-password-file-auth-uuid
+ guix-build-coordinator-agent-password-file-auth-password-file
+
+ guix-build-coordinator-agent-dynamic-auth
+ guix-build-coordinator-agent-dynamic-auth?
+ guix-build-coordinator-agent-dynamic-auth-agent-name
+ guix-build-coordinator-agent-dynamic-auth-token
+
+ guix-build-coordinator-agent-dynamic-auth-with-file
+ guix-build-coordinator-agent-dynamic-auth-with-file?
+ guix-build-coordinator-agent-dynamic-auth-with-file-agent-name
+ guix-build-coordinator-agent-dynamic-auth-with-file-token-file
+
+ guix-build-coordinator-agent-service-type
+
+ guix-build-coordinator-queue-builds-configuration
+ guix-build-coordinator-queue-builds-configuration?
+ guix-build-coordinator-queue-builds-configuration-package
+ guix-build-coordinator-queue-builds-configuration-user
+ guix-build-coordinator-queue-builds-coordinator
+ guix-build-coordinator-queue-builds-configuration-systems
+ guix-build-coordinator-queue-builds-configuration-system-and-targets
+ guix-build-coordinator-queue-builds-configuration-guix-data-service
+ guix-build-coordinator-queue-builds-configuration-processed-commits-file
+
+ guix-build-coordinator-queue-builds-service-type
+
+ <guix-data-service-configuration>
guix-data-service-configuration
guix-data-service-configuration?
guix-data-service-package
;;;; Commentary:
;;;
-;;; This module implements a service that to run instances of the Guix Data
-;;; Service, which provides data about Guix over time.
+;;; Services specifically related to GNU Guix.
;;;
;;;; Code:
+(define-record-type* <guix-build-coordinator-configuration>
+ guix-build-coordinator-configuration make-guix-build-coordinator-configuration
+ guix-build-coordinator-configuration?
+ (package guix-build-coordinator-configuration-package
+ (default guix-build-coordinator))
+ (user guix-build-coordinator-configuration-user
+ (default "guix-build-coordinator"))
+ (group guix-build-coordinator-configuration-group
+ (default "guix-build-coordinator"))
+ (database-uri-string
+ guix-build-coordinator-configuration-datastore-uri-string
+ (default "sqlite:///var/lib/guix-build-coordinator/guix_build_coordinator.db"))
+ (agent-communication-uri-string
+ guix-build-coordinator-configuration-agent-communication-uri-string
+ (default "http://0.0.0.0:8745"))
+ (client-communication-uri-string
+ guix-build-coordinator-configuration-client-communication-uri-string
+ (default "http://127.0.0.1:8746"))
+ (allocation-strategy
+ guix-build-coordinator-configuration-allocation-strategy
+ (default #~basic-build-allocation-strategy))
+ (hooks guix-build-coordinator-configuration-hooks
+ (default '()))
+ (guile guix-build-coordinator-configuration-guile
+ (default guile-3.0-latest)))
+
+(define-record-type* <guix-build-coordinator-agent-configuration>
+ guix-build-coordinator-agent-configuration
+ make-guix-build-coordinator-agent-configuration
+ guix-build-coordinator-agent-configuration?
+ (package guix-build-coordinator-agent-configuration-package
+ (default guix-build-coordinator))
+ (user guix-build-coordinator-agent-configuration-user
+ (default "guix-build-coordinator-agent"))
+ (coordinator guix-build-coordinator-agent-configuration-coordinator
+ (default "http://localhost:8745"))
+ (authentication guix-build-coordinator-agent-configuration-authentication)
+ (systems guix-build-coordinator-agent-configuration-systems
+ (default #f))
+ (max-parallel-builds
+ guix-build-coordinator-agent-configuration-max-parallel-builds
+ (default 1))
+ (max-1min-load-average
+ guix-build-coordinator-agent-configuration-max-1min-load-average
+ (default #f))
+ (derivation-substitute-urls
+ guix-build-coordinator-agent-configuration-derivation-substitute-urls
+ (default #f))
+ (non-derivation-substitute-urls
+ guix-build-coordinator-agent-configuration-non-derivation-substitute-urls
+ (default #f)))
+
+(define-record-type* <guix-build-coordinator-agent-password-auth>
+ guix-build-coordinator-agent-password-auth
+ make-guix-build-coordinator-agent-password-auth
+ guix-build-coordinator-agent-password-auth?
+ (uuid guix-build-coordinator-agent-password-auth-uuid)
+ (password guix-build-coordinator-agent-password-auth-password))
+
+(define-record-type* <guix-build-coordinator-agent-password-file-auth>
+ guix-build-coordinator-agent-password-file-auth
+ make-guix-build-coordinator-agent-password-file-auth
+ guix-build-coordinator-agent-password-file-auth?
+ (uuid guix-build-coordinator-agent-password-file-auth-uuid)
+ (password-file
+ guix-build-coordinator-agent-password-file-auth-password-file))
+
+(define-record-type* <guix-build-coordinator-agent-dynamic-auth>
+ guix-build-coordinator-agent-dynamic-auth
+ make-guix-build-coordinator-agent-dynamic-auth
+ guix-build-coordinator-agent-dynamic-auth?
+ (agent-name guix-build-coordinator-agent-dynamic-auth-agent-name)
+ (token guix-build-coordinator-agent-dynamic-auth-token))
+
+(define-record-type* <guix-build-coordinator-agent-dynamic-auth-with-file>
+ guix-build-coordinator-agent-dynamic-auth-with-file
+ make-guix-build-coordinator-agent-dynamic-auth-with-file
+ guix-build-coordinator-agent-dynamic-auth-with-file?
+ (agent-name guix-build-coordinator-agent-dynamic-auth-with-file-agent-name)
+ (token-file guix-build-coordinator-agent-dynamic-auth-with-file-token-file))
+
+(define-record-type* <guix-build-coordinator-queue-builds-configuration>
+ guix-build-coordinator-queue-builds-configuration
+ make-guix-build-coordinator-queue-builds-configuration
+ guix-build-coordinator-queue-builds-configuration?
+ (package guix-build-coordinator-queue-builds-configuration-package
+ (default guix-build-coordinator))
+ (user guix-build-coordinator-queue-builds-configuration-user
+ (default "guix-build-coordinator-queue-builds"))
+ (coordinator guix-build-coordinator-queue-builds-coordinator
+ (default "http://localhost:8746"))
+ (systems guix-build-coordinator-queue-builds-configuration-systems
+ (default #f))
+ (systems-and-targets
+ guix-build-coordinator-queue-builds-configuration-system-and-targets
+ (default #f))
+ (guix-data-service
+ guix-build-coordinator-queue-builds-configuration-guix-data-service
+ (default "https://data.guix.gnu.org"))
+ (processed-commits-file
+ guix-build-coordinator-queue-builds-configuration-processed-commits-file
+ (default "/var/cache/guix-build-coordinator-queue-builds/processed-commits")))
+
+(define* (make-guix-build-coordinator-start-script database-uri-string
+ allocation-strategy
+ pid-file
+ guix-build-coordinator-package
+ #:key
+ agent-communication-uri-string
+ client-communication-uri-string
+ (hooks '())
+ (guile guile-3.0))
+ (program-file
+ "start-guix-build-coordinator"
+ (with-extensions (cons guix-build-coordinator-package
+ ;; This is a poorly constructed Guile load path,
+ ;; since it contains things that aren't Guile
+ ;; libraries, but it means that the Guile libraries
+ ;; needed for the Guix Build Coordinator don't need
+ ;; to be individually specified here.
+ (append
+ (map second (package-inputs
+ guix-build-coordinator-package))
+ (map second (package-propagated-inputs
+ guix-build-coordinator-package))))
+ #~(begin
+ (use-modules (srfi srfi-1)
+ (ice-9 match)
+ (web uri)
+ (prometheus)
+ (guix-build-coordinator hooks)
+ (guix-build-coordinator datastore)
+ (guix-build-coordinator build-allocator)
+ (guix-build-coordinator coordinator))
+
+ (setvbuf (current-output-port) 'line)
+ (setvbuf (current-error-port) 'line)
+
+ (simple-format #t "starting the guix-build-coordinator:\n ~A\n"
+ (current-filename))
+ (let* ((metrics-registry (make-metrics-registry
+ #:namespace
+ "guixbuildcoordinator"))
+ (datastore (database-uri->datastore
+ #$database-uri-string
+ #:metrics-registry metrics-registry))
+ (hooks
+ (list #$@(map (match-lambda
+ ((name . hook-gexp)
+ #~(cons '#$name #$hook-gexp)))
+ hooks)))
+ (hooks-with-defaults
+ `(,@hooks
+ ,@(remove (match-lambda
+ ((name . _) (assq-ref hooks name)))
+ %default-hooks)))
+ (build-coordinator (make-build-coordinator
+ #:datastore datastore
+ #:hooks hooks-with-defaults
+ #:metrics-registry metrics-registry
+ #:allocation-strategy #$allocation-strategy)))
+
+ (run-coordinator-service
+ build-coordinator
+ #:update-datastore? #t
+ #:pid-file #$pid-file
+ #:agent-communication-uri (string->uri
+ #$agent-communication-uri-string)
+ #:client-communication-uri (string->uri
+ #$client-communication-uri-string)))))
+ #:guile guile))
+
+(define (guix-build-coordinator-shepherd-services config)
+ (match-record config <guix-build-coordinator-configuration>
+ (package user group database-uri-string
+ agent-communication-uri-string
+ client-communication-uri-string
+ allocation-strategy
+ hooks
+ guile)
+ (list
+ (shepherd-service
+ (documentation "Guix Build Coordinator")
+ (provision '(guix-build-coordinator))
+ (requirement '(networking))
+ (start #~(make-forkexec-constructor
+ (list #$(make-guix-build-coordinator-start-script
+ database-uri-string
+ allocation-strategy
+ "/var/run/guix-build-coordinator/pid"
+ package
+ #:agent-communication-uri-string
+ agent-communication-uri-string
+ #:client-communication-uri-string
+ client-communication-uri-string
+ #:hooks hooks
+ #:guile guile))
+ #:user #$user
+ #:group #$group
+ #:pid-file "/var/run/guix-build-coordinator/pid"
+ ;; Allow time for migrations to run
+ #:pid-file-timeout 60
+ #:environment-variables
+ `(,(string-append
+ "GUIX_LOCPATH=" #$glibc-utf8-locales "/lib/locale")
+ "LC_ALL=en_US.utf8"
+ "PATH=/run/current-system/profile/bin") ; for hooks
+ #:log-file "/var/log/guix-build-coordinator/coordinator.log"))
+ (stop #~(make-kill-destructor))))))
+
+(define (guix-build-coordinator-activation config)
+ #~(begin
+ (use-modules (guix build utils))
+
+ (define %user
+ (getpw #$(guix-build-coordinator-configuration-user
+ config)))
+
+ (chmod "/var/lib/guix-build-coordinator" #o755)
+
+ (mkdir-p "/var/log/guix-build-coordinator")
+
+ ;; Allow writing the PID file
+ (mkdir-p "/var/run/guix-build-coordinator")
+ (chown "/var/run/guix-build-coordinator"
+ (passwd:uid %user)
+ (passwd:gid %user))))
+
+(define (guix-build-coordinator-account config)
+ (match-record config <guix-build-coordinator-configuration>
+ (user group)
+ (list (user-group
+ (name group)
+ (system? #t))
+ (user-account
+ (name user)
+ (group group)
+ (system? #t)
+ (comment "Guix Build Coordinator user")
+ (home-directory "/var/lib/guix-build-coordinator")
+ (shell (file-append shadow "/sbin/nologin"))))))
+
+(define guix-build-coordinator-service-type
+ (service-type
+ (name 'guix-build-coordinator)
+ (extensions
+ (list
+ (service-extension shepherd-root-service-type
+ guix-build-coordinator-shepherd-services)
+ (service-extension activation-service-type
+ guix-build-coordinator-activation)
+ (service-extension account-service-type
+ guix-build-coordinator-account)))
+ (default-value
+ (guix-build-coordinator-configuration))
+ (description
+ "Run an instance of the Guix Build Coordinator.")))
+
+(define (guix-build-coordinator-agent-shepherd-services config)
+ (match-record config <guix-build-coordinator-agent-configuration>
+ (package user coordinator authentication max-parallel-builds
+ max-1min-load-average
+ derivation-substitute-urls non-derivation-substitute-urls
+ systems)
+ (list
+ (shepherd-service
+ (documentation "Guix Build Coordinator Agent")
+ (provision '(guix-build-coordinator-agent))
+ (requirement '(networking))
+ (start #~(make-forkexec-constructor
+ (list #$(file-append package "/bin/guix-build-coordinator-agent")
+ #$(string-append "--coordinator=" coordinator)
+ #$@(match authentication
+ (($ <guix-build-coordinator-agent-password-auth>
+ uuid password)
+ #~(#$(string-append "--uuid=" uuid)
+ #$(string-append "--password=" password)))
+ (($ <guix-build-coordinator-agent-password-file-auth>
+ uuid password-file)
+ #~(#$(string-append "--uuid=" uuid)
+ #$(string-append "--password-file="
+ password-file)))
+ (($ <guix-build-coordinator-agent-dynamic-auth>
+ agent-name token)
+ #~(#$(string-append "--name=" agent-name)
+ #$(string-append "--dynamic-auth-token=" token)))
+ (($
+ <guix-build-coordinator-agent-dynamic-auth-with-file>
+ agent-name token-file)
+ #~(#$(string-append "--name=" agent-name)
+ #$(string-append "--dynamic-auth-token-file="
+ token-file))))
+ #$(simple-format #f "--max-parallel-builds=~A"
+ max-parallel-builds)
+ #$@(if max-1min-load-average
+ #~(#$(simple-format #f "--max-1min-load-average=~A"
+ max-1min-load-average))
+ #~())
+ #$@(if derivation-substitute-urls
+ #~(#$(string-append
+ "--derivation-substitute-urls="
+ (string-join derivation-substitute-urls " ")))
+ #~())
+ #$@(if non-derivation-substitute-urls
+ #~(#$(string-append
+ "--non-derivation-substitute-urls="
+ (string-join non-derivation-substitute-urls " ")))
+ #~())
+ #$@(map (lambda (system)
+ (string-append "--system=" system))
+ (or systems '())))
+ #:user #$user
+ #:environment-variables
+ `(,(string-append
+ "GUIX_LOCPATH=" #$glibc-utf8-locales "/lib/locale")
+ ;; XDG_CACHE_HOME is used by Guix when caching narinfo files
+ "XDG_CACHE_HOME=/var/cache/guix-build-coordinator-agent"
+ "LC_ALL=en_US.utf8")
+ #:log-file "/var/log/guix-build-coordinator/agent.log"))
+ (stop #~(make-kill-destructor))))))
+
+(define (guix-build-coordinator-agent-activation config)
+ #~(begin
+ (use-modules (guix build utils))
+
+ (define %user
+ (getpw #$(guix-build-coordinator-agent-configuration-user
+ config)))
+
+ (mkdir-p "/var/log/guix-build-coordinator")
+
+ ;; Create a cache directory for storing narinfo files if downloaded
+ (mkdir-p "/var/cache/guix-build-coordinator-agent")
+ (chown "/var/cache/guix-build-coordinator-agent"
+ (passwd:uid %user)
+ (passwd:gid %user))))
+
+(define (guix-build-coordinator-agent-account config)
+ (list (user-account
+ (name (guix-build-coordinator-agent-configuration-user config))
+ (group "nogroup")
+ (system? #t)
+ (comment "Guix Build Coordinator agent user")
+ (home-directory "/var/empty")
+ (shell (file-append shadow "/sbin/nologin")))))
+
+(define guix-build-coordinator-agent-service-type
+ (service-type
+ (name 'guix-build-coordinator-agent)
+ (extensions
+ (list
+ (service-extension shepherd-root-service-type
+ guix-build-coordinator-agent-shepherd-services)
+ (service-extension activation-service-type
+ guix-build-coordinator-agent-activation)
+ (service-extension account-service-type
+ guix-build-coordinator-agent-account)))
+ (description
+ "Run a Guix Build Coordinator agent.")))
+
+(define (guix-build-coordinator-queue-builds-shepherd-services config)
+ (match-record config <guix-build-coordinator-queue-builds-configuration>
+ (package user coordinator systems systems-and-targets
+ guix-data-service processed-commits-file)
+ (list
+ (shepherd-service
+ (documentation "Guix Build Coordinator queue builds from Guix Data Service")
+ (provision '(guix-build-coordinator-queue-builds))
+ (requirement '(networking))
+ (start
+ #~(make-forkexec-constructor
+ (list
+ #$(file-append
+ package
+ "/bin/guix-build-coordinator-queue-builds-from-guix-data-service")
+ #$(string-append "--coordinator=" coordinator)
+ #$@(map (lambda (system)
+ (string-append "--system=" system))
+ (or systems '()))
+ #$@(map (match-lambda
+ ((system . target)
+ (string-append "--system-and-target=" system "=" target)))
+ (or systems-and-targets '()))
+ #$@(if guix-data-service
+ #~(#$(string-append "--guix-data-service=" guix-data-service))
+ #~())
+ #$@(if processed-commits-file
+ #~(#$(string-append "--processed-commits-file="
+ processed-commits-file))
+ #~()))
+ #:user #$user
+ #:environment-variables
+ `(,(string-append
+ "GUIX_LOCPATH=" #$glibc-utf8-locales "/lib/locale")
+ "LC_ALL=en_US.utf8")
+ #:log-file "/var/log/guix-build-coordinator/queue-builds.log"))
+ (stop #~(make-kill-destructor))))))
+
+(define (guix-build-coordinator-queue-builds-activation config)
+ #~(begin
+ (use-modules (guix build utils))
+
+ (define %user
+ (getpw #$(guix-build-coordinator-queue-builds-configuration-user
+ config)))
+
+ (mkdir-p "/var/log/guix-build-coordinator")
+
+ ;; Allow writing the processed commits file
+ (mkdir-p "/var/cache/guix-build-coordinator-queue-builds")
+ (chown "/var/cache/guix-build-coordinator-queue-builds"
+ (passwd:uid %user)
+ (passwd:gid %user))))
+
+(define (guix-build-coordinator-queue-builds-account config)
+ (list (user-account
+ (name (guix-build-coordinator-queue-builds-configuration-user config))
+ (group "nogroup")
+ (system? #t)
+ (comment "Guix Build Coordinator queue-builds user")
+ (home-directory "/var/empty")
+ (shell (file-append shadow "/sbin/nologin")))))
+
+(define guix-build-coordinator-queue-builds-service-type
+ (service-type
+ (name 'guix-build-coordinator-queue-builds)
+ (extensions
+ (list
+ (service-extension shepherd-root-service-type
+ guix-build-coordinator-queue-builds-shepherd-services)
+ (service-extension activation-service-type
+ guix-build-coordinator-queue-builds-activation)
+ (service-extension account-service-type
+ guix-build-coordinator-queue-builds-account)))
+ (description
+ "Run the guix-build-coordinator-queue-builds-from-guix-data-service
+script.
+
+This is a script to assist in having the Guix Build Coordinator build
+derivations stored in an instance of the Guix Data Service.")))
+
+\f
+;;;
+;;; Guix Data Service
+;;;
+
(define-record-type* <guix-data-service-configuration>
guix-data-service-configuration make-guix-data-service-configuration
guix-data-service-configuration?
(default #f))
(commits-getmail-retriever-configuration
guix-data-service-commits-getmail-retriever-configuration
- (default #f)))
+ (default #f))
+ (extra-options guix-data-service-extra-options
+ (default '()))
+ (extra-process-jobs-options
+ guix-data-service-extra-process-jobs-options
+ (default '())))
(define (guix-data-service-profile-packages config)
"Return the guix-data-service package, this will populate the
(define (guix-data-service-shepherd-services config)
(match-record config <guix-data-service-configuration>
- (package user group port host)
+ (package user group port host extra-options extra-process-jobs-options)
(list
(shepherd-service
(documentation "Guix Data Service web server")
#$(string-append "--host=" host)
;; Perform any database migrations when the
;; service is started
- "--update-database")
+ "--update-database"
+ #$@extra-options)
#:user #$user
#:group #$group
#:environment-variables
`(,(string-append
"GUIX_LOCPATH=" #$glibc-utf8-locales "/lib/locale")
- "LC_ALL=en_US.utf8")
+ "LC_ALL=en_US.UTF-8")
#:log-file "/var/log/guix-data-service/web.log"))
(stop #~(make-kill-destructor)))
(start #~(make-forkexec-constructor
(list
#$(file-append package
- "/bin/guix-data-service-process-jobs"))
+ "/bin/guix-data-service-process-jobs")
+ #$@extra-process-jobs-options)
#:user #$user
#:group #$group
#:environment-variables
"GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt"
,(string-append
"GUIX_LOCPATH=" #$glibc-utf8-locales "/lib/locale")
- "LC_ALL=en_US.utf8")
+ "LC_ALL=en_US.UTF-8")
#:log-file "/var/log/guix-data-service/process-jobs.log"))
(stop #~(make-kill-destructor))))))