- [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
parent
162e9ca256
commit
8b252367b9
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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" \
|
||||||
|
|
22
README.md
22
README.md
|
@ -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.
|
||||||
|
|
||||||
|
### Let’s Encrypt LTS certificates using [Traefik](https://docs.traefik.io/)
|
||||||
|
|
||||||
|
[Let’s 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`
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue