services: certbot: Turn into a Shepherd timer.

* gnu/services/certbot.scm (certbot-renewal-jobs): Rename to…
(certbot-renewal-shepherd-services): … this.  Return a list of Shepherd
services, including ‘renew-certbot-certificates’, formally defined…
(certbot-renewal-one-shot): … here.  Remove.
(certbot-service-type): Adjust accordingly.

Reviewed-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
Change-Id: I25ad9fc1277f4f6f948ab5fce7c6626f22591d10
This commit is contained in:
Ludovic Courtès 2025-03-13 11:46:49 +01:00
parent 465ce8c6a6
commit 8d77e252d2
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5

View file

@ -27,7 +27,6 @@
#:use-module (gnu services) #:use-module (gnu services)
#:use-module (gnu services base) #:use-module (gnu services base)
#:use-module (gnu services shepherd) #:use-module (gnu services shepherd)
#:use-module (gnu services mcron)
#:use-module (gnu services web) #:use-module (gnu services web)
#:use-module (gnu system shadow) #:use-module (gnu system shadow)
#:use-module (gnu packages tls) #:use-module (gnu packages tls)
@ -220,46 +219,56 @@ deploy."
'#$commands) '#$commands)
(exit script-code)))))))) (exit script-code))))))))
(define (certbot-renewal-jobs config) (define (certbot-renewal-shepherd-services config)
(list (list (shepherd-service
;; Attempt to renew the certificates twice per day, at a random minute (provision '(certbot-certificate-renewal))
;; within the hour. See https://eff-certbot.readthedocs.io/. (requirement '(user-processes nginx))
#~(job '(next-minute-from (next-hour '(0 12)) (list (random 60))) (modules '((shepherd service timer)))
#$(certbot-command config)))) (start #~(make-timer-constructor
;; Attempt to renew the certificates twice per day. See
;; https://eff-certbot.readthedocs.io/.
(calendar-event #:minutes '(22) #:hours '(0 12))
(command '(#$(certbot-command config)))
#:wait-for-termination? #t))
(stop #~(make-timer-destructor))
(documentation "Periodically run the 'certbot' command to renew X.509
certificates.")
(actions
(list shepherd-trigger-action
(shepherd-configuration-action (certbot-command config)))))
(define (certbot-renewal-one-shot config) ;; Renew certificates when the system first starts. This is a one-shot
(list ;; service, because the timer above takes care of running this
;; Renew certificates when the system first starts. This is a one-shot ;; periodically. This is most useful the very first time the system
;; service, because the mcron configuration will take care of running this ;; starts, to overwrite our self-signed certificates as soon as
;; periodically. This is most useful the very first time the system starts, ;; possible without user intervention.
;; to overwrite our self-signed certificates as soon as possible without (shepherd-service
;; user intervention. (provision '(renew-certbot-certificates))
(shepherd-service (requirement '(user-processes nginx))
(provision '(renew-certbot-certificates)) (one-shot? #t)
(requirement '(nginx)) (start #~(lambda _
(one-shot? #t) ;; This needs the network, but there's no reliable way to know
(start #~(lambda _ ;; if the network is up other than trying. If we fail due to a
;; This needs the network, but there's no reliable way to know ;; connection error we retry a number of times in the hope that
;; if the network is up other than trying. If we fail due to a ;; the network comes up soon.
;; connection error we retry a number of times in the hope that (let loop ((attempt 0))
;; the network comes up soon. (let ((code (status:exit-val
(let loop ((attempt 0)) (system* #$(certbot-command config)))))
(let ((code (status:exit-val (cond
(system* #$(certbot-command config))))) ((and (= code 2) ; Exit code 2 means connection error
(cond (< attempt 12)) ; Arbitrarily chosen max attempts
((and (= code 2) ; Exit code 2 means connection error (sleep 10) ; Arbitrarily chosen retry delay
(< attempt 12)) ; Arbitrarily chosen max attempts (loop (1+ attempt)))
(sleep 10) ; Arbitrarily chosen retry delay ((zero? code)
(loop (1+ attempt))) ;; Success!
((zero? code) #t)
;; Success! (else
#t) ;; Failure.
(else #f))))))
;; Failure. (auto-start? #t)
#f)))))) (documentation "Run 'certbot' to renew certificates at boot time.")
(auto-start? #t) (actions
(documentation "Call certbot to renew certificates.") (list (shepherd-configuration-action (certbot-command config)))))))
(actions (list (shepherd-configuration-action (certbot-command config)))))))
(define (generate-certificate-gexp certbot-cert-directory rsa-key-size) (define (generate-certificate-gexp certbot-cert-directory rsa-key-size)
(match-lambda (match-lambda
@ -354,10 +363,8 @@ deploy."
(compose list certbot-configuration-package)) (compose list certbot-configuration-package))
(service-extension activation-service-type (service-extension activation-service-type
certbot-activation) certbot-activation)
(service-extension mcron-service-type
certbot-renewal-jobs)
(service-extension shepherd-root-service-type (service-extension shepherd-root-service-type
certbot-renewal-one-shot))) certbot-renewal-shepherd-services)))
(compose concatenate) (compose concatenate)
(extend (lambda (config additional-certificates) (extend (lambda (config additional-certificates)
(certbot-configuration (certbot-configuration