all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Carlo Zancanaro <carlo@zancanaro.id.au>
To: 46961@debbugs.gnu.org
Subject: bug#46961: [PATCH 2/2] services: certbot: Create self-signed certificates before certbot runs
Date: Wed, 24 Jan 2024 23:18:38 +1100	[thread overview]
Message-ID: <788b23efd206b4ef627de06236f868f97e3cbe05.1706098718.git.carlo@zancanaro.id.au> (raw)
In-Reply-To: <cover.1706098718.git.carlo@zancanaro.id.au>

* gnu/services/certbot.scm (<certificate-configuration>): Add
start-self-signed? field.
(generate-certificate-gexp): New procedure.
(certbot-activation): Generate self-signed certificates when
start-self-signed? is #t.
* doc/guix.texi (Certificate services): Document start-self-signed?.
---
 doc/guix.texi            |  6 +++++
 gnu/services/certbot.scm | 56 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 2d43ab9a65..15b256d0a3 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -32664,6 +32664,12 @@ Certificate Services
 contain a space-delimited list of renewed certificate domains (for
 example, @samp{"example.com www.example.com"}.
 
+@item @code{start-self-signed?} (default: @code{#t})
+Whether to generate an initial self-signed certificate during system
+activation.  This option is particularly useful to allow @code{nginx} to
+start before @code{certbot} has run, because @code{certbot} relies on
+@code{nginx} running to perform HTTP challenges.
+
 @end table
 @end deftp
 
diff --git a/gnu/services/certbot.scm b/gnu/services/certbot.scm
index 58e709f8a4..bb321a1b50 100644
--- a/gnu/services/certbot.scm
+++ b/gnu/services/certbot.scm
@@ -64,7 +64,9 @@ (define-record-type* <certificate-configuration>
   (cleanup-hook        certificate-cleanup-hook
                        (default #f))
   (deploy-hook         certificate-configuration-deploy-hook
-                       (default #f)))
+                       (default #f))
+  (start-self-signed?  certificate-configuration-start-self-signed?
+                       (default #t)))
 
 (define-record-type* <certbot-configuration>
   certbot-configuration make-certbot-configuration
@@ -91,7 +93,10 @@ (define-record-type* <certbot-configuration>
 (define (certbot-deploy-hook name deploy-hook-script)
   "Returns a gexp which creates symlinks for privkey.pem and fullchain.pem
 from /etc/certs/NAME to /etc/letsenctypt/live/NAME.  If DEPLOY-HOOK-SCRIPT is
-not #f then it is run after the symlinks have been created."
+not #f then it is run after the symlinks have been created.  This wrapping is
+necessary for certificates with start-self-signed? set to #t, as it will
+overwrite the initial self-signed certificates upon the first successful
+deploy."
   (program-file
    (string-append name "-deploy-hook")
    (with-imported-modules '((guix build utils))
@@ -108,7 +113,8 @@ (define (certbot-deploy-hook name deploy-hook-script)
                      "/etc/letsencrypt/live/" name "/fullchain.pem")
                   #$(string-append "/etc/certs/" name "/fullchain.pem.new"))
 
-         ;; Rename over the top of the old ones, if there are any.
+         ;; Rename over the top of the old ones, just in case they were the
+         ;; original self-signed certificates.
          (rename-file #$(string-append "/etc/certs/" name "/privkey.pem.new")
                       #$(string-append "/etc/certs/" name "/privkey.pem"))
          (rename-file #$(string-append "/etc/certs/" name "/fullchain.pem.new")
@@ -182,6 +188,44 @@ (define (certbot-renewal-jobs config)
    #~(job '(next-minute-from (next-hour '(0 12)) (list (random 60)))
           #$(certbot-command config))))
 
+(define (generate-certificate-gexp certbot-cert-directory rsa-key-size)
+  (match-lambda
+    (($ <certificate-configuration> name (primary-domain other-domains ...) challenge
+                                    csr authentication-hook
+                                    cleanup-hook deploy-hook)
+     (let (;; Arbitrary default subject, with just the
+           ;; right domain filled in. These values don't
+           ;; have any real significance.
+           (subject (string-append "/C=US/ST=Oregon/L=Portland/O=Company Name/OU=Org/CN="
+                                   primary-domain))
+           (alt-names (if (null? other-domains)
+                          #f
+                          (format #f "subjectAltName=~{DNS:~a~^,~}" other-domains)))
+           (directory (string-append "/etc/certs/" (or name primary-domain))))
+       #~(begin
+           (use-modules (ice-9 format))
+           (when (not (file-exists? #$directory))
+             ;; Due to the way certbot runs, we need to
+             ;; create the self-signed certificates in the
+             ;; archive folder and symlink them into the live
+             ;; folder. This mimics what certbot does well
+             ;; enough to make acquiring new certificates
+             ;; work.
+             (mkdir-p #$directory)
+             (chmod #$directory #o755)
+             (invoke #$(file-append openssl "/bin/openssl")
+                     "req" "-x509"
+                     "-newkey" #$(string-append "rsa:" (or rsa-key-size "4096"))
+                     "-keyout" #$(string-append directory "/privkey.pem")
+                     "-out" #$(string-append directory "/fullchain.pem")
+                     "-sha256"
+                     "-days" "1" ; Only one day, because we expect certbot to run
+                     "-nodes"
+                     "-subj" #$subject
+                     #$@(if alt-names
+                            (list "-addext" alt-names)
+                            (list)))))))))
+
 (define (certbot-activation config)
   (let* ((certbot-directory "/var/lib/certbot")
          (certbot-cert-directory "/etc/letsencrypt/live")
@@ -196,6 +240,12 @@ (define (certbot-activation config)
              (mkdir-p #$webroot)
              (mkdir-p #$certbot-directory)
              (mkdir-p #$certbot-cert-directory)
+
+             #$@(map (generate-certificate-gexp certbot-cert-directory
+                                                (and rsa-key-size (number->string rsa-key-size)))
+                     (filter certificate-configuration-start-self-signed?
+                             certificates))
+
              (copy-file #$(certbot-command config) #$script)
              (display #$message)))))))
 
-- 
2.41.0





  parent reply	other threads:[~2024-01-24 12:57 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   ` Carlo Zancanaro [this message]
2024-01-24 13:01     ` bug#46961: [PATCH 2/2] services: certbot: Create self-signed certificates before certbot runs 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     ` bug#46961: [PATCH v3 4/4] services: certbot: Add one-shot service to renew certificates Carlo Zancanaro
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=788b23efd206b4ef627de06236f868f97e3cbe05.1706098718.git.carlo@zancanaro.id.au \
    --to=carlo@zancanaro.id.au \
    --cc=46961@debbugs.gnu.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.