101 lines
4.1 KiB
Scheme
101 lines
4.1 KiB
Scheme
|
(define-module (services certbot)
|
||
|
#:use-module (gnu services)
|
||
|
#:use-module (gnu services base)
|
||
|
#:use-module (gnu services shepherd)
|
||
|
#:use-module (gnu services mcron)
|
||
|
#:use-module (gnu packages tls)
|
||
|
#:use-module (guix i18n)
|
||
|
#:use-module (guix records)
|
||
|
#:use-module (guix gexp)
|
||
|
#:use-module (srfi srfi-1)
|
||
|
#:use-module (ice-9 match)
|
||
|
#:export (certbot-service-type
|
||
|
certbot-configuration
|
||
|
certbot-configuration?
|
||
|
certificate-configuration))
|
||
|
|
||
|
;; Standalone certbot service.
|
||
|
|
||
|
(define-record-type* <certificate-configuration>
|
||
|
certificate-configuration make-certificate-configuration
|
||
|
certificate-configuration?
|
||
|
(name certificate-configuration-name (default #f))
|
||
|
(domains certificate-configuration-domains (default '()))
|
||
|
(deploy-hook certificate-configuration-deploy-hook (default #f)))
|
||
|
|
||
|
(define-record-type* <certbot-configuration>
|
||
|
certbot-configuration make-certbot-configuration
|
||
|
certbot-configuration?
|
||
|
(package certbot-configuration-package (default certbot))
|
||
|
(certificates certbot-configuration-certificates (default '())))
|
||
|
|
||
|
(define certbot-command
|
||
|
(match-lambda
|
||
|
(($ <certbot-configuration> package certificates)
|
||
|
(let* ((certbot (file-append package "/bin/certbot"))
|
||
|
(commands
|
||
|
(map
|
||
|
(match-lambda
|
||
|
(($ <certificate-configuration> custom-name domains deploy-hook)
|
||
|
(let ((name (or custom-name (car domains))))
|
||
|
(append
|
||
|
(list name certbot "certonly" "-n" "--agree-tos"
|
||
|
"--register-unsafely-without-email"
|
||
|
"--standalone" "--cert-name" name
|
||
|
"-d" (string-join domains ","))
|
||
|
(if deploy-hook `("--deploy-hook" ,deploy-hook) '())))))
|
||
|
certificates)))
|
||
|
(program-file
|
||
|
"certbot-command"
|
||
|
#~(begin
|
||
|
(use-modules (ice-9 match))
|
||
|
(apply max 0
|
||
|
(map (match-lambda
|
||
|
((name . command)
|
||
|
(begin
|
||
|
(format #t "Acquiring or renewing certificate: ~a~%" name)
|
||
|
(apply system* command))))
|
||
|
'#$commands))))))))
|
||
|
|
||
|
(define (certbot-renewal-jobs config)
|
||
|
(list
|
||
|
;; Attempt to renew the certificates twice per day, at a random minute
|
||
|
;; within the hour. See https://certbot.eff.org/all-instructions/.
|
||
|
#~(job '(next-minute-from (next-hour '(0 12)) (list (random 60)))
|
||
|
#$(certbot-command config))))
|
||
|
|
||
|
(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)))
|
||
|
(match config
|
||
|
(($ <certbot-configuration> package certificates)
|
||
|
(with-imported-modules '((guix build utils))
|
||
|
#~(begin
|
||
|
(use-modules (guix build utils))
|
||
|
(mkdir-p #$certbot-directory)
|
||
|
(mkdir-p #$certbot-cert-directory)
|
||
|
(copy-file #$(certbot-command config) #$script)
|
||
|
(display #$message)))))))
|
||
|
|
||
|
(define certbot-service-type
|
||
|
(service-type (name 'certbot)
|
||
|
(extensions
|
||
|
(list (service-extension activation-service-type
|
||
|
certbot-activation)
|
||
|
(service-extension mcron-service-type
|
||
|
certbot-renewal-jobs)))
|
||
|
(compose concatenate)
|
||
|
(extend (lambda (config additional-certificates)
|
||
|
(certbot-configuration
|
||
|
(inherit config)
|
||
|
(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
|
||
|
and periodically invoking @command{certbot}.")))
|