From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms8.migadu.com with LMTPS id qBebBEf7uGUKMAAAqHPOHw:P1 (envelope-from ) for ; Tue, 30 Jan 2024 14:36:07 +0100 Received: from aspmx1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0.migadu.com with LMTPS id qBebBEf7uGUKMAAAqHPOHw (envelope-from ) for ; Tue, 30 Jan 2024 14:36:07 +0100 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=zancanaro.id.au header.s=k1 header.b=lK+g1snv; dmarc=fail reason="SPF not aligned (relaxed)" header.from=zancanaro.id.au (policy=none); spf=pass (aspmx1.migadu.com: domain of "bug-guix-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="bug-guix-bounces+larch=yhetil.org@gnu.org" ARC-Seal: i=1; s=key1; d=yhetil.org; t=1706621767; a=rsa-sha256; cv=none; b=mABNRINlsH5G6kExfQuL+D7QOkzeUbbJxR4CfW/kgoIjTgT5KpROH7lXOwoUh1pLPJeug0 X7sDmPnIToqiyd2dKiWIgGlutCyv0vyAwESLrTjjW1QrBzDySv1vW2ek6D0ZYsV323qnRA UxRgRGGJWMvC2EQTgTaCIGS2S4SCBD3fURiTE1gj2K/9MvNDWyO+SOYHgMuUCj2Oc0irt1 qFg1/1V9wFPXF+6eKCg2iC/gdgLjELqKoIc5vIqXN7mT5tyWEcKh6ImrmY1Ku/H7h1FYAk rsoEgrW2X05rCg1Yis17NKoqsE1LOe+P1oqhZgPzlWXDzPHy+zoBAsBabGqrkw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=zancanaro.id.au header.s=k1 header.b=lK+g1snv; dmarc=fail reason="SPF not aligned (relaxed)" header.from=zancanaro.id.au (policy=none); spf=pass (aspmx1.migadu.com: domain of "bug-guix-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="bug-guix-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1706621767; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=gEe//OJ7nP5Hpxm2WeAsTDEFM1cqlF07cM3xW/J+vog=; b=OS9UNlS73PaXkoxS+/PxiR5a5WDcp33T64wM/U9PPO4wsxo19Hv++xx9QhH42ZN8HCBZps rWaPKYFolBzcdF2AGSdd8wdkvXVnaEtLFcKzIE8ceXPY4/nvvUFYd8PZdNpuaprup6HMLX pLyeNdbp51fI+3qv4h0msdekmMl1jwZ+mMvEmAhja7JM38bYw7ONGGiV9o6CcxkXlbVlE+ oxBKW2NhoR21hf35ibXrWycWXrOrKEc46o7ZHAb3xKwrKbJHF3HGCcL+tIHCM8yZNiO2cy TFLsX9JvoQLzNXqyuS+mCTC0kTpbcoNE5gVFGLYumyCpg+XKAa+ltSCciuu3Ww== Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id E4AECC5F7 for ; Tue, 30 Jan 2024 14:36:06 +0100 (CET) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rUoGT-0000da-GT; Tue, 30 Jan 2024 08:35:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rUoGO-0000Tt-Bq for bug-guix@gnu.org; Tue, 30 Jan 2024 08:34:56 -0500 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rUoGN-0006PT-8z for bug-guix@gnu.org; Tue, 30 Jan 2024 08:34:56 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1rUoGW-00042J-2M for bug-guix@gnu.org; Tue, 30 Jan 2024 08:35:04 -0500 X-Loop: help-debbugs@gnu.org Subject: bug#46961: [PATCH v2 4/4] services: certbot: Add one-shot service to renew certificates. Resent-From: Carlo Zancanaro Original-Sender: "Debbugs-submit" Resent-CC: bug-guix@gnu.org Resent-Date: Tue, 30 Jan 2024 13:35:04 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 46961 X-GNU-PR-Package: guix X-GNU-PR-Keywords: To: 46961@debbugs.gnu.org Cc: guix-devel@gnu.org, brice@waegenei.re, clement@lassieur.org Received: via spool by 46961-submit@debbugs.gnu.org id=B46961.170662164415408 (code B ref 46961); Tue, 30 Jan 2024 13:35:04 +0000 Received: (at 46961) by debbugs.gnu.org; 30 Jan 2024 13:34:04 +0000 Received: from localhost ([127.0.0.1]:34643 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rUoFY-00040N-4t for submit@debbugs.gnu.org; Tue, 30 Jan 2024 08:34:04 -0500 Received: from voltorb.zancanaro.id.au ([45.77.50.64]:48456) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rUoFS-0003yx-5D for 46961@debbugs.gnu.org; Tue, 30 Jan 2024 08:33:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; s=k1; bh=gEe//OJ7nP5Hpxm 2WeAsTDEFM1cqlF07cM3xW/J+vog=; h=references:in-reply-to:date:subject: cc:to:from; d=zancanaro.id.au; b=lK+g1snvBC4FppC61H7uU/y/p36YBmafDJknp GXGXa395XK3DK40q68m9BBDPoGc5ARBq/IMiOktKtUGsZVA/gm9ASpGeUb10//DFndSYz0 9FrRsEZ/1hNPAPwR8Cf2GMNEjCTf9WKAsHxTjKd1eCFT2tWAUh8kj6jgu1CbYkS0= Received: by voltorb.zancanaro.id.au (OpenSMTPD) with ESMTPSA id f3a74ae4 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 30 Jan 2024 13:33:28 +0000 (UTC) From: Carlo Zancanaro Date: Tue, 30 Jan 2024 13:26:40 +0000 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-guix@gnu.org List-Id: Bug reports for GNU Guix List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-guix-bounces+larch=yhetil.org@gnu.org Sender: bug-guix-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Migadu-Scanner: mx10.migadu.com X-Spam-Score: -4.07 X-Migadu-Queue-Id: E4AECC5F7 X-Migadu-Spam-Score: -4.07 X-TUID: U20+XYzjEDog Message-ID: <20240130132640.bK82j-spNwKsev5cMEVFjRjnwNr1FkaA9J2IpZ_k760@z> * 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 --- gnu/services/certbot.scm | 77 +++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/gnu/services/certbot.scm b/gnu/services/certbot.scm index 490b9e8d6d..d6354c86d3 100644 --- a/gnu/services/certbot.scm +++ b/gnu/services/certbot.scm @@ -183,15 +183,37 @@ (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 (file-contains? file string) + (string-contains (call-with-input-file file + get-string-all) + string)) + + (define (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))))))) + (unless (zero? (status:exit-val (apply system* command))) + ;; Certbot errors are always exit code 1, but we'd like + ;; to separate connection errors from other error types. + (if (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. + (exit 2) + ;; If we have any other type of error, then continue + ;; but exit with a failing status code in the end. + (set! script-code 1)))))) + '#$commands) + (exit script-code)))))))) (define (certbot-renewal-jobs config) (list @@ -200,6 +222,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)) ; 12 * 10 seconds = 2 minutes + (sleep 10) + (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 (($ name (primary-domain other-domains ...) @@ -243,9 +299,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 (($ package webroot certificates email server rsa-key-size default-location) @@ -261,10 +315,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 @@ -297,7 +348,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