From 869b6ce440d5d1dff1da3de5395595869ae305e7 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 27 Feb 2024 12:10:11 +0100 Subject: Update Certbot configuration to work after Guix Certbot updates. --- container.scm | 190 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 113 insertions(+), 77 deletions(-) (limited to 'container.scm') diff --git a/container.scm b/container.scm index 914abe5..ad5e741 100644 --- a/container.scm +++ b/container.scm @@ -480,79 +480,81 @@ "/etc/self-issued/ca-cert.pem")))) (define g-activate-certs - #~(lambda (cert-names domain-lists) - (use-modules (guix build utils) - (ice-9 format) - (ice-9 textual-ports)) - - (define (issue-cert cert-name domains) - (let* ((cert-dir (format #f "/etc/self-issued/certs/~a" cert-name)) - (cert-path (format #f "~a/cert.pem" cert-dir)) - (chain-path (format #f "~a/chain.pem" cert-dir)) - (fullchain-path (format #f "~a/fullchain.pem" cert-dir)) - (privkey-path (format #f "~a/privkey.pem" cert-dir)) - (csr-path (format #f "~a/csr.pem" cert-dir)) - (openssl (string-append #$openssl "/bin/openssl")) - (initial-umask (umask))) - (unless (false-if-exception (> (stat:gid (stat cert-path)) 0)) - ;; Prepare the directory and private key. - (umask #o027) - (mkdir-p cert-dir) - (system* openssl "genrsa" "-out" privkey-path "2048") - - ;; Make cert.pem and chain.pem. - (with-output-to-file "/tmp/sth" - (lambda _ - (display (format #f "subjectAltName=~{DNS:~a~^,~}" - domains)))) - (system* openssl "req" - "-new" "-nodes" "-out" csr-path "-key" privkey-path - "-subj" "/CN=My Server/C=PL/ST=PL/L=Krakow/O=Koszko" - "-addext" (format #f "subjectAltName=~{DNS:~a~^,~}" - domains)) - (system* openssl "x509" - "-req" "-in" csr-path "-copy_extensions=copyall" - "-CA" "/etc/self-issued/ca-cert.pem" - "-CAkey" "/etc/self-issued/ca-key.pem" "-CAcreateserial" - "-out" cert-path "-days" "3650" "-sha256") - (copy-file "/etc/self-issued/ca-cert.pem" chain-path) - - ;; Concatenate cert.pem and chain.pem into fullchain.pem. - (with-output-to-file fullchain-path - (lambda _ - (for-each (lambda (part) - (call-with-input-file part - (lambda (port) - (display (get-string-all port))))) - (list cert-path chain-path)))) - - ;; Correct permissions. - (chmod privkey-path #o640) - (for-each (lambda (path) - (chown path 0 #$%g-certsaccess-gid)) - (list cert-dir - privkey-path - cert-path - chain-path - fullchain-path)) - (umask initial-umask)))) - - (for-each (lambda (cert-name domains) - (let* ((link-name (format #f "/etc/cert-links/~a" cert-name)) - (tmp-link-name (format #f "~a.newlink" link-name)) - (letsencrypt-target-name - (format #f "/etc/letsencrypt/live/~a" cert-name)) - (self-issued-target-name - (format #f "/etc/self-issued/certs/~a" cert-name))) - (when (#$g-symlink-exists? tmp-link-name) - (delete-file tmp-link-name)) - (if (file-exists? letsencrypt-target-name) - (symlink letsencrypt-target-name tmp-link-name) - (begin - (issue-cert cert-name domains) - (symlink self-issued-target-name tmp-link-name))) - (rename-file tmp-link-name link-name))) - cert-names domain-lists))) + (with-imported-modules '((guix build utils)) + #~(lambda (cert-names domain-lists) + (use-modules (guix build utils) + (ice-9 format) + (ice-9 textual-ports)) + + (define (issue-cert cert-name domains) + (let* ((cert-dir (format #f "/etc/self-issued/certs/~a" cert-name)) + (cert-path (format #f "~a/cert.pem" cert-dir)) + (chain-path (format #f "~a/chain.pem" cert-dir)) + (fullchain-path (format #f "~a/fullchain.pem" cert-dir)) + (privkey-path (format #f "~a/privkey.pem" cert-dir)) + (csr-path (format #f "~a/csr.pem" cert-dir)) + (openssl (string-append #$openssl "/bin/openssl")) + (initial-umask (umask))) + (unless (false-if-exception (> (stat:gid (stat cert-path)) 0)) + ;; Prepare the directory and private key. + (umask #o027) + (mkdir-p cert-dir) + (system* openssl "genrsa" "-out" privkey-path "2048") + + ;; Make cert.pem and chain.pem. + (with-output-to-file "/tmp/sth" + (lambda _ + (display (format #f "subjectAltName=~{DNS:~a~^,~}" + domains)))) + (system* openssl "req" + "-new" "-nodes" "-out" csr-path "-key" privkey-path + "-subj" "/CN=My Server/C=PL/ST=PL/L=Krakow/O=Koszko" + "-addext" (format #f "subjectAltName=~{DNS:~a~^,~}" + domains)) + (system* openssl "x509" + "-req" "-in" csr-path "-copy_extensions=copyall" + "-CA" "/etc/self-issued/ca-cert.pem" + "-CAkey" "/etc/self-issued/ca-key.pem" "-CAcreateserial" + "-out" cert-path "-days" "3650" "-sha256") + (copy-file "/etc/self-issued/ca-cert.pem" chain-path) + + ;; Concatenate cert.pem and chain.pem into fullchain.pem. + (with-output-to-file fullchain-path + (lambda _ + (for-each (lambda (part) + (call-with-input-file part + (lambda (port) + (display (get-string-all port))))) + (list cert-path chain-path)))) + + ;; Correct permissions. + (chmod privkey-path #o640) + (for-each (lambda (path) + (chown path 0 #$%g-certsaccess-gid)) + (list cert-dir + privkey-path + cert-path + chain-path + fullchain-path)) + (umask initial-umask)))) + + (for-each (lambda (cert-name domains) + (let* ((link-name (format #f "/etc/cert-links/~a" + cert-name)) + (tmp-link-name (format #f "~a.newlink" link-name)) + (letsencrypt-target-name + (format #f "/etc/letsencrypt/live/~a" cert-name)) + (self-issued-target-name + (format #f "/etc/self-issued/certs/~a" cert-name))) + (when (#$g-symlink-exists? tmp-link-name) + (delete-file tmp-link-name)) + (if (file-exists? letsencrypt-target-name) + (symlink letsencrypt-target-name tmp-link-name) + (begin + (issue-cert cert-name domains) + (symlink self-issued-target-name tmp-link-name))) + (rename-file tmp-link-name link-name))) + cert-names domain-lists)))) (define (make-httpd-deploy-hook cert-name domains) (program-file @@ -576,8 +578,10 @@ (#$g-activate-certs (list %cert-name) (list %domains)) - (kill (call-with-input-file "/var/run/httpd" read) - SIGHUP)))) + (let ((pid (call-with-input-file "/var/run/httpd" read))) + (if pid + (kill pid SIGHUP) + #t))))) (define %certbot-token-filename-gexp #~(format #f "/srv/http/acme-challenge/~a" (getenv "CERTBOT_TOKEN"))) @@ -598,14 +602,46 @@ "cert-cleanup-hook" #~(delete-file #$%certbot-token-filename-gexp))) +(define (adapt-certbot-shepherd-root-extension ext) + ;; Make certbot independent of Nginx. + (let ((old-activation (service-extension-compute ext))) + (define (new-activation certbot-config) + (cons + ;; Dummy Nginx shepherd service will prevent reloading in certbot from + ;; throwing "&service-not-found-error: nginx". + (shepherd-service + (provision '(nginx)) + (one-shot? #t) + (start #~(const #t)) + (documentation "Provide dummy Nginx.") + (actions + (list + (shepherd-action + (name 'reload) + (documentation "Dummy reload") + (procedure #~(const #t)))))) + + (map (lambda (shepherd-service-record) + (shepherd-service + (inherit shepherd-service-record) + (requirement '(httpd)))) + (old-activation certbot-config)))) + + (service-extension shepherd-root-service-type new-activation))) + (define koszko-certbot-service-type (service-type (inherit certbot-service-type) (name 'koszko-certbot) ;; Prevent certbot from pulling in Nginx — we use Apache here. - (extensions (filter + (extensions (filter-map (lambda (ext) - (not (extension-of-type? ext nginx-service-type))) + (cond ((extension-of-type? ext nginx-service-type) + #f) + ((extension-of-type? ext shepherd-root-service-type) + (adapt-certbot-shepherd-root-extension ext)) + (else + ext))) (service-type-extensions certbot-service-type))))) (define %koszko-certificate-configurations -- cgit v1.2.3