From: Carlo Zancanaro <carlo@zancanaro.id.au>
To: 46961@debbugs.gnu.org
Cc: clement@lassieur.org
Subject: bug#46961: [PATCH v3 4/4] services: certbot: Add one-shot service to renew certificates.
Date: Wed, 31 Jan 2024 11:46:25 +0000 [thread overview]
Message-ID: <4674088538cb55d20978f5cff9fe8820e9171bf1.1706701585.git.carlo@zancanaro.id.au> (raw)
In-Reply-To: <cover.1706621200.git.carlo@zancanaro.id.au>
* gnu/services/certbot.scm (certbot-renewal-one-shot): New procedure.
(certbot-service-type)[extensions]: Add it to shepherd-root extension.
(certbot-command): Make connection errors return a different exit code.
(certbot-activation): Remove message with certificate renewal instructions.
Change-Id: I614ac6214a753dba0396e2385a75926c8355caa1
---
I've added some more logging here, and removed the comments that
implied that we expected the length of time for the retries to be
bounded.
gnu/services/certbot.scm | 89 +++++++++++++++++++++++++++++++++-------
1 file changed, 75 insertions(+), 14 deletions(-)
diff --git a/gnu/services/certbot.scm b/gnu/services/certbot.scm
index cb1be0c0e9..f287c8367f 100644
--- a/gnu/services/certbot.scm
+++ b/gnu/services/certbot.scm
@@ -180,15 +180,45 @@ (define certbot-command
(program-file
"certbot-command"
#~(begin
- (use-modules (ice-9 match))
- (let ((code 0))
+ (use-modules (ice-9 match)
+ (ice-9 textual-ports))
+
+ (define (log format-string . args)
+ (apply format #t format-string args)
+ (force-output))
+
+ (define (file-contains? file string)
+ (string-contains (call-with-input-file file
+ get-string-all)
+ string))
+
+ (define (connection-error?)
+ ;; Certbot errors are always exit code 1, so we need to look at
+ ;; the log file to see if there was a connection error.
+ (file-contains? "/var/log/letsencrypt/letsencrypt.log"
+ "Failed to establish a new connection"))
+
+ (let ((script-code 0))
(for-each
(match-lambda
((name . command)
- (begin
- (format #t "Acquiring or renewing certificate: ~a~%" name)
- (set! code (or (apply system* command) code)))))
- '#$commands) code)))))))
+ (log "Acquiring or renewing certificate: ~a~%" name)
+ (cond
+ ((zero? (status:exit-val (apply system* command)))
+ (log "Certificate successfully acquired: ~a~%" name))
+ ((connection-error?)
+ ;; If we have a connection error, then bail early with
+ ;; exit code 2. We don't expect this to resolve within the
+ ;; timespan of this script.
+ (log "Connection error - bailing out~%")
+ (exit 2))
+ (else
+ ;; If we have any other type of error, then continue but
+ ;; exit with a failing status code in the end.
+ (log "Error: ~a - continuing with other domains~%" name)
+ (set! script-code 1)))))
+ '#$commands)
+ (exit script-code))))))))
(define (certbot-renewal-jobs config)
(list
@@ -197,6 +227,40 @@ (define (certbot-renewal-jobs config)
#~(job '(next-minute-from (next-hour '(0 12)) (list (random 60)))
#$(certbot-command config))))
+(define (certbot-renewal-one-shot config)
+ (list
+ ;; Renew certificates when the system first starts. This is a one-shot
+ ;; service, because the mcron configuration will take care of running this
+ ;; periodically. This is most useful the very first time the system starts,
+ ;; to overwrite our self-signed certificates as soon as possible without
+ ;; user intervention.
+ (shepherd-service
+ (provision '(renew-certbot-certificates))
+ (requirement '(nginx))
+ (one-shot? #t)
+ (start #~(lambda _
+ ;; This needs the network, but there's no reliable way to know
+ ;; if the network is up other than trying. If we fail due to a
+ ;; connection error we retry a number of times in the hope that
+ ;; the network comes up soon.
+ (let loop ((attempt 0))
+ (let ((code (status:exit-val
+ (system* #$(certbot-command config)))))
+ (cond
+ ((and (= code 2) ; Exit code 2 means connection error
+ (< attempt 12)) ; Arbitrarily chosen max attempts
+ (sleep 10) ; Arbitrarily chosen retry delay
+ (loop (1+ attempt)))
+ ((zero? code)
+ ;; Success!
+ #t)
+ (else
+ ;; Failure.
+ #f))))))
+ (auto-start? #t)
+ (documentation "Call certbot to renew certificates.")
+ (actions (list (shepherd-configuration-action (certbot-command config)))))))
+
(define (generate-certificate-gexp certbot-cert-directory rsa-key-size)
(match-lambda
(($ <certificate-configuration> name (primary-domain other-domains ...)
@@ -240,9 +304,7 @@ (define (generate-certificate-gexp certbot-cert-directory rsa-key-size)
(define (certbot-activation config)
(let* ((certbot-directory "/var/lib/certbot")
- (certbot-cert-directory "/etc/letsencrypt/live")
- (script (in-vicinity certbot-directory "renew-certificates"))
- (message (format #f (G_ "~a may need to be run~%") script)))
+ (certbot-cert-directory "/etc/letsencrypt/live"))
(match config
(($ <certbot-configuration> package webroot certificates email
server rsa-key-size default-location)
@@ -258,10 +320,7 @@ (define (certbot-activation config)
(map (generate-certificate-gexp certbot-cert-directory
rsa-key-size)
(filter certificate-configuration-start-self-signed?
- certificates)))
-
- (copy-file #$(certbot-command config) #$script)
- (display #$message)))))))
+ certificates)))))))))
(define certbot-nginx-server-configurations
(match-lambda
@@ -294,7 +353,9 @@ (define certbot-service-type
(service-extension activation-service-type
certbot-activation)
(service-extension mcron-service-type
- certbot-renewal-jobs)))
+ certbot-renewal-jobs)
+ (service-extension shepherd-root-service-type
+ certbot-renewal-one-shot)))
(compose concatenate)
(extend (lambda (config additional-certificates)
(certbot-configuration
--
2.41.0
next prev parent reply other threads:[~2024-01-31 11:51 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-06 8:15 Nginx and certbot cervices don't play well togther Brice Waegeneire
2024-01-24 12:18 ` bug#46961: [PATCH 0/2] Allow nginx to start before certbot has run Carlo Zancanaro
2024-01-24 12:18 ` bug#46961: [PATCH 1/2] services: certbot: Symlink certificates to /etc/certs Carlo Zancanaro
2024-01-24 12:18 ` bug#46961: [PATCH 2/2] services: certbot: Create self-signed certificates before certbot runs Carlo Zancanaro
2024-01-24 13:01 ` Carlo Zancanaro
2024-01-29 19:23 ` bug#46961: Nginx and certbot cervices don't play well togther Clément Lassieur
2024-01-29 23:02 ` Carlo Zancanaro
2024-01-29 23:19 ` Clément Lassieur
2024-01-29 19:28 ` Clément Lassieur
2024-01-30 13:26 ` bug#46961: [PATCH v2 0/4] Make certbot play more nicely with nginx Carlo Zancanaro
2024-01-30 13:26 ` Carlo Zancanaro
2024-01-30 14:49 ` Felix Lechner via Development of GNU Guix and the GNU System distribution.
2024-01-30 21:48 ` Carlo Zancanaro
2024-01-31 0:04 ` Wojtek Kosior via Development of GNU Guix and the GNU System distribution.
[not found] ` <875xzanaer.fsf__22488.5524179385$1706626282$gmane$org@lease-up.com>
2024-01-30 19:39 ` bug#46961: " Clément Lassieur
2024-04-13 1:17 ` Felix Lechner via Development of GNU Guix and the GNU System distribution.
2024-04-14 11:42 ` Carlo Zancanaro
2024-04-14 13:51 ` Carlo Zancanaro
2024-04-14 16:25 ` Felix Lechner via Development of GNU Guix and the GNU System distribution.
2024-01-31 11:46 ` bug#46961: [PATCH v3 " Carlo Zancanaro
2024-01-31 11:46 ` bug#46961: [PATCH v3 1/4] services: certbot: Symlink certificates to /etc/certs Carlo Zancanaro
2024-01-31 11:46 ` bug#46961: [PATCH v3 2/4] services: certbot: Create self-signed certificates before certbot runs Carlo Zancanaro
2024-01-31 11:46 ` bug#46961: [PATCH v3 3/4] services: certbot: Reload nginx in deploy hook Carlo Zancanaro
2024-01-31 11:46 ` Carlo Zancanaro [this message]
2024-01-30 13:26 ` [PATCH v2 1/4] services: certbot: Symlink certificates to /etc/certs Carlo Zancanaro
2024-01-30 13:26 ` [PATCH v2 2/4] services: certbot: Create self-signed certificates before certbot runs Carlo Zancanaro
2024-01-30 13:26 ` [PATCH v2 3/4] services: certbot: Add a default deploy hook to reload nginx Carlo Zancanaro
2024-01-31 0:29 ` bug#46961: Nginx and certbot cervices don't play well togther Clément Lassieur
2024-01-30 13:26 ` bug#46961: [PATCH v2 4/4] services: certbot: Add one-shot service to renew certificates Carlo Zancanaro
2024-01-30 13:26 ` Carlo Zancanaro
2024-01-31 0:55 ` bug#46961: Nginx and certbot cervices don't play well togther Clément Lassieur
2024-01-31 11:50 ` Carlo Zancanaro
2024-01-31 15:58 ` Clément Lassieur
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4674088538cb55d20978f5cff9fe8820e9171bf1.1706701585.git.carlo@zancanaro.id.au \
--to=carlo@zancanaro.id.au \
--cc=46961@debbugs.gnu.org \
--cc=clement@lassieur.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/guix.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.