- [acme](src/acme) Added module providing Let's encrypt TLS certificates using ACME.

- [acme](src/acme) Fixed ACME module shell (ash and bash) portability.
master
mlan 2020-11-11 19:08:41 +01:00
parent 162e9ca256
commit 8b252367b9
10 changed files with 312 additions and 13 deletions

View File

@ -3,6 +3,8 @@
- [kopano](src/kopano) Adding support for secure IMAPS, POP3S and ICALS. - [kopano](src/kopano) Adding support for secure IMAPS, POP3S and ICALS.
- [kopano](src/kopano) Now generate self-signed certs if needed. - [kopano](src/kopano) Now generate self-signed certs if needed.
- [demo](demo) Enable IMAPS, POP3S, ICALS and SMTPS in demo. - [demo](demo) Enable IMAPS, POP3S, ICALS and SMTPS in demo.
- [acme](src/acme) Added module providing Let's encrypt TLS certificates using ACME.
- [acme](src/acme) Fixed ACME module shell (ash and bash) portability.
# 1.2.2 # 1.2.2

View File

@ -17,6 +17,7 @@ ENV DEBIAN_FRONTEND=noninteractive \
DOCKER_CONF_DIR2=/usr/share/z-push \ DOCKER_CONF_DIR2=/usr/share/z-push \
DOCKER_APPL_LIB=/var/lib/kopano \ DOCKER_APPL_LIB=/var/lib/kopano \
DOCKER_APPL_SSL_DIR=/etc/kopano/ssl \ DOCKER_APPL_SSL_DIR=/etc/kopano/ssl \
DOCKER_ACME_SSL_DIR=/etc/ssl/acme \
KOPANO_SPAMD_LIB=/var/lib/kopano/spamd \ KOPANO_SPAMD_LIB=/var/lib/kopano/spamd \
DOCKER_APPL_RUNAS=kopano \ DOCKER_APPL_RUNAS=kopano \
DOCKER_BUILD_DEB_DIR=/tmp/deb \ DOCKER_BUILD_DEB_DIR=/tmp/deb \
@ -43,6 +44,8 @@ RUN apt-get update && apt-get install --yes --no-install-recommends \
ca-certificates \ ca-certificates \
tar \ tar \
gnupg \ gnupg \
jq \
inotify-tools \
&& docker-service.sh "syslogd -nO- -l$SYSLOG_LEVEL $SYSLOG_OPTIONS" && docker-service.sh "syslogd -nO- -l$SYSLOG_LEVEL $SYSLOG_OPTIONS"
@ -63,7 +66,7 @@ RUN rm -f /etc/dpkg/dpkg.cfg.d/excludes \
man \ man \
manpages \ manpages \
bash-completion \ bash-completion \
&& rm -r /var/lib/apt/lists/* && rm -r /var/lib/apt/lists/*
@ -102,9 +105,13 @@ RUN mkdir -p $DOCKER_BUILD_DEB_DIR \
&& apt-get install --yes --no-install-recommends --fix-broken; done \ && apt-get install --yes --no-install-recommends --fix-broken; done \
&& mkdir -p /var/lib/kopano/attachments && chown $DOCKER_APPL_RUNAS: /var/lib/kopano/attachments \ && mkdir -p /var/lib/kopano/attachments && chown $DOCKER_APPL_RUNAS: /var/lib/kopano/attachments \
&& mkdir -p $DOCKER_APPL_SSL_DIR \ && mkdir -p $DOCKER_APPL_SSL_DIR \
&& mkdir -p $DOCKER_ACME_SSL_DIR \
&& mkdir -p $KOPANO_SPAMD_LIB/ham && chown $DOCKER_APPL_RUNAS: $KOPANO_SPAMD_LIB/ham \ && mkdir -p $KOPANO_SPAMD_LIB/ham && chown $DOCKER_APPL_RUNAS: $KOPANO_SPAMD_LIB/ham \
&& rm -rf $DOCKER_BUILD_DEB_DIR \ && rm -rf $DOCKER_BUILD_DEB_DIR \
&& rm $DOCKER_CONF_DIR1/*.cfg \ && rm $DOCKER_CONF_DIR1/*.cfg \
&& . docker-common.sh \
&& . docker-config.sh \
&& dc_comment /etc/ssl/openssl.cnf RANDFILE \
&& docker-service.sh \ && docker-service.sh \
"kopano-dagent -l" \ "kopano-dagent -l" \
"kopano-gateway" \ "kopano-gateway" \

View File

@ -321,7 +321,27 @@ If any of `IMAPS_LISTEN`, `POP3S_LISTEN` and `ICALS_LISTEN` are explicitly defin
#### `SSL_CERTIFICATE_FILE` and `SSL_PRIVATE_KEY_FILE` #### `SSL_CERTIFICATE_FILE` and `SSL_PRIVATE_KEY_FILE`
For most deployments a trusted TLS certificate is needed. When such are available, copy the [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) certificate and private key files to the container and use the envvars `SSL_CERTIFICATE_FILE` and `SSL_PRIVATE_KEY_FILE` to let the kopano-gateway and kopano-ical services find them. For example `SSL_CERTIFICATE_FILE=/etc/kopano/ssl/cert.pem` and `SSL_PRIVATE_KEY_FILE=/etc/kopano/ssl/priv_key.pem`. Note that these files need to be readable by the `kopano` user. For most deployments a trusted TLS certificate is needed. When such are available, copy the [RSA](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) certificate and private key files to the container and use the envvars `SSL_CERTIFICATE_FILE` and `SSL_PRIVATE_KEY_FILE` to let the kopano-gateway and kopano-ical services find them. For example `SSL_CERTIFICATE_FILE=/etc/kopano/ssl/cert.pem` and `SSL_PRIVATE_KEY_FILE=/etc/kopano/ssl/priv_key.pem`. Note that these files need to be readable by the `kopano` user.
### Lets Encrypt LTS certificates using [Traefik](https://docs.traefik.io/)
[Lets Encrypt](https://letsencrypt.org/) provide free, automated, authorized certificates when you can demonstrate control over your domain. [Automatic Certificate Management Environment (ACME)](https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment) is the protocol used for such demonstration. There are many agents and applications that supports ACME, e.g., [certbot](https://certbot.eff.org/). The reverse proxy [Traefik](https://docs.traefik.io/) also supports ACME.
#### `ACME_FILE`, `ACME_POSTHOOK`
The `mlan/kopano` image looks for a file `ACME_FILE=/acme/acme.json` at container startup and every time this file changes certificates within this file are extracted. If the host or domain name of one of those certificates matches `HOSTNAME=$(hostname)` or `DOMAIN=${HOSTNAME#*.}` it will be used for TLS support.
Once the certificates and keys have been updated, we run the command in the environment variable `ACME_POSTHOOK="sv restart kopano-gateway kopano-ical"`. Kopano services needs to be restarted to update the LTS parameters. If such automatic reloading is not desired, set `ACME_POSTHOOK=` to empty.
So reusing certificates from Traefik will work out of the box if the `/acme` directory in the Traefik container is also mounted in the `mlan/kopano` container.
```bash
docker run -d -name app -v proxy-acme:/acme:ro mlan/postfix
```
Note, if the target certificate Common Name (CN) or Subject Alternate Name (SAN) is changed the container needs to be restarted.
Moreover, do not set any of `SSL_CERTIFICATE_FILE` and `SSL_PRIVATE_KEY_FILE` when using `ACME_FILE`.
## Logging `SYSLOG_LEVEL`, `LOG_LEVEL` ## Logging `SYSLOG_LEVEL`, `LOG_LEVEL`

View File

@ -182,7 +182,7 @@ db-init: db-up
db-test: db-test:
docker-compose exec db mysqlshow -u $(MYSQL_USER) $(MYSQL_DATABASE) -p$(MYSQL_PASSWORD) docker-compose exec db mysqlshow -u $(MYSQL_USER) $(MYSQL_DATABASE) -p$(MYSQL_PASSWORD)
app-init: app-up wait_5 app-public_store app-init: app-up wait_12 app-public_store
app-debugtools: app-debugtools:
docker-compose exec app apt-get update docker-compose exec app apt-get update
@ -206,7 +206,7 @@ app-test_smtp: mta-test_smtp
app-test_lmtp: app-hostaddr app-test_lmtp: app-hostaddr
printf "LHLO mx\nMAIL FROM: <test@example.biz>\nRCPT TO: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDATA\nFrom: A tester <test@example.biz>\nTo: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDate: $$(date)\nSubject: A LMTP test message from me to you\n\nDelete me, please \n.\nQUIT\n" | nc -C $(myhost) 2003 printf "LHLO mx\nMAIL FROM: <test@example.biz>\nRCPT TO: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDATA\nFrom: A tester <test@example.biz>\nTo: <$(LDAP_TEST_USER)@$(MAIL_DOMAIN)>\nDate: $$(date)\nSubject: A LMTP test message from me to you\n\nDelete me, please \n.\nQUIT\n" | nc -C $(myhost) 2003
app-test_proto: all-test_muted app-test_imap app-test_pop3 app-test_ical app-test_imaps app-test_pop3s app-test_icals app-test_all: all-test_muted app-test_imap app-test_pop3 app-test_ical app-test_imaps app-test_pop3s app-test_icals
app-test_imap: app-hostaddr app-test_imap: app-hostaddr
curl imap://$(myhost) -u $(LDAP_TEST_USER):$(LDAP_TEST_PASSWD) $(curl_dbg) curl imap://$(myhost) -u $(LDAP_TEST_USER):$(LDAP_TEST_PASSWD) $(curl_dbg)
@ -226,6 +226,9 @@ app-test_ical: app-hostaddr
app-test_icals: app-hostaddr app-test_icals: app-hostaddr
curl https://$(myhost):8443 -k -u $(LDAP_TEST_USER):$(LDAP_TEST_PASSWD) $(curl_dbg) curl https://$(myhost):8443 -k -u $(LDAP_TEST_USER):$(LDAP_TEST_PASSWD) $(curl_dbg)
app-test_tls: app-hostaddr
docker run --rm -it --network demo_backend drwetter/testssl.sh app:993 || true
app-show_user1: app-show_user1:
docker-compose exec app kopano-admin -l docker-compose exec app kopano-admin -l

193
src/acme/bin/acme-extract.sh Executable file
View File

@ -0,0 +1,193 @@
#!/usr/bin/env sh
# Copyright (c) 2017 Brian 'redbeard' Harrington <redbeard@dead-city.org>
#
# acme-export.sh - A simple utility to explode a Traefik acme.json file into a
# directory of certificates and a private key
#
# Usage - acme-export.sh /etc/traefik/acme.json /etc/ssl/
#
# Dependencies -
# util-linux
# openssl
# jq
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Exit codes:
# 1 - A component is missing or could not be read
# 2 - There was a problem reading acme.json
# 4 - The destination certificate directory does not exist
# 8 - Missing private key
#set -o errexit
##set -o pipefail
#set -o nounset
#set -o verbose
#
# configuration
#
. docker-common.sh
DOCKER_ACME_SSL_DIR=${DOCKER_ACME_SSL_DIR-/etc/ssl/acme}
ACME_FILE=${ACME_FILE-/acme/acme.json}
CMD_DECODE_BASE64="base64 -d"
#
# functions
#
usage() { echo "$(basename $0) <path to acme> <destination cert directory>" ;}
test_args() {
# when called by inotifyd the first argument is the single character
# event descriptor, lets drop it
dc_log 7 "Called with args $@"
[ $# -ge 0 ] && [ ${#1} -eq 1 ] && shift
readonly acmefile="${1-$ACME_FILE}"
readonly certdir="${2-$DOCKER_ACME_SSL_DIR}"
}
test_dependencies() {
# Allow us to exit on a missing jq binary
if dc_is_installed jq; then
dc_log 7 "The package jq is installed."
else
dc_log 4 "You must have the binary jq to use this."
exit 1
fi
}
test_acmefile() {
if [ ! -r "${acmefile}" ]; then
dc_log 4 "There was a problem reading from (${acmefile}). We need to read this file to explode the JSON bundle... exiting."
exit 2
fi
}
test_certdir() {
if [ ! -d "${certdir}" ]; then
dc_log 4 "Path ${certdir} does not seem to be a directory. We need a directory in which to explode the JSON bundle... exiting."
exit 4
fi
}
make_certdirs() {
# If they do not exist, create the needed subdirectories for our assets
# and place each in a variable for later use, normalizing the path
mkdir -p "${certdir}/certs" "${certdir}/private"
pdir="${certdir}/private"
cdir="${certdir}/certs"
}
bad_acme() {
dc_log 4 "There was a problem parsing your acme.json file."
exit 2
}
read_letsencryptkey() {
# look for key assuming acme v2 format
priv=$(jq -e -r '.[].Account.PrivateKey' "${acmefile}" 2>/dev/null)
if [ $? -eq 0 ]; then
acmeversion=2
dc_log 7 "Using acme v2 format, the PrivateKey was found in ${acmefile}"
else
# look for key assuming acme v1 format
priv=$(jq -e -r '.Account.PrivateKey' "${acmefile}" 2>/dev/null)
if [ $? -eq 0 ]; then
acmeversion=1
dc_log 7 "Using acme v1 format, the PrivateKey was found in ${acmefile}"
else
dc_log 4 "There didn't seem to be a private key in ${acmefile}. Please ensure that there is a key in this file and try again."
exit 2
fi
fi
}
save_letsencryptkey() {
local keyfile=${pdir}/letsencrypt.key
printf -- \
"-----BEGIN RSA PRIVATE KEY-----\n%s\n-----END RSA PRIVATE KEY-----\n" \
${priv} | fold -w 65 | \
openssl rsa -inform pem -out $keyfile 2>/dev/null
if [ -e $keyfile ]; then
dc_log 7 "PrivateKey is valid and saved in $keyfile"
else
dc_log 4 "PrivateKey appers NOT to be valid"
exit 2
fi
}
read_domains() {
# Process the certificates for each of the domains in acme.json
case $acmeversion in
1) jq_filter='.Certificates[].Domain.Main' ;;
2) jq_filter='.[].Certificates[].domain.main' ;;
esac
domains=$(jq -r $jq_filter $acmefile)
if [ -n "$domains" ]; then
dc_log 7 "Extracting private key and cert bundle for domains $domains."
else
dc_log 4 "Unable to find any domains in $acmefile."
exit 2
fi
}
#
# Traefik stores a cert bundle for each domain. Within this cert
# bundle there is both proper the certificate and the Let's Encrypt CA
#
save_certs() {
dc_log 5 "Extracting private keys and cert bundles in ${acmefile}"
case $acmeversion in
1)
jq_crtfilter='.Certificates[] | select (.Domain.Main == $domain )| .Certificate'
jq_keyfilter='.Certificates[] | select (.Domain.Main == $domain )| .Key'
;;
2)
jq_crtfilter='.[].Certificates[] | select (.domain.main == $domain )| .certificate'
jq_keyfilter='.[].Certificates[] | select (.domain.main == $domain )| .key'
;;
esac
for domain in $domains; do
crt=$(jq -e -r --arg domain "$domain" "$jq_crtfilter" $acmefile) || bad_acme
echo "${crt}" | ${CMD_DECODE_BASE64} > "${cdir}/${domain}.crt"
key=$(jq -e -r --arg domain "$domain" "$jq_keyfilter" $acmefile) || bad_acme
echo "${key}" | ${CMD_DECODE_BASE64} > "${pdir}/${domain}.key"
done
}
#
# Run command in ACME_POSTHOOK if it contain a valid command and runsvdir is running.
#
run_posthook() {
if (pidof runsvdir >/dev/null && [ -n "$ACME_POSTHOOK" ] && command -v $ACME_POSTHOOK >/dev/null); then
local out=$(eval "$ACME_POSTHOOK" 2>&1)
[ -n "$out" ] && dc_log 7 "$ACME_POSTHOOK : $out"
fi
}
#
# run
#
test_args $@
test_dependencies
test_acmefile
test_certdir
read_letsencryptkey
make_certdirs
save_letsencryptkey
read_domains
save_certs
run_posthook

56
src/acme/entry.d/10-acme-common Executable file
View File

@ -0,0 +1,56 @@
#!/bin/sh
#
# 10-acme-common
#
# Define variables and functions used during container initialization.
#
# Variables defined in Dockerfile
# DOCKER_ACME_SSL_DIR DOCKER_APPL_SSL_DIR
#
ACME_FILE=${ACME_FILE-/acme/acme.json}
HOSTNAME=${HOSTNAME-$(hostname)}
DOMAIN=${HOSTNAME#*.}
DOCKER_APPL_SSL_CERT=${DOCKER_APPL_SSL_CERT-$DOCKER_APPL_SSL_DIR/cert.pem}
DOCKER_APPL_SSL_KEY=${DOCKER_APPL_SSL_KEY-$DOCKER_APPL_SSL_DIR/priv_key.pem}
DOCKER_ACME_SSL_H_CERT=$DOCKER_ACME_SSL_DIR/certs/${HOSTNAME}.crt
DOCKER_ACME_SSL_H_KEY=$DOCKER_ACME_SSL_DIR/private/${HOSTNAME}.key
DOCKER_ACME_SSL_D_CERT=$DOCKER_ACME_SSL_DIR/certs/${DOMAIN}.crt
DOCKER_ACME_SSL_D_KEY=$DOCKER_ACME_SSL_DIR/private/${DOMAIN}.key
#
# Setup monitoring of ACME_FILE
#
acme_monitor_tls_cert() {
if (dc_is_installed jq && (dc_is_command inotifyd || dc_is_command inotifywait)); then
if [ -s $ACME_FILE ]; then
# run acme-extract.sh on cnt creation (and every time the json file changes)
dc_log 5 "Setup ACME TLS certificate monitoring"
if dc_is_command inotifyd; then
docker-service.sh "-n acme $(which inotifyd) $(which acme-extract.sh) $ACME_FILE:c"
else
docker-service.sh "-n acme sh -c \"while $(which inotifywait) -e close_write $ACME_FILE; do $(which acme-extract.sh); done\""
fi
# acme-extract.sh reports to logger but it is yet to be started so this run will be quiet
acme-extract.sh $ACME_FILE $DOCKER_ACME_SSL_DIR
fi
else
dc_log 5 "Not all required pkgs installed so cannot setup ACME TLS certificate monitoring"
fi
}
#
# Arrange sym-links to support both host and domain certificates.
#
acme_symlink_tls_cert() {
if ([ -r $DOCKER_ACME_SSL_H_CERT ] && [ -r $DOCKER_ACME_SSL_H_KEY ]); then
dc_log 5 "Setting up ACME TLS certificate for host $HOSTNAME"
ln -sf $DOCKER_ACME_SSL_H_CERT $DOCKER_APPL_SSL_CERT
ln -sf $DOCKER_ACME_SSL_H_KEY $DOCKER_APPL_SSL_KEY
else
if ([ -r $DOCKER_ACME_SSL_D_CERT ] && [ -r $DOCKER_ACME_SSL_D_KEY ]); then
dc_log 5 "Setting up ACME TLS certificate for domain $DOMAIN"
ln -sf $DOCKER_ACME_SSL_D_CERT $DOCKER_APPL_SSL_CERT
ln -sf $DOCKER_ACME_SSL_D_KEY $DOCKER_APPL_SSL_KEY
fi
fi
}

View File

@ -0,0 +1,13 @@
#!/bin/sh
#
# 50-acme-monitor-tlscert
#
# Functions defined in:
# 10-acme-common
#
#
# Setup ACME monitor and arrange certificate sym-links
#
acme_monitor_tls_cert
acme_symlink_tls_cert

View File

@ -85,10 +85,13 @@ dc_log_stamp() {
} }
# #
# Tests if pkg is installed # Tests if command is in the path
# #
dc_is_command() { [ -x "$(command -v $1)" ] ;} dc_is_command() { [ -x "$(command -v $1)" ] ;}
#
# Tests if pkgs are installed
#
dc_is_installed() { dc_is_installed() {
if dc_is_command apk; then if dc_is_command apk; then
ver_cmd="apk -e info" ver_cmd="apk -e info"
@ -97,7 +100,9 @@ dc_is_installed() {
else else
dc_log 5 "No package manager found among: apk dpkg" dc_log 5 "No package manager found among: apk dpkg"
fi fi
$ver_cmd $1 &>/dev/null for cmd in $@; do
$ver_cmd $cmd > /dev/null 2>&1 || return 1
done
} }
# #

View File

@ -61,6 +61,7 @@ init_service() {
local clearpid= local clearpid=
local sourcefile= local sourcefile=
local sv_name cmd runsv_dir svlog_dir sv_log sv_down sv_force options local sv_name cmd runsv_dir svlog_dir sv_log sv_down sv_force options
dc_log 7 "Called with args $@"
while getopts ":dfhln:s:q" opts; do while getopts ":dfhln:s:q" opts; do
case "${opts}" in case "${opts}" in
d) sv_down="down"; add_opt "down";; d) sv_down="down"; add_opt "down";;
@ -104,6 +105,8 @@ init_service() {
!cat !cat
chmod +x $runsv_dir/log/run chmod +x $runsv_dir/log/run
fi fi
else
dc_log 4 "Cannot find command."
fi fi
} }

View File

@ -30,13 +30,13 @@ zpush_cfg_file=$DOCKER_CONF_DIR2/config.php
# Define environment variables # Define environment variables
# #
ssl_env_vars="SSL_CERTIFICATE_FILE SSL_CIPHERS SSL_CURVES SSL_PREFER_SERVER_CIPHERS SSL_PRIVATE_KEY_FILE SSL_VERIFY_CLIENT SSL_VERIFY_FILE SSL_VERIFY_PATH TLS_MIN_PROTO" ssl_env_vars="SSL_CERTIFICATE_FILE SSL_CIPHERS SSL_CURVES SSL_PREFER_SERVER_CIPHERS SSL_PRIVATE_KEY_FILE SSL_VERIFY_CLIENT SSL_VERIFY_FILE SSL_VERIFY_PATH TLS_MIN_PROTO"
dagent_env_vars="LMTP_LISTEN LOG_LEVEL SPAM_HEADER_NAME SPAM_HEADER_VALUE" dagent_env_vars="LMTP_LISTEN SPAM_HEADER_NAME SPAM_HEADER_VALUE LOG_LEVEL"
gateway_env_vars="BYPASS_AUTH DISABLE_PLAINTEXT_AUTH HTML_SAFETY_FILTER IMAP_CAPABILITY_IDLE IMAP_EXPUNGE_ON_DELETE IMAP_IGNORE_COMMAND_IDLE IMAP_LISTEN IMAP_MAX_FAIL_COMMANDS IMAP_MAX_MESSAGESIZE IMAP_ONLY_MAILFOLDERS IMAP_PUBLIC_FOLDERS IMAPS_LISTEN POP3_LISTEN POP3S_LISTEN DISABLE_PLAINTEXT_AUTH LOG_LEVEL" gateway_env_vars="BYPASS_AUTH DISABLE_PLAINTEXT_AUTH HTML_SAFETY_FILTER IMAP_CAPABILITY_IDLE IMAP_EXPUNGE_ON_DELETE IMAP_IGNORE_COMMAND_IDLE IMAP_LISTEN IMAP_MAX_FAIL_COMMANDS IMAP_MAX_MESSAGESIZE IMAP_ONLY_MAILFOLDERS IMAP_PUBLIC_FOLDERS IMAPS_LISTEN POP3_LISTEN POP3S_LISTEN DISABLE_PLAINTEXT_AUTH LOG_LEVEL"
ical_env_vars="ICAL_LISTEN ICALS_LISTEN ENABLE_ICAL_GET LOG_LEVEL" ical_env_vars="ICAL_LISTEN ICALS_LISTEN ENABLE_ICAL_GET LOG_LEVEL"
ldap_env_vars="LDAP_URI LDAP_STARTTLS LDAP_BIND_USER LDAP_BIND_PASSWD LDAP_SEARCH_BASE LDAP_USER_TYPE_ATTRIBUTE_VALUE LDAP_GROUP_TYPE_ATTRIBUTE_VALUE LDAP_USER_SEARCH_FILTER" ldap_env_vars="LDAP_URI LDAP_STARTTLS LDAP_BIND_USER LDAP_BIND_PASSWD LDAP_SEARCH_BASE LDAP_USER_TYPE_ATTRIBUTE_VALUE LDAP_GROUP_TYPE_ATTRIBUTE_VALUE LDAP_USER_SEARCH_FILTER"
search_env_vars="INDEX_PROCESSES INDEX_DRAFTS INDEX_JUNK SUGGESTIONS INDEX_ATTACHMENTS INDEX_ATTACHMENT_MAX_SIZE" search_env_vars="INDEX_PROCESSES INDEX_DRAFTS INDEX_JUNK SUGGESTIONS INDEX_ATTACHMENTS INDEX_ATTACHMENT_MAX_SIZE LOG_LEVEL LOG_METHOD"
server_env_vars="MYSQL_HOST MYSQL_PORT MYSQL_DATABASE MYSQL_USER MYSQL_PASSWORD DISABLED_FEATURES USER_PLUGIN LOG_LEVEL SEARCH_TIMEOUT" server_env_vars="MYSQL_HOST MYSQL_PORT MYSQL_DATABASE MYSQL_USER MYSQL_PASSWORD DISABLED_FEATURES USER_PLUGIN SEARCH_TIMEOUT LOG_LEVEL"
spamd_env_vars="LOG_METHOD SPAM_DIR SPAM_DB HEADER_TAG LEARN_HAM HAM_DIR SA_GROUP" spamd_env_vars="SPAM_DIR SPAM_DB HEADER_TAG LEARN_HAM HAM_DIR SA_GROUP LOG_LEVEL LOG_METHOD"
spooler_env_vars="SMTP_SERVER SMTP_PORT LOG_LEVEL" spooler_env_vars="SMTP_SERVER SMTP_PORT LOG_LEVEL"
sqlstate_env_vars="STATE_SQL_ENGINE STATE_SQL_SERVER STATE_SQL_PORT STATE_SQL_DATABASE STATE_SQL_USER STATE_SQL_PASSWORD STATE_SQL_OPTIONS" sqlstate_env_vars="STATE_SQL_ENGINE STATE_SQL_SERVER STATE_SQL_PORT STATE_SQL_DATABASE STATE_SQL_USER STATE_SQL_PASSWORD STATE_SQL_OPTIONS"
@ -94,9 +94,6 @@ kopano_apply_phpenvvars() {
# #
# Update SSL_CERTIFICATE_FILE and SSL_PRIVATE_KEY_FILE. # Update SSL_CERTIFICATE_FILE and SSL_PRIVATE_KEY_FILE.
# Variables defined in 30-acme-common
# DOCKER_APPL_SSL_CERT
# DOCKER_APPL_SSL_KEY
# #
kopano_export_tls_cert() { kopano_export_tls_cert() {
if ([ -f "$DOCKER_APPL_SSL_CERT" ] && [ -f "$DOCKER_APPL_SSL_KEY" ]); then if ([ -f "$DOCKER_APPL_SSL_CERT" ] && [ -f "$DOCKER_APPL_SSL_KEY" ]); then