services: dovecot: Copy dovecot.conf to /etc/dovecot.

Many Dovecot utilities compiled with assumption of ‘/etc/dovecot/dovecot.conf’
existence.

* gnu/services/mail.scm (dovecot-shepherd-service): Move config generation.
Invoke ‘dovecot’ without ‘-c’ flag.
(%dovecot-activation): Copy ‘dovecot.conf’ to ‘/etc/dovecot’.
(dovecot-service-type): Make ‘%dovecot-activation’ non-constant.
This commit is contained in:
Oleg Pykhalov 2018-03-06 15:42:49 +03:00
parent a539ad867d
commit 6310dff1dc
No known key found for this signature in database
GPG key ID: 7246E11C69B79569

View file

@ -1435,90 +1435,91 @@ (define %dovecot-accounts
(home-directory "/var/empty") (home-directory "/var/empty")
(shell (file-append shadow "/sbin/nologin"))))) (shell (file-append shadow "/sbin/nologin")))))
(define %dovecot-activation (define (%dovecot-activation config)
;; Activation gexp. ;; Activation gexp.
#~(begin (let ((config-str
(use-modules (guix build utils)) (cond
(define (mkdir-p/perms directory owner perms) ((opaque-dovecot-configuration? config)
(mkdir-p directory) (opaque-dovecot-configuration-string config))
(chown "/var/run/dovecot" (passwd:uid owner) (passwd:gid owner)) (else
(chmod directory perms)) (with-output-to-string
(define (build-subject parameters) (lambda ()
(string-concatenate (serialize-configuration config
(map (lambda (pair) dovecot-configuration-fields)))))))
(let ((k (car pair)) (v (cdr pair))) #~(begin
(define (escape-char str chr) (use-modules (guix build utils))
(string-join (string-split str chr) (string #\\ chr))) (define (mkdir-p/perms directory owner perms)
(string-append "/" k "=" (mkdir-p directory)
(escape-char (escape-char v #\=) #\/)))) (chown "/var/run/dovecot" (passwd:uid owner) (passwd:gid owner))
(filter (lambda (pair) (cdr pair)) parameters)))) (chmod directory perms))
(define* (create-self-signed-certificate-if-absent (define (build-subject parameters)
#:key private-key public-key (owner (getpwnam "root")) (string-concatenate
(common-name (gethostname)) (map (lambda (pair)
(organization-name "GuixSD") (let ((k (car pair)) (v (cdr pair)))
(organization-unit-name "Default Self-Signed Certificate") (define (escape-char str chr)
(subject-parameters `(("CN" . ,common-name) (string-join (string-split str chr) (string #\\ chr)))
("O" . ,organization-name) (string-append "/" k "="
("OU" . ,organization-unit-name))) (escape-char (escape-char v #\=) #\/))))
(subject (build-subject subject-parameters))) (filter (lambda (pair) (cdr pair)) parameters))))
;; Note that by default, OpenSSL outputs keys in PEM format. This (define* (create-self-signed-certificate-if-absent
;; is what we want. #:key private-key public-key (owner (getpwnam "root"))
(unless (file-exists? private-key) (common-name (gethostname))
(cond (organization-name "GuixSD")
((zero? (system* (string-append #$openssl "/bin/openssl") (organization-unit-name "Default Self-Signed Certificate")
"genrsa" "-out" private-key "2048")) (subject-parameters `(("CN" . ,common-name)
(chown private-key (passwd:uid owner) (passwd:gid owner)) ("O" . ,organization-name)
(chmod private-key #o400)) ("OU" . ,organization-unit-name)))
(else (subject (build-subject subject-parameters)))
(format (current-error-port) ;; Note that by default, OpenSSL outputs keys in PEM format. This
"Failed to create private key at ~a.\n" private-key)))) ;; is what we want.
(unless (file-exists? public-key) (unless (file-exists? private-key)
(cond (cond
((zero? (system* (string-append #$openssl "/bin/openssl") ((zero? (system* (string-append #$openssl "/bin/openssl")
"req" "-new" "-x509" "-key" private-key "genrsa" "-out" private-key "2048"))
"-out" public-key "-days" "3650" (chown private-key (passwd:uid owner) (passwd:gid owner))
"-batch" "-subj" subject)) (chmod private-key #o400))
(chown public-key (passwd:uid owner) (passwd:gid owner)) (else
(chmod public-key #o444)) (format (current-error-port)
(else "Failed to create private key at ~a.\n" private-key))))
(format (current-error-port) (unless (file-exists? public-key)
"Failed to create public key at ~a.\n" public-key))))) (cond
(let ((user (getpwnam "dovecot"))) ((zero? (system* (string-append #$openssl "/bin/openssl")
(mkdir-p/perms "/var/run/dovecot" user #o755) "req" "-new" "-x509" "-key" private-key
(mkdir-p/perms "/var/lib/dovecot" user #o755) "-out" public-key "-days" "3650"
(mkdir-p/perms "/etc/dovecot" user #o755) "-batch" "-subj" subject))
(mkdir-p/perms "/etc/dovecot/private" user #o700) (chown public-key (passwd:uid owner) (passwd:gid owner))
(create-self-signed-certificate-if-absent (chmod public-key #o444))
#:private-key "/etc/dovecot/private/default.pem" (else
#:public-key "/etc/dovecot/default.pem" (format (current-error-port)
#:owner (getpwnam "root") "Failed to create public key at ~a.\n" public-key)))))
#:common-name (format #f "Dovecot service on ~a" (gethostname)))))) (let ((user (getpwnam "dovecot")))
(mkdir-p/perms "/var/run/dovecot" user #o755)
(mkdir-p/perms "/var/lib/dovecot" user #o755)
(mkdir-p/perms "/etc/dovecot" user #o755)
(copy-file #$(plain-file "dovecot.conf" config-str)
"/etc/dovecot/dovecot.conf")
(mkdir-p/perms "/etc/dovecot/private" user #o700)
(create-self-signed-certificate-if-absent
#:private-key "/etc/dovecot/private/default.pem"
#:public-key "/etc/dovecot/default.pem"
#:owner (getpwnam "root")
#:common-name (format #f "Dovecot service on ~a" (gethostname)))))))
(define (dovecot-shepherd-service config) (define (dovecot-shepherd-service config)
"Return a list of <shepherd-service> for CONFIG." "Return a list of <shepherd-service> for CONFIG."
(let* ((config-str (let ((dovecot (if (opaque-dovecot-configuration? config)
(cond (opaque-dovecot-configuration-dovecot config)
((opaque-dovecot-configuration? config) (dovecot-configuration-dovecot config))))
(opaque-dovecot-configuration-string config))
(else
(with-output-to-string
(lambda ()
(serialize-configuration config
dovecot-configuration-fields))))))
(config-file (plain-file "dovecot.conf" config-str))
(dovecot (if (opaque-dovecot-configuration? config)
(opaque-dovecot-configuration-dovecot config)
(dovecot-configuration-dovecot config))))
(list (shepherd-service (list (shepherd-service
(documentation "Run the Dovecot POP3/IMAP mail server.") (documentation "Run the Dovecot POP3/IMAP mail server.")
(provision '(dovecot)) (provision '(dovecot))
(requirement '(networking)) (requirement '(networking))
(start #~(make-forkexec-constructor (start #~(make-forkexec-constructor
(list (string-append #$dovecot "/sbin/dovecot") (list (string-append #$dovecot "/sbin/dovecot")
"-F" "-c" #$config-file))) "-F")))
(stop #~(make-forkexec-constructor (stop #~(make-forkexec-constructor
(list (string-append #$dovecot "/sbin/dovecot") (list (string-append #$dovecot "/sbin/dovecot")
"-c" #$config-file "stop"))))))) "stop")))))))
(define %dovecot-pam-services (define %dovecot-pam-services
(list (unix-pam-service "dovecot"))) (list (unix-pam-service "dovecot")))
@ -1533,7 +1534,7 @@ (define dovecot-service-type
(service-extension pam-root-service-type (service-extension pam-root-service-type
(const %dovecot-pam-services)) (const %dovecot-pam-services))
(service-extension activation-service-type (service-extension activation-service-type
(const %dovecot-activation)))))) %dovecot-activation)))))
(define* (dovecot-service #:key (config (dovecot-configuration))) (define* (dovecot-service #:key (config (dovecot-configuration)))
"Return a service that runs @command{dovecot}, a mail server that can run "Return a service that runs @command{dovecot}, a mail server that can run