~ruther/guix-local

c3215d2f9d8fa4b890e3a41ceb4404b76a7c5c49 — ClĂ©ment Lassieur 8 years ago 65fc1d8
services: certbot: Associate one certificate with several domains.

* doc/guix.texi (Certificate Services): Document <certificate-configuration>,
the change from domains to certificates and the fact that their path is now
derived from their name.
* gnu/services/certbot.scm (<certificate-configuration>): Add and export it.
(certbot-configuration, certbot-command, certbot-activation,
certbot-nginx-server-configurations, certbot-service-type): Replace 'domains'
with 'certificates'.
(certbot-nginx-server-configurations): Use only one nginx-server-configuration
and use all certificate domains as the server-name.
2 files changed, 81 insertions(+), 38 deletions(-)

M doc/guix.texi
M gnu/services/certbot.scm
M doc/guix.texi => doc/guix.texi +40 -8
@@ 15746,7 15746,22 @@ can be found there:
@url{https://acme-v01.api.letsencrypt.org/directory}.

@defvr {Scheme Variable} certbot-service-type
A service type for the @code{certbot} Let's Encrypt client.
A service type for the @code{certbot} Let's Encrypt client.  Its value
must be a @code{certbot-configuration} record as in this example:

@example
(service certbot-service-type
         (certbot-configuration
          (email "foo@@example.net")
          (certificates
           (list
            (certificate-configuration
             (domains '("example.net" "www.example.net")))
            (certificate-configuration
             (domains '("bar.example.net")))))))
@end example

See below for details about @code{certbot-configuration}.
@end defvr

@deftp {Data Type} certbot-configuration


@@ 15761,9 15776,10 @@ The certbot package to use.
The directory from which to serve the Let's Encrypt challenge/response
files.

@item @code{domains} (default: @code{()})
A list of domains for which to generate certificates and request
signatures.
@item @code{certificates} (default: @code{()})
A list of @code{certificates-configuration}s for which to generate
certificates and request signatures.  Each certificate has a @code{name}
and several @code{domains}.

@item @code{email}
Mandatory email used for registration, recovery contact, and important


@@ 15791,12 15807,28 @@ Pass @code{#f} to not issue a default location.
@end table
@end deftp

The public key and its signatures will be written to
@code{/etc/letsencrypt/live/@var{domain}/fullchain.pem}, for each
@var{domain} in the configuration.  The private key is written to
@code{/etc/letsencrypt/live/@var{domain}/privkey.pem}.
@deftp {Data Type} certificate-configuration
Data type representing the configuration of a certificate.
This type has the following parameters:

@table @asis
@item @code{name} (default: @i{see below})
This name is used by Certbot for housekeeping and in file paths; it
doesn't affect the content of the certificate itself.  To see
certificate names, run @code{certbot certificates}.

Its default is the first provided domain.

@item @code{domains} (default: @code{()})
The first domain provided will be the subject CN of the certificate, and
all domains will be Subject Alternative Names on the certificate.

@end table
@end deftp

For each @code{certificate-configuration}, the certificate is saved to
@code{/etc/letsencrypt/live/@var{name}/fullchain.pem} and the key is
saved to @code{/etc/letsencrypt/live/@var{name}/privkey.pem}.
@node DNS Services
@subsubsection DNS Services
@cindex DNS (domain name system)

M gnu/services/certbot.scm => gnu/services/certbot.scm +41 -30
@@ 32,7 32,8 @@
  #:use-module (ice-9 match)
  #:export (certbot-service-type
            certbot-configuration
            certbot-configuration?))
            certbot-configuration?
            certificate-configuration))

;;; Commentary:
;;;


@@ 41,6 42,14 @@
;;; Code:


(define-record-type* <certificate-configuration>
  certificate-configuration make-certificate-configuration
  certificate-configuration?
  (name                certificate-configuration-name
                       (default #f))
  (domains             certificate-configuration-domains
                       (default '())))

(define-record-type* <certbot-configuration>
  certbot-configuration make-certbot-configuration
  certbot-configuration?


@@ 48,7 57,7 @@
                       (default certbot))
  (webroot             certbot-configuration-webroot
                       (default "/var/www"))
  (domains             certbot-configuration-domains
  (certificates        certbot-configuration-certificates
                       (default '()))
  (email               certbot-configuration-email)
  (default-location    certbot-configuration-default-location


@@ 60,17 69,19 @@

(define certbot-command
  (match-lambda
    (($ <certbot-configuration> package webroot domains email
    (($ <certbot-configuration> package webroot certificates email
                                default-location)
     (let* ((certbot (file-append package "/bin/certbot"))
            (commands
             (map
              (lambda (domain)
                (list certbot "certonly" "-n" "--agree-tos"
                      "-m" email
                      "--webroot" "-w" webroot
                      "-d" domain))
              domains)))
              (match-lambda
                (($ <certificate-configuration> name domains)
                 (list certbot "certonly" "-n" "--agree-tos"
                       "-m" email
                       "--webroot" "-w" webroot
                       "--cert-name" (or name (car domains))
                       "-d" (string-join domains ","))))
              certificates)))
       (program-file
        "certbot-command"
        #~(let ((code 0))


@@ 88,7 99,7 @@

(define (certbot-activation config)
  (match config
    (($ <certbot-configuration> package webroot domains email
    (($ <certbot-configuration> package webroot certificates email
                                default-location)
     (with-imported-modules '((guix build utils))
       #~(begin


@@ 98,23 109,22 @@

(define certbot-nginx-server-configurations
  (match-lambda
    (($ <certbot-configuration> package webroot domains email
    (($ <certbot-configuration> package webroot certificates email
                                default-location)
     (map
      (lambda (domain)
        (nginx-server-configuration
         (listen '("80" "[::]:80"))
         (ssl-certificate #f)
         (ssl-certificate-key #f)
         (server-name (list domain))
         (locations
          (filter identity
                  (list
                   (nginx-location-configuration
                    (uri "/.well-known")
                    (body (list (list "root " webroot ";"))))
                   default-location)))))
      domains))))
     (list
      (nginx-server-configuration
       (listen '("80" "[::]:80"))
       (ssl-certificate #f)
       (ssl-certificate-key #f)
       (server-name
        (apply append (map certificate-configuration-domains certificates)))
       (locations
        (filter identity
                (list
                 (nginx-location-configuration
                  (uri "/.well-known")
                  (body (list (list "root " webroot ";"))))
                 default-location))))))))

(define certbot-service-type
  (service-type (name 'certbot)


@@ 126,12 136,13 @@
                       (service-extension mcron-service-type
                                          certbot-renewal-jobs)))
                (compose concatenate)
                (extend (lambda (config additional-domains)
                (extend (lambda (config additional-certificates)
                          (certbot-configuration
                           (inherit config)
                           (domains (append
                                     (certbot-configuration-domains config)
                                     additional-domains)))))
                           (certificates
                            (append
                             (certbot-configuration-certificates config)
                             additional-certificates)))))
                (description
                 "Automatically renew @url{https://letsencrypt.org, Let's
Encrypt} HTTPS certificates by adjusting the nginx web server configuration