aboutsummaryrefslogtreecommitdiff
path: root/gnu/services/certbot.scm
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/services/certbot.scm')
-rw-r--r--gnu/services/certbot.scm104
1 files changed, 64 insertions, 40 deletions
diff --git a/gnu/services/certbot.scm b/gnu/services/certbot.scm
index c62e5492dc..7bee0de0a3 100644
--- a/gnu/services/certbot.scm
+++ b/gnu/services/certbot.scm
@@ -7,6 +7,9 @@
;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2021 Raghav Gururajan <rg@raghavgururajan.name>
;;; Copyright © 2024 Carlo Zancanaro <carlo@zancanaro.id.au>
+;;; Copyright © 2024 W. Kosior <koszko@koszko.org>
+;;; Additions and modifications by W. Kosior are additionally
+;;; dual-licensed under the Creative Commons Zero v1.0.
;;;
;;; This file is part of GNU Guix.
;;;
@@ -68,7 +71,9 @@
(deploy-hook certificate-configuration-deploy-hook
(default #f))
(start-self-signed? certificate-configuration-start-self-signed?
- (default #t)))
+ (default #t))
+ (key-read-group certificate-configuration-key-read-group
+ (default #f)))
(define-record-type* <certbot-configuration>
certbot-configuration make-certbot-configuration
@@ -96,7 +101,8 @@
(service-requirement certbot-configuration-service-requirement
(default '(nginx))))
-(define (certbot-deploy-hook name deploy-hook-script reload-service-names)
+(define (certbot-deploy-hook name deploy-hook-script reload-service-names
+ key-read-group)
"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. This wrapping is
@@ -110,6 +116,10 @@ deploy."
#~(begin
(use-modules (gnu services herd)
(guix build utils))
+ #$(set-key-access-gexp
+ (string-append "/etc/letsencrypt/live/" name "/privkey.pem")
+ key-read-group)
+
(mkdir-p #$(string-append "/etc/certs/" name))
(chmod #$(string-append "/etc/certs/" name) #o755)
@@ -150,7 +160,9 @@ deploy."
(match-lambda
(($ <certificate-configuration> custom-name domains challenge
csr authentication-hook
- cleanup-hook deploy-hook)
+ cleanup-hook deploy-hook
+ start-self-signed?
+ key-read-group)
(let ((name (or custom-name (car domains))))
(if challenge
(append
@@ -172,7 +184,8 @@ deploy."
(if cleanup-hook `("--manual-cleanup-hook" ,cleanup-hook) '())
(list "--deploy-hook"
(certbot-deploy-hook name deploy-hook
- service-reload)))
+ service-reload
+ key-read-group)))
(append
(list name certbot "certonly" "-n" "--agree-tos"
"--webroot" "-w" webroot
@@ -186,7 +199,8 @@ deploy."
(if rsa-key-size `("--rsa-key-size" ,rsa-key-size) '())
(list "--deploy-hook"
(certbot-deploy-hook name deploy-hook
- service-reload)))))))
+ service-reload
+ key-read-group)))))))
certificates)))
(program-file
"certbot-command"
@@ -272,46 +286,56 @@ deploy."
(documentation "Call certbot to renew certificates.")
(actions (list (shepherd-configuration-action (certbot-command config)))))))
+(define (set-key-access-gexp keyfile key-read-group)
+ #~(let ((gid (or (and=> #$key-read-group (compose group:gid getgr))
+ 0)))
+ (chown #$keyfile -1 gid)
+ (chmod #$keyfile #$(if key-read-group #o640 #o600))))
+
(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))))
- #~(when (not (file-exists? #$directory))
- ;; We generate self-signed certificates in /etc/certs/{domain},
- ;; because certbot is very sensitive to its directory
- ;; structure. It refuses to write over the top of existing files,
- ;; so we need to use a directory outside of its control.
- ;;
- ;; These certificates are overwritten by the certbot deploy hook
- ;; the first time it successfully obtains a letsencrypt-signed
- ;; certificate.
- (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))))))))
+ cleanup-hook deploy-hook
+ start-self-signed? key-read-group)
+ (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)))
+ (keyfile (string-append directory "/privkey.pem")))
+ #~(begin
+ (when (not (file-exists? #$directory))
+ ;; We generate self-signed certificates in /etc/certs/{domain},
+ ;; because certbot is very sensitive to its directory
+ ;; structure. It refuses to write over the top of existing files,
+ ;; so we need to use a directory outside of its control.
+ ;;
+ ;; These certificates are overwritten by the certbot deploy hook
+ ;; the first time it successfully obtains a letsencrypt-signed
+ ;; certificate.
+ (mkdir-p #$directory)
+ (chmod #$directory #o755)
+ (invoke #$(file-append openssl "/bin/openssl")
+ "req" "-x509"
+ "-newkey" #$(format #f "rsa:~a" (or rsa-key-size "4096"))
+ "-keyout" #$keyfile
+ "-out" #$(string-append directory "/fullchain.pem")
+ "-sha256"
+ "-days" "1" ; Only one day, we expect certbot to run
+ "-nodes"
+ "-subj" #$subject
+ #$@(if alt-names
+ (list "-addext" alt-names)
+ (list))))
+ #$(set-key-access-gexp keyfile key-read-group))))))
(define (certbot-activation config)
(let* ((certbot-directory "/var/lib/certbot")