scripts: new log (#2493)

* added new `_log` function

With `_log`, the `_notify` method wa rendered obsolete. `_notify` was
not completely removed due to test failures in `check-for-changes.sh`.

The new `_log` function properly uses log levels such as `trace`,
`debug`, `info`, `warn` and `error`. It provides a cleaner solution
and renders `DMS_DEBUG` obsolete too (as only `_notify` depends on it).

* converted all helper script to new `_log` function

* converted all startup stacks to new `log` function

* `start-mailserver.sh` now uses new `_log` function

* final test and misc small script adjustments

* updated documentation
This commit is contained in:
Georg Lauterbach 2022-03-21 07:07:52 +01:00 committed by GitHub
parent d8d4b6a189
commit 24031ae365
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 367 additions and 221 deletions

View File

@ -15,9 +15,17 @@ title: Environment Variables
##### DMS_DEBUG
This environment variable is deprecated. Use `LOG_LEVEL` instead.
- **0** => Debug disabled
- 1 => Enables debug on startup
##### LOG_LEVEL
Set the log level for DMS. This is mostly relevant for container startup scripts and change detection event feedback.
Valid values (in order of increasing verbosity) are: `error`, `warn`, `info`, `debug` and `trace`. The default log level is `info`.
##### SUPERVISOR_LOGLEVEL
Here you can adjust the [log-level for Supervisor](http://supervisord.org/logging.html#activity-log-levels). Possible values are

View File

@ -115,7 +115,7 @@ A positive example, which is taken from `setup-stack.sh`, would be
```bash
function _setup_postfix_aliases
{
_notify 'task' 'Setting up Postfix Aliases'
_log 'debug' 'Setting up Postfix aliases'
: >/etc/postfix/virtual
: >/etc/postfix/regexp
@ -139,10 +139,10 @@ function _setup_postfix_aliases
DOMAIN=$(echo "${FROM}" | cut -d @ -f2)
# if they are equal it means the line looks like: "user1 other@example.com"
[[ ${UNAME} != "${DOMAIN}" ]] && echo "${DOMAIN}" >> /tmp/vhost.tmp
[[ ${UNAME} != "${DOMAIN}" ]] && echo "${DOMAIN}" >>/tmp/vhost.tmp
done < <(grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-virtual.cf || true)
else
_notify 'inf' "Warning '/tmp/docker-mailserver/postfix-virtual.cf' is not provided. No mail alias/forward created."
_log 'debug' "'/tmp/docker-mailserver/postfix-virtual.cf' not provided - no mail alias/forward created"
fi
...

View File

@ -13,10 +13,18 @@
# => Specify a fully-qualified domainname to serve mail for. This is used for many of the config features so if you can't set your hostname (e.g. you're in a container platform that doesn't let you) specify it in this environment variable.
OVERRIDE_HOSTNAME=
# (deprecated: use LOG_LEVEL instead)
# 0 => Debug disabled
# 1 => Enables debug on startup
DMS_DEBUG=0
# Set the log level for DMS.
# This is mostly relevant for container startup scripts and change detection event feedback.
#
# Valid values (in order of increasing verbosity) are: `error`, `warn`, `info`, `debug` and `trace`.
# The default log level is `info`.
LOG_LEVEL=info
# critical => Only show critical messages
# error => Only show erroneous output
# **warn** => Show warnings

View File

@ -3,5 +3,5 @@
# shellcheck source=../scripts/helpers/index.sh
source /usr/local/bin/helpers/index.sh
_notify 'inf' 'Printing environment variables. Make sure no sensitive data is copied.'
_log 'debug' 'Printing environment variables. Make sure no sensitive data is copied.'
cat /etc/dms-settings

View File

@ -15,10 +15,10 @@ function _create_accounts
if [[ -f /tmp/docker-mailserver/postfix-accounts.cf ]] && [[ ${ENABLE_LDAP} -ne 1 ]]
then
_notify 'inf' "Checking file line endings"
_log 'trace' "Checking file line endings"
sed -i 's|\r||g' /tmp/docker-mailserver/postfix-accounts.cf
_notify 'inf' "Regenerating postfix user list"
_log 'trace' "Regenerating postfix user list"
echo "# WARNING: this file is auto-generated. Modify /tmp/docker-mailserver/postfix-accounts.cf to edit the user list." > /etc/postfix/vmailbox
# checking that /tmp/docker-mailserver/postfix-accounts.cf ends with a newline
@ -54,9 +54,9 @@ function _create_accounts
if [[ -z ${USER_ATTRIBUTES} ]]
then
_notify 'inf' "Creating user '${USER}' for domain '${DOMAIN}'"
_log 'debug' "Creating user '${USER}' for domain '${DOMAIN}'"
else
_notify 'inf' "Creating user '${USER}' for domain '${DOMAIN}' with attributes '${USER_ATTRIBUTES}'"
_log 'debug' "Creating user '${USER}' for domain '${DOMAIN}' with attributes '${USER_ATTRIBUTES}'"
fi
local POSTFIX_VMAILBOX_LINE DOVECOT_USERDB_LINE
@ -64,7 +64,7 @@ function _create_accounts
POSTFIX_VMAILBOX_LINE="${LOGIN} ${DOMAIN}/${USER}/"
if grep -qF "${POSTFIX_VMAILBOX_LINE}" /etc/postfix/vmailbox
then
_notify 'warn' "User '${USER}@${DOMAIN}' will not be added to '/etc/postfix/vmailbox' twice"
_log 'warn' "User '${USER}@${DOMAIN}' will not be added to '/etc/postfix/vmailbox' twice"
else
echo "${POSTFIX_VMAILBOX_LINE}" >>/etc/postfix/vmailbox
fi
@ -74,7 +74,7 @@ function _create_accounts
DOVECOT_USERDB_LINE="${LOGIN}:${PASS}:5000:5000::/var/mail/${DOMAIN}/${USER}::${USER_ATTRIBUTES}"
if grep -qF "${DOVECOT_USERDB_LINE}" "${DOVECOT_USERDB_FILE}"
then
_notify 'warn' "Login '${LOGIN}' will not be added to '${DOVECOT_USERDB_FILE}' twice"
_log 'warn' "Login '${LOGIN}' will not be added to '${DOVECOT_USERDB_FILE}' twice"
else
echo "${DOVECOT_USERDB_LINE}" >>"${DOVECOT_USERDB_FILE}"
fi
@ -87,7 +87,7 @@ function _create_accounts
cp "/tmp/docker-mailserver/${LOGIN}.dovecot.sieve" "/var/mail/${DOMAIN}/${USER}/.dovecot.sieve"
fi
echo "${DOMAIN}" >> /tmp/vhost.tmp
echo "${DOMAIN}" >>/tmp/vhost.tmp
done < <(grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-accounts.cf)
_create_dovecot_alias_dummy_accounts
@ -128,11 +128,11 @@ function _create_dovecot_alias_dummy_accounts
if ! grep -q "${REAL_FQUN}" /tmp/docker-mailserver/postfix-accounts.cf
then
_notify 'inf' "Alias '${ALIAS}' is non-local (or mapped to a non-existing account) and will not be added to Dovecot's userdb"
_log 'debug' "Alias '${ALIAS}' is non-local (or mapped to a non-existing account) and will not be added to Dovecot's userdb"
continue
fi
_notify 'inf' "Adding alias '${ALIAS}' for user '${REAL_FQUN}' to Dovecot's userdb"
_log 'debug' "Adding alias '${ALIAS}' for user '${REAL_FQUN}' to Dovecot's userdb"
# ${REAL_ACC[0]} => real account name (e-mail address) == ${REAL_FQUN}
# ${REAL_ACC[1]} => password hash
@ -157,7 +157,7 @@ function _create_dovecot_alias_dummy_accounts
DOVECOT_USERDB_LINE="${ALIAS}:${REAL_ACC[1]}:5000:5000::/var/mail/${REAL_DOMAINNAME}/${REAL_USERNAME}::${REAL_ACC[2]:-}"
if grep -qF "${DOVECOT_USERDB_LINE}" "${DOVECOT_USERDB_FILE}"
then
_notify 'warn' "Alias '${ALIAS}' will not be added to '${DOVECOT_USERDB_FILE}' twice"
_log 'warn' "Alias '${ALIAS}' will not be added to '${DOVECOT_USERDB_FILE}' twice"
else
echo "${DOVECOT_USERDB_LINE}" >>"${DOVECOT_USERDB_FILE}"
fi

View File

@ -32,7 +32,7 @@ function _handle_postfix_virtual_config
[[ ${UNAME} != "${DOMAIN}" ]] && echo "${DOMAIN}" >>/tmp/vhost.tmp
done < <(grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-virtual.cf || true)
else
_notify 'inf' "Warning '/tmp/docker-mailserver/postfix-virtual.cf' is not provided. No mail alias/forward created."
_log 'debug' "'/tmp/docker-mailserver/postfix-virtual.cf' not provided - no mail alias/forward created"
fi
}
@ -40,7 +40,7 @@ function _handle_postfix_regexp_config
{
if [[ -f /tmp/docker-mailserver/postfix-regexp.cf ]]
then
_notify 'inf' "Adding regexp alias file postfix-regexp.cf"
_log 'trace' "Adding regexp alias file postfix-regexp.cf"
cp -f /tmp/docker-mailserver/postfix-regexp.cf /etc/postfix/regexp
@ -55,7 +55,7 @@ function _handle_postfix_regexp_config
function _handle_postfix_aliases_config
{
_notify 'inf' 'Configuring root alias'
_log 'trace' 'Configuring root alias'
echo "root: ${POSTMASTER_ADDRESS}" >/etc/aliases
@ -63,7 +63,7 @@ function _handle_postfix_aliases_config
then
cat /tmp/docker-mailserver/postfix-aliases.cf >>/etc/aliases
else
_notify 'inf' "'/tmp/docker-mailserver/postfix-aliases.cf' is not provided, it will be auto created."
_log 'trace' "'/tmp/docker-mailserver/postfix-aliases.cf' is not provided, it will be auto created."
: >/tmp/docker-mailserver/postfix-aliases.cf
fi

View File

@ -2,7 +2,14 @@
function _errex
{
echo -e "Error :: ${*}\nAborting." >&2
if [[ -n ${1+set} ]]
then
_log 'error' "${1}"
else
_log 'error' "Call to '_errex' is missing a message to log"
fi
_log 'error' 'Aborting'
exit 1
}
@ -62,13 +69,13 @@ function dms_panic__no_file { dms_panic 'no-file' "${1}" "${2}"; }
function dms_panic__misconfigured { dms_panic 'misconfigured' "${1}" "${2}"; }
function dms_panic__invalid_value { dms_panic 'invalid-value' "${1}" "${2}"; }
# Call this method when you want to panic (emit a 'FATAL' log level error, and exit uncleanly).
# Call this method when you want to panic (i.e. emit an 'ERROR' log, and exit uncleanly).
# `dms_panic` methods should be preferred if your failure type is supported.
function _shutdown
{
local FATAL_ERROR_MESSAGE=$1
_log 'error' "${1}"
_log 'error' 'Shutting down'
_notify 'fatal' "${FATAL_ERROR_MESSAGE}"
_notify 'err' "Shutting down.."
kill 1
exit 1
}

View File

@ -12,19 +12,20 @@ function _create_lock
LOCK_FILE="/tmp/docker-mailserver/${SCRIPT_NAME}.lock"
while [[ -e "${LOCK_FILE}" ]]
do
_notify 'warn' "Lock file ${LOCK_FILE} exists. Another ${SCRIPT_NAME} execution is happening. Trying again shortly..."
_log 'warn' "Lock file '${LOCK_FILE}' exists - another execution of '${SCRIPT_NAME}' is happening - trying again shortly"
# Handle stale lock files left behind on crashes
# or premature/non-graceful exits of containers while they're making changes
if [[ -n "$(find "${LOCK_FILE}" -mmin +1 2>/dev/null)" ]]
then
_notify 'warn' "Lock file older than 1 minute. Removing stale lock file."
_log 'warn' 'Lock file older than 1 minute - removing stale lock file'
rm -f "${LOCK_FILE}"
_notify 'inf' "Removed stale lock ${LOCK_FILE}."
fi
sleep 5
done
trap _remove_lock EXIT
echo "${LOCK_ID}" > "${LOCK_FILE}"
_log 'trace' "Creating lock ${LOCK_FILE}"
echo "${LOCK_ID}" >"${LOCK_FILE}"
}
function _remove_lock
@ -34,6 +35,6 @@ function _remove_lock
if [[ -e "${LOCK_FILE}" ]] && grep -q "${LOCK_ID}" "${LOCK_FILE}" # Ensure we don't delete a lock that's not ours
then
rm -f "${LOCK_FILE}"
_notify 'inf' "Removed lock ${LOCK_FILE}."
_log 'trace' "Removed lock ${LOCK_FILE}"
fi
}

View File

@ -1,5 +1,100 @@
#! /bin/bash
LOG_RESET='\e[0m'
LOG_LGRAY='\e[37m'
LOG_LBLUE='\e[94m'
LOG_BLUE='\e[34m'
LOG_LYELLOW='\e[93m'
LOG_RED='\e[91m'
# ### DMS Logging Functionality
#
# This function provides the logging for scripts used by DMS.
# It adheres to the convention for log levels.
# Valid values (in order of increasing verbosity) are: `error`,
# `warn`, `info`, `debug` and `trace`. The default log level
# is `info`.
#
# #### Arguments
#
# $1 :: the log level to log the message with
# $2 :: the message
#
# #### Panics
#
# If the first argument is not set or invalid, an error
# message is logged. Likewise when the second argument
# is missing. Both failures will return with exit code '1'.
function _log
{
if [[ -z ${1+set} ]]
then
echo "Call to '_log' is missing a valid log level" >&2
return 1
fi
if [[ -z ${2+set} ]]
then
echo "Call to '_log' is missing a message to log" >&2
return 1
fi
local MESSAGE LEVEL_AS_INT
MESSAGE="${LOG_RESET}["
case "${LOG_LEVEL:-}" in
( 'trace' ) LEVEL_AS_INT=5 ;;
( 'debug' ) LEVEL_AS_INT=4 ;;
( 'warn' ) LEVEL_AS_INT=2 ;;
( 'error' ) LEVEL_AS_INT=1 ;;
( * ) LEVEL_AS_INT=3 ;;
esac
case "${1}" in
( 'trace' )
[[ ${LEVEL_AS_INT} -ge 5 ]] || return 0
MESSAGE+=" ${LOG_LGRAY}TRACE "
;;
( 'debug' )
[[ ${LEVEL_AS_INT} -ge 4 ]] || return 0
MESSAGE+=" ${LOG_LBLUE}DEBUG "
;;
( 'info' )
[[ ${LEVEL_AS_INT} -ge 3 ]] || return 0
MESSAGE+=" ${LOG_BLUE}INF "
;;
( 'warn' )
[[ ${LEVEL_AS_INT} -ge 2 ]] || return 0
MESSAGE+=" ${LOG_LYELLOW}WARNING "
;;
( 'error' )
[[ ${LEVEL_AS_INT} -ge 1 ]] || return 0
MESSAGE+=" ${LOG_RED}ERROR " ;;
( * )
echo "Call to '_log' with invalid log level argument '${1}'" >&2
return 1
;;
esac
MESSAGE+="${LOG_RESET}] ${2}"
if [[ ${1} =~ ^(warn|error)$ ]]
then
echo -e "${MESSAGE}" >&2
else
echo -e "${MESSAGE}"
fi
}
# Still used by `check-for-changes.sh` for legacy / test purposes. Adjusting
# `check-for-changes.sh` must be done with great care and requires some effort.
# As a consequence, this function is kept to keep some of the original log for
# `check-for-changes.sh` for tests to pass.
function _notify
{
{ [[ -z ${1:-} ]] || [[ -z ${2:-} ]] ; } && return 0

View File

@ -17,13 +17,13 @@ function _relayhost_sasl
{
if [[ ! -f /tmp/docker-mailserver/postfix-sasl-password.cf ]] && [[ -z ${RELAY_USER} || -z ${RELAY_PASSWORD} ]]
then
_notify 'warn' "No relay auth file found and no default set"
_log 'warn' "No relay auth file found and no default set"
return 1
fi
if [[ -f /tmp/docker-mailserver/postfix-sasl-password.cf ]]
then
_notify 'inf' "Adding relay authentication from postfix-sasl-password.cf"
_log 'trace' "Adding relay authentication from postfix-sasl-password.cf"
# add domain-specific auth from config file:
while read -r LINE
@ -60,7 +60,7 @@ function _populate_relayhost_map
if [[ -f /tmp/docker-mailserver/postfix-relaymap.cf ]]
then
_notify 'inf' "Adding relay mappings from postfix-relaymap.cf"
_log 'trace' "Adding relay mappings from postfix-relaymap.cf"
# keep lines which are not a comment *and* have a destination.
sed -n '/^\s*[^#[:space:]]\S*\s\+\S/p' /tmp/docker-mailserver/postfix-relaymap.cf >> /etc/postfix/relayhost_map
fi
@ -75,7 +75,7 @@ function _populate_relayhost_map
# DOMAIN not already present *and* not ignored
if ! grep -q -e "^@${DOMAIN}\b" /etc/postfix/relayhost_map && ! grep -qs -e "^\s*@${DOMAIN}\s*$" /tmp/docker-mailserver/postfix-relaymap.cf
then
_notify 'inf' "Adding relay mapping for ${DOMAIN}"
_log 'trace' "Adding relay mapping for ${DOMAIN}"
echo "@${DOMAIN} [${RELAY_HOST}]:${RELAY_PORT}" >> /etc/postfix/relayhost_map
fi
done
@ -96,18 +96,18 @@ function _relayhost_configure_postfix
function _setup_relayhost
{
_notify 'task' 'Setting up Postfix Relay Hosts'
_log 'debug' 'Setting up Postfix Relay Hosts'
if [[ -n ${DEFAULT_RELAY_HOST} ]]
then
_notify 'inf' "Setting default relay host ${DEFAULT_RELAY_HOST} to /etc/postfix/main.cf"
_log 'trace' "Setting default relay host ${DEFAULT_RELAY_HOST} to /etc/postfix/main.cf"
postconf -e "relayhost = ${DEFAULT_RELAY_HOST}"
fi
if [[ -n ${RELAY_HOST} ]]
then
_relayhost_default_port_fallback
_notify 'inf' "Setting up outgoing email relaying via ${RELAY_HOST}:${RELAY_PORT}"
_log 'trace' "Setting up outgoing email relaying via ${RELAY_HOST}:${RELAY_PORT}"
# Expects `_sasl_passwd_create` was called prior in `setup-stack.sh`
_relayhost_sasl

View File

@ -2,7 +2,7 @@
function _setup_ssl
{
_notify 'task' 'Setting up SSL'
_log 'debug' 'Setting up SSL'
local POSTFIX_CONFIG_MAIN='/etc/postfix/main.cf'
local POSTFIX_CONFIG_MASTER='/etc/postfix/master.cf'
@ -116,10 +116,10 @@ function _setup_ssl
then
EXTRACTED_DOMAIN=('DOMAINNAME' "${DOMAINNAME}")
else
_notify 'err' "'setup-stack.sh' | letsencrypt (acme.json) failed to identify a certificate to extract"
_log 'warn' "letsencrypt (acme.json) failed to identify a certificate to extract"
fi
_notify 'inf' "'setup-stack.sh' | letsencrypt (acme.json) extracted certificate using ${EXTRACTED_DOMAIN[0]}: '${EXTRACTED_DOMAIN[1]}'"
_log 'trace' "letsencrypt (acme.json) extracted certificate using ${EXTRACTED_DOMAIN[0]}: '${EXTRACTED_DOMAIN[1]}'"
fi
}
@ -132,7 +132,7 @@ function _setup_ssl
_apply_tls_level "${TLS_MODERN_SUITE}" "${TLS_MODERN_IGNORE}" "${TLS_MODERN_MIN}"
_notify 'inf' "TLS configured with 'modern' ciphers"
_log 'debug' "TLS configured with 'modern' ciphers"
;;
( "intermediate" )
@ -154,11 +154,11 @@ function _setup_ssl
-e 's|^(CipherString).*|\1 = DEFAULT@SECLEVEL=1|' \
/usr/lib/ssl/openssl.cnf
_notify 'inf' "TLS configured with 'intermediate' ciphers"
_log 'debug' "TLS configured with 'intermediate' ciphers"
;;
( * )
_notify 'err' "TLS_LEVEL not found [ in ${FUNCNAME[0]} ]"
_log 'warn' "TLS_LEVEL '${TLS_LEVEL}' not valid"
;;
esac
@ -169,7 +169,7 @@ function _setup_ssl
# NOTE: Some `SSL_TYPE` logic uses mounted certs/keys directly, some make an internal copy either retaining filename or renaming.
case "${SSL_TYPE}" in
( "letsencrypt" )
_notify 'inf' "Configuring SSL using 'letsencrypt'"
_log 'debug' "Configuring SSL using 'letsencrypt'"
# `docker-mailserver` will only use one certificate from an FQDN folder in `/etc/letsencrypt/live/`.
# We iterate the sequence [SSL_DOMAIN, HOSTNAME, DOMAINNAME] to find a matching FQDN folder.
@ -200,7 +200,7 @@ function _setup_ssl
then
LETSENCRYPT_DOMAIN=${DOMAINNAME}
else
_notify 'err' "Cannot find a valid DOMAIN for '/etc/letsencrypt/live/<DOMAIN>/', tried: '${SSL_DOMAIN}', '${HOSTNAME}', '${DOMAINNAME}'"
_log 'warn' "Cannot find a valid DOMAIN for '/etc/letsencrypt/live/<DOMAIN>/', tried: '${SSL_DOMAIN}', '${HOSTNAME}', '${DOMAINNAME}'"
dms_panic__misconfigured 'LETSENCRYPT_DOMAIN' "${SCOPE_SSL_TYPE}"
return 1
fi
@ -213,13 +213,13 @@ function _setup_ssl
then
LETSENCRYPT_KEY='key'
else
_notify 'err' "Cannot find key file ('privkey.pem' or 'key.pem') in '/etc/letsencrypt/live/${LETSENCRYPT_DOMAIN}/'"
_log 'warn' "Cannot find key file ('privkey.pem' or 'key.pem') in '/etc/letsencrypt/live/${LETSENCRYPT_DOMAIN}/'"
dms_panic__misconfigured 'LETSENCRYPT_KEY' "${SCOPE_SSL_TYPE}"
return 1
fi
# Update relevant config for Postfix and Dovecot
_notify 'inf' "Adding ${LETSENCRYPT_DOMAIN} SSL certificate to the postfix and dovecot configuration"
_log 'trace' "Adding ${LETSENCRYPT_DOMAIN} SSL certificate to the postfix and dovecot configuration"
# LetsEncrypt `fullchain.pem` and `privkey.pem` contents are detailed here from CertBot:
# https://certbot.eff.org/docs/using.html#where-are-my-certificates
@ -230,11 +230,11 @@ function _setup_ssl
_set_certificate "${PRIVATE_KEY}" "${CERT_CHAIN}"
_notify 'inf' "SSL configured with 'letsencrypt' certificates"
_log 'trace' "SSL configured with 'letsencrypt' certificates"
;;
( "custom" ) # (hard-coded path) Use a private key with full certificate chain all in a single PEM file.
_notify 'inf' "Adding ${HOSTNAME} SSL certificate"
_log 'debug' "Adding ${HOSTNAME} SSL certificate"
# NOTE: Dovecot works fine still as both values are bundled into the keychain
local COMBINED_PEM_NAME="${HOSTNAME}-full.pem"
@ -248,14 +248,14 @@ function _setup_ssl
_set_certificate "${KEY_WITH_FULLCHAIN}"
_notify 'inf' "SSL configured with 'CA signed/custom' certificates"
_log 'trace' "SSL configured with 'CA signed/custom' certificates"
else
dms_panic__no_file "${TMP_KEY_WITH_FULLCHAIN}" "${SCOPE_SSL_TYPE}"
fi
;;
( "manual" ) # (dynamic path via ENV) Use separate private key and cert/chain files (should be PEM encoded)
_notify 'inf' "Configuring certificates using key ${SSL_KEY_PATH} and cert ${SSL_CERT_PATH}"
_log 'debug' "Configuring certificates using key ${SSL_KEY_PATH} and cert ${SSL_CERT_PATH}"
# Source files are copied internally to these destinations:
local PRIVATE_KEY="${DMS_TLS_PATH}/key"
@ -287,7 +287,7 @@ function _setup_ssl
# Support for a fallback certificate, useful for hybrid/dual ECDSA + RSA certs
if [[ -n ${SSL_ALT_KEY_PATH} ]] && [[ -n ${SSL_ALT_CERT_PATH} ]]
then
_notify 'inf' "Configuring fallback certificates using key ${SSL_ALT_KEY_PATH} and cert ${SSL_ALT_CERT_PATH}"
_log 'trace' "Configuring fallback certificates using key ${SSL_ALT_KEY_PATH} and cert ${SSL_ALT_CERT_PATH}"
_set_alt_certificate "${SSL_ALT_KEY_PATH}" "${SSL_ALT_CERT_PATH}"
else
@ -299,14 +299,14 @@ function _setup_ssl
"${DOVECOT_CONFIG_SSL}"
fi
_notify 'inf' "SSL configured with 'Manual' certificates"
_log 'trace' "SSL configured with 'Manual' certificates"
else
dms_panic__no_file "${SSL_KEY_PATH} or ${SSL_CERT_PATH}" "${SCOPE_SSL_TYPE}"
fi
;;
( "self-signed" ) # (hard-coded path) Use separate private key and cert/chain files (should be PEM encoded), expects self-signed CA
_notify 'inf' "Adding ${HOSTNAME} SSL certificate"
_log 'debug' "Adding ${HOSTNAME} SSL certificate"
local KEY_NAME="${HOSTNAME}-key.pem"
local CERT_NAME="${HOSTNAME}-cert.pem"
@ -344,14 +344,14 @@ function _setup_ssl
local PRIVATE_CA="/etc/ssl/certs/cacert-${HOSTNAME}.pem"
ln -s "${CA_CERT}" "${PRIVATE_CA}"
_notify 'inf' "SSL configured with 'self-signed' certificates"
_log 'trace' "SSL configured with 'self-signed' certificates"
else
dms_panic__no_file "${SS_KEY} or ${SS_CERT}" "${SCOPE_SSL_TYPE}"
fi
;;
( '' ) # No SSL/TLS certificate used/required, plaintext auth permitted over insecure connections
_notify 'warn' "(INSECURE!) SSL configured with plain text access. DO NOT USE FOR PRODUCTION DEPLOYMENT."
_log 'warn' "(INSECURE!) SSL configured with plain text access. DO NOT USE FOR PRODUCTION DEPLOYMENT."
# Untested. Not officially supported.
# Postfix configuration:
@ -413,7 +413,7 @@ function _extract_certs_from_acme
local CERT_DOMAIN=${1}
if [[ -z ${CERT_DOMAIN} ]]
then
_notify 'err' "_extract_certs_from_acme | CERT_DOMAIN is empty"
_log 'warn' "_extract_certs_from_acme | CERT_DOMAIN is empty"
return 1
fi
@ -423,7 +423,7 @@ function _extract_certs_from_acme
if [[ -z ${KEY} ]] || [[ -z ${CERT} ]]
then
_notify 'warn' "_extract_certs_from_acme | Unable to find key and/or cert for '${CERT_DOMAIN}' in '/etc/letsencrypt/acme.json'"
_log 'warn' "_extract_certs_from_acme | Unable to find key and/or cert for '${CERT_DOMAIN}' in '/etc/letsencrypt/acme.json'"
return 1
fi
@ -438,7 +438,7 @@ function _extract_certs_from_acme
echo "${KEY}" | base64 -d > "/etc/letsencrypt/live/${CERT_DOMAIN}/key.pem" || exit 1
echo "${CERT}" | base64 -d > "/etc/letsencrypt/live/${CERT_DOMAIN}/fullchain.pem" || exit 1
_notify 'inf' "_extract_certs_from_acme | Certificate successfully extracted for '${CERT_DOMAIN}'"
_log 'trace' "_extract_certs_from_acme | Certificate successfully extracted for '${CERT_DOMAIN}'"
}
# Remove the `*.` prefix if it exists, else returns the input value

View File

@ -46,6 +46,7 @@ VARS[FAIL2BAN_BLOCKTYPE]="${FAIL2BAN_BLOCKTYPE:=drop}"
VARS[FETCHMAIL_PARALLEL]="${FETCHMAIL_PARALLEL:=0}"
VARS[FETCHMAIL_POLL]="${FETCHMAIL_POLL:=300}"
VARS[LDAP_START_TLS]="${LDAP_START_TLS:=no}"
VARS[LOG_LEVEL]="${LOG_LEVEL:=info}"
VARS[LOGROTATE_INTERVAL]="${LOGROTATE_INTERVAL:=weekly}"
VARS[LOGWATCH_INTERVAL]="${LOGWATCH_INTERVAL:=none}"
VARS[LOGWATCH_RECIPIENT]="${LOGWATCH_RECIPIENT:=${REPORT_RECIPIENT}}"
@ -89,12 +90,13 @@ VARS[VIRUSMAILS_DELETE_DELAY]="${VIRUSMAILS_DELETE_DELAY:=7}"
function register_functions
{
_notify 'tasklog' 'Initializing setup'
_notify 'task' 'Registering functions'
_log 'info' 'Initializing setup'
_log 'debug' 'Registering functions'
# ? >> Checks
_register_check_function '_check_hostname'
_register_check_function '_check_log_level'
# ? >> Setup
@ -201,31 +203,31 @@ function register_functions
function _register_start_daemon
{
DAEMONS_START+=("${1}")
_notify 'inf' "${1}() registered"
_log 'trace' "${1}() registered"
}
function _register_setup_function
{
FUNCS_SETUP+=("${1}")
_notify 'inf' "${1}() registered"
_log 'trace' "${1}() registered"
}
function _register_fix_function
{
FUNCS_FIX+=("${1}")
_notify 'inf' "${1}() registered"
_log 'trace' "${1}() registered"
}
function _register_check_function
{
FUNCS_CHECK+=("${1}")
_notify 'inf' "${1}() registered"
_log 'trace' "${1}() registered"
}
function _register_misc_function
{
FUNCS_MISC+=("${1}")
_notify 'inf' "${1}() registered"
_log 'trace' "${1}() registered"
}
# ------------------------------------------------------------
@ -260,12 +262,12 @@ source /usr/local/bin/daemons-stack.sh
# ? >> Executing all stacks
# ------------------------------------------------------------
_notify 'tasklog' "Welcome to docker-mailserver $(</VERSION)"
_log 'info' "Welcome to docker-mailserver $(</VERSION)"
register_functions
check
setup
[[ ${DMS_DEBUG} -eq 1 ]] && print-environment
[[ ${LOG_LEVEL} =~ (debug|trace) ]] && print-environment
fix
start_misc
start_daemons
@ -273,7 +275,7 @@ start_daemons
# marker to check, if container was restarted
date >/CONTAINER_START
_notify 'tasklog' "${HOSTNAME} is up and running"
_log 'info' "${HOSTNAME} is up and running"
touch /var/log/mail/mail.log
tail -Fn 0 /var/log/mail/mail.log

View File

@ -2,7 +2,7 @@
function check
{
_notify 'tasklog' 'Checking configuration'
_log 'info' 'Checking configuration'
for FUNC in "${FUNCS_CHECK[@]}"
do
${FUNC}
@ -11,10 +11,10 @@ function check
function _check_hostname
{
_notify 'task' 'Checking that hostname/domainname is provided or overridden'
_log 'debug' 'Checking that hostname/domainname is provided or overridden'
_notify 'inf' "Domain has been set to ${DOMAINNAME}"
_notify 'inf' "Hostname has been set to ${HOSTNAME}"
_log 'debug' "Domain has been set to ${DOMAINNAME}"
_log 'debug' "Hostname has been set to ${HOSTNAME}"
# HOSTNAME should be an FQDN (eg: hostname.domain)
if ! grep -q -E '^(\S+[.]\S+)$' <<< "${HOSTNAME}"
@ -22,3 +22,23 @@ function _check_hostname
_shutdown 'Setting hostname/domainname is required'
fi
}
function _check_log_level
{
if [[ ${LOG_LEVEL} == 'trace' ]] \
|| [[ ${LOG_LEVEL} == 'debug' ]] \
|| [[ ${LOG_LEVEL} == 'info' ]] \
|| [[ ${LOG_LEVEL} == 'warn' ]] \
|| [[ ${LOG_LEVEL} == 'error' ]]
then
return 0
else
local DEFAULT_LOG_LEVEL='info'
# shellcheck disable=SC2034
VARS[LOG_LEVEL]="${DEFAULT_LOG_LEVEL}"
LOG_LEVEL="${DEFAULT_LOG_LEVEL}"
_log 'warn' "Log level '${LOG_LEVEL}' is invalid (falling back to default '${DEFAULT_LOG_LEVEL}')"
fi
}

View File

@ -2,7 +2,7 @@
function start_daemons
{
_notify 'tasklog' 'Starting daemons & mail server'
_log 'info' 'Starting daemons & mail server'
for FUNC in "${DAEMONS_START[@]}"
do
${FUNC}
@ -11,25 +11,25 @@ function start_daemons
function _start_daemons_cron
{
_notify 'task' 'Starting cron'
_log 'debug' 'Starting cron'
supervisorctl start cron || dms_panic__fail_init 'cron'
}
function _start_daemons_rsyslog
{
_notify 'task' 'Starting rsyslog'
_log 'debug' 'Starting rsyslog'
supervisorctl start rsyslog || dms_panic__fail_init 'rsyslog'
}
function _start_daemons_saslauthd
{
_notify 'task' 'Starting saslauthd'
_log 'debug' 'Starting saslauthd'
supervisorctl start "saslauthd_${SASLAUTHD_MECHANISMS}" || dms_panic__fail_init 'saslauthd'
}
function _start_daemons_fail2ban
{
_notify 'task' 'Starting Fail2ban'
_log 'debug' 'Starting Fail2ban'
touch /var/log/auth.log
# delete fail2ban.sock that probably was left here after container restart
@ -43,35 +43,35 @@ function _start_daemons_fail2ban
function _start_daemons_opendkim
{
_notify 'task' 'Starting opendkim'
_log 'debug' 'Starting opendkim'
supervisorctl start opendkim || dms_panic__fail_init 'opendkim'
}
function _start_daemons_opendmarc
{
_notify 'task' 'Starting opendmarc'
_log 'debug' 'Starting opendmarc'
supervisorctl start opendmarc || dms_panic__fail_init 'opendmarc'
}
function _start_daemons_postsrsd
{
_notify 'task' 'Starting postsrsd'
_log 'debug' 'Starting postsrsd'
supervisorctl start postsrsd || dms_panic__fail_init 'postsrsd'
}
function _start_daemons_postfix
{
_notify 'task' 'Starting postfix'
_log 'debug' 'Starting postfix'
supervisorctl start postfix || dms_panic__fail_init 'postfix'
}
function _start_daemons_dovecot
{
_notify 'task' 'Starting dovecot services'
_log 'debug' 'Starting dovecot services'
if [[ ${ENABLE_POP3} -eq 1 ]]
then
_notify 'task' 'Starting pop3 services'
_log 'debug' 'Starting pop3 services'
mv /etc/dovecot/protocols.d/pop3d.protocol.disab \
/etc/dovecot/protocols.d/pop3d.protocol
fi
@ -86,7 +86,7 @@ function _start_daemons_dovecot
function _start_daemons_fetchmail
{
_notify 'task' 'Preparing fetchmail config'
_log 'debug' 'Preparing fetchmail config'
/usr/local/bin/setup-fetchmail
if [[ ${FETCHMAIL_PARALLEL} -eq 1 ]]
@ -119,42 +119,42 @@ EOF
for _ in /etc/fetchmailrc.d/fetchmail-*.rc
do
COUNTER=$(( COUNTER + 1 ))
_notify 'task' "Starting fetchmail instance ${COUNTER}"
_log 'debug' "Starting fetchmail instance ${COUNTER}"
supervisorctl start "fetchmail-${COUNTER}" || _panic__fail_init "fetchmail-${COUNTER}"
done
else
_notify 'task' 'Starting fetchmail'
_log 'debug' 'Starting fetchmail'
supervisorctl start fetchmail || dms_panic__fail_init 'fetchmail'
fi
}
function _start_daemons_clamav
{
_notify 'task' 'Starting ClamAV'
_log 'debug' 'Starting ClamAV'
supervisorctl start clamav || dms_panic__fail_init 'ClamAV'
}
function _start_daemons_postgrey
{
_notify 'task' 'Starting postgrey'
_log 'debug' 'Starting postgrey'
rm -f /var/run/postgrey/postgrey.pid
supervisorctl start postgrey || dms_panic__fail_init 'postgrey'
}
function _start_daemons_amavis
{
_notify 'task' 'Starting amavis'
_log 'debug' 'Starting amavis'
supervisorctl start amavis || dms_panic__fail_init 'amavis'
}
function _start_changedetector
{
_notify 'task' 'Starting changedetector'
_log 'debug' 'Starting changedetector'
supervisorctl start changedetector || dms_panic__fail_init 'changedetector'
}
function _start_daemons_update_check
{
_notify 'task' 'Starting update-check'
_log 'debug' 'Starting update-check'
supervisorctl start update-check || dms_panic__fail_init 'update-check'
}

View File

@ -2,28 +2,28 @@
function fix
{
_notify 'tasklog' 'Post-configuration checks'
_log 'info' 'Post-configuration checks'
for FUNC in "${FUNCS_FIX[@]}"
do
${FUNC}
done
_notify 'inf' 'Removing leftover PID files from a stop/start'
_log 'trace' 'Removing leftover PID files from a stop/start'
find /var/run/ -not -name 'supervisord.pid' -name '*.pid' -delete
touch /dev/shm/supervisor.sock
}
function _fix_var_mail_permissions
{
_notify 'task' 'Checking /var/mail permissions'
_log 'debug' 'Checking /var/mail permissions'
# fix permissions, but skip this if 3 levels deep the user id is already set
if find /var/mail -maxdepth 3 -a \( \! -user 5000 -o \! -group 5000 \) | read -r
then
_notify 'inf' 'Fixing /var/mail permissions'
_log 'trace' 'Fixing /var/mail permissions'
chown -R 5000:5000 /var/mail || _shutdown 'Failed to fix /var/mail permissions'
else
_notify 'inf' 'Permissions in /var/mail look OK'
_log 'trace' 'Permissions in /var/mail look OK'
fi
}
@ -33,24 +33,24 @@ function _fix_var_amavis_permissions
[[ ${ONE_DIR} -eq 0 ]] && AMAVIS_STATE_DIR="/var/lib/amavis"
[[ ! -e ${AMAVIS_STATE_DIR} ]] && return 0
_notify 'inf' 'Fixing Amavis permissions'
_log 'trace' 'Fixing Amavis permissions'
chown -hR amavis:amavis "${AMAVIS_STATE_DIR}" || _shutdown 'Failed to fix Amavis permissions'
}
function _fix_cleanup_clamav
{
_notify 'task' 'Cleaning up disabled ClamAV'
_log 'trace' 'Cleaning up disabled ClamAV'
rm /etc/logrotate.d/clamav-* /etc/cron.d/clamav-freshclam 2>/dev/null || {
# show error only on first container start
[[ ! -f /CONTAINER_START ]] && _notify 'err' 'Failed to remove ClamAV configuration'
# show warning only on first container start
[[ ! -f /CONTAINER_START ]] && _log 'warn' 'Failed to remove ClamAV configuration'
}
}
function _fix_cleanup_spamassassin
{
_notify 'task' 'Cleaning up disabled SpamAssassin'
_log 'trace' 'Cleaning up disabled SpamAssassin'
rm /etc/cron.daily/spamassassin 2>/dev/null || {
# show error only on first container start
[[ ! -f /CONTAINER_START ]] && _notify 'err' 'Failed to remove SpamAssassin configuration'
# show warning only on first container start
[[ ! -f /CONTAINER_START ]] && _log 'warn' 'Failed to remove SpamAssassin configuration'
}
}

View File

@ -2,7 +2,7 @@
function start_misc
{
_notify 'inf' 'Starting miscellaneous tasks'
_log 'info' 'Starting miscellaneous tasks'
for FUNC in "${FUNCS_MISC[@]}"
do
${FUNC}
@ -19,7 +19,7 @@ function _misc_save_states
if [[ ${ONE_DIR} -eq 1 ]] && [[ -d ${STATEDIR} ]]
then
_notify 'inf' "Consolidating all state onto ${STATEDIR}"
_log 'debug' "Consolidating all state onto ${STATEDIR}"
FILES=(
spool/postfix
@ -39,22 +39,22 @@ function _misc_save_states
if [[ -d ${DEST} ]]
then
_notify 'inf' "Destination ${DEST} exists, linking ${FILE} to it"
_log 'trace' "Destination ${DEST} exists, linking ${FILE} to it"
rm -rf "${FILE}"
ln -s "${DEST}" "${FILE}"
elif [[ -d ${FILE} ]]
then
_notify 'inf' "Moving contents of ${FILE} to ${DEST}"
_log 'trace' "Moving contents of ${FILE} to ${DEST}"
mv "${FILE}" "${DEST}"
ln -s "${DEST}" "${FILE}"
else
_notify 'inf' "Linking ${FILE} to ${DEST}"
_log 'trace' "Linking ${FILE} to ${DEST}"
mkdir -p "${DEST}"
ln -s "${DEST}" "${FILE}"
fi
done
_notify 'inf' 'Fixing /var/mail-state/* permissions'
_log 'trace' 'Fixing /var/mail-state/* permissions'
chown -R clamav /var/mail-state/lib-clamav
chown -R postfix /var/mail-state/lib-postfix
chown -R postgrey /var/mail-state/lib-postgrey

View File

@ -2,7 +2,7 @@
function setup
{
_notify 'tasklog' 'Configuring mail server'
_log 'info' 'Configuring mail server'
for FUNC in "${FUNCS_SETUP[@]}"
do
${FUNC}
@ -28,7 +28,7 @@ function _setup_supervisor
;;
( * )
_notify 'err' \
_log 'warn' \
"SUPERVISOR_LOGLEVEL '${SUPERVISOR_LOGLEVEL}' unknown. Using default 'warn'"
;;
@ -40,7 +40,7 @@ function _setup_supervisor
function _setup_default_vars
{
_notify 'task' 'Setting up default variables'
_log 'debug' 'Setting up default variables'
: >/root/.bashrc # make DMS variables available in login shells and their subprocesses
: >/etc/dms-settings # this file can be sourced by other scripts
@ -61,7 +61,7 @@ function _setup_default_vars
# Set the expected values and create missing folders/files just in case.
function _setup_file_permissions
{
_notify 'task' 'Setting file/folder permissions'
_log 'debug' 'Setting file/folder permissions'
mkdir -p /var/log/supervisor
@ -79,23 +79,23 @@ function _setup_file_permissions
function _setup_chksum_file
{
_notify 'task' 'Setting up configuration checksum file'
_log 'debug' 'Setting up configuration checksum file'
if [[ -d /tmp/docker-mailserver ]]
then
_notify 'inf' "Creating ${CHKSUM_FILE}"
_log 'trace' "Creating ${CHKSUM_FILE}"
_monitored_files_checksums >"${CHKSUM_FILE}"
else
# We could just skip the file, but perhaps config can be added later?
# If so it must be processed by the check for changes script
_notify 'inf' "Creating empty ${CHKSUM_FILE} (no config)"
_log 'trace' "Creating empty ${CHKSUM_FILE} (no config)"
touch "${CHKSUM_FILE}"
fi
}
function _setup_mailname
{
_notify 'task' 'Setting up mailname / creating /etc/mailname'
_log 'debug' 'Setting up mailname / creating /etc/mailname'
echo "${DOMAINNAME}" >/etc/mailname
}
@ -103,21 +103,21 @@ function _setup_amavis
{
if [[ ${ENABLE_AMAVIS} -eq 1 ]]
then
_notify 'task' 'Setting up Amavis'
_log 'debug' 'Setting up Amavis'
sed -i \
"s|^#\$myhostname = \"mail.example.com\";|\$myhostname = \"${HOSTNAME}\";|" \
/etc/amavis/conf.d/05-node_id
else
_notify 'task' 'Remove Amavis from postfix configuration'
_log 'debug' 'Remove Amavis from postfix configuration'
sed -i 's|content_filter =.*|content_filter =|' /etc/postfix/main.cf
[[ ${ENABLE_CLAMAV} -eq 1 ]] && _notify 'warn' 'ClamAV will not work when Amavis is disabled. Remove ENABLE_AMAVIS=0 from your configuration to fix it.'
[[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && _notify 'warn' 'Spamassassin will not work when Amavis is disabled. Remove ENABLE_AMAVIS=0 from your configuration to fix it.'
[[ ${ENABLE_CLAMAV} -eq 1 ]] && _log 'warn' 'ClamAV will not work when Amavis is disabled. Remove ENABLE_AMAVIS=0 from your configuration to fix it.'
[[ ${ENABLE_SPAMASSASSIN} -eq 1 ]] && _log 'warn' 'Spamassassin will not work when Amavis is disabled. Remove ENABLE_AMAVIS=0 from your configuration to fix it.'
fi
}
function _setup_dmarc_hostname
{
_notify 'task' 'Setting up dmarc'
_log 'debug' 'Setting up dmarc'
sed -i -e \
"s|^AuthservID.*$|AuthservID ${HOSTNAME}|g" \
-e "s|^TrustedAuthservIDs.*$|TrustedAuthservIDs ${HOSTNAME}|g" \
@ -126,14 +126,14 @@ function _setup_dmarc_hostname
function _setup_postfix_hostname
{
_notify 'task' 'Applying hostname and domainname to Postfix'
_log 'debug' 'Applying hostname and domainname to Postfix'
postconf -e "myhostname = ${HOSTNAME}"
postconf -e "mydomain = ${DOMAINNAME}"
}
function _setup_dovecot_hostname
{
_notify 'task' 'Applying hostname to Dovecot'
_log 'debug' 'Applying hostname to Dovecot'
sed -i \
"s|^#hostname =.*$|hostname = '${HOSTNAME}'|g" \
/etc/dovecot/conf.d/15-lda.conf
@ -141,7 +141,7 @@ function _setup_dovecot_hostname
function _setup_dovecot
{
_notify 'task' 'Setting up Dovecot'
_log 'debug' 'Setting up Dovecot'
cp -a /usr/share/dovecot/protocols.d /etc/dovecot/
# disable pop3 (it will be eventually enabled later in the script, if requested)
@ -160,19 +160,20 @@ function _setup_dovecot
# set mail_location according to mailbox format
case "${DOVECOT_MAILBOX_FORMAT}" in
( "sdbox" | "mdbox" )
_notify 'inf' "Dovecot ${DOVECOT_MAILBOX_FORMAT} format configured"
( 'sdbox' | 'mdbox' )
_log 'trace' "Dovecot ${DOVECOT_MAILBOX_FORMAT} format configured"
sed -i -e \
"s|^mail_location = .*$|mail_location = ${DOVECOT_MAILBOX_FORMAT}:\/var\/mail\/%d\/%n|g" \
/etc/dovecot/conf.d/10-mail.conf
_notify 'inf' 'Enabling cron job for dbox purge'
_log 'trace' 'Enabling cron job for dbox purge'
mv /etc/cron.d/dovecot-purge.disabled /etc/cron.d/dovecot-purge
chmod 644 /etc/cron.d/dovecot-purge
;;
( * )
_notify 'inf' "Dovecot maildir format configured (default)"
_log 'trace' "Dovecot maildir format configured (default)"
sed -i -e 's|^mail_location = .*$|mail_location = maildir:\/var\/mail\/%d\/%n|g' /etc/dovecot/conf.d/10-mail.conf
;;
@ -182,7 +183,7 @@ function _setup_dovecot
# to the configuration file Dovecot will actually find
if [[ ${ENABLE_MANAGESIEVE} -eq 1 ]]
then
_notify 'inf' 'Sieve management enabled'
_log 'trace' 'Sieve management enabled'
mv /etc/dovecot/protocols.d/managesieved.protocol.disab /etc/dovecot/protocols.d/managesieved.protocol
fi
@ -215,7 +216,7 @@ function _setup_dovecot
# sieve will move spams to .Junk folder when SPAMASSASSIN_SPAM_TO_INBOX=1 and MOVE_SPAM_TO_JUNK=1
if [[ ${SPAMASSASSIN_SPAM_TO_INBOX} -eq 1 ]] && [[ ${MOVE_SPAM_TO_JUNK} -eq 1 ]]
then
_notify 'inf' "Spam messages will be moved to the Junk folder."
_log 'debug' "Spam messages will be moved to the Junk folder."
cp /etc/dovecot/sieve/before/60-spam.sieve /usr/lib/dovecot/sieve-global/before/
sievec /usr/lib/dovecot/sieve-global/before/60-spam.sieve
else
@ -229,7 +230,7 @@ function _setup_dovecot
function _setup_dovecot_quota
{
_notify 'task' 'Setting up Dovecot quota'
_log 'debug' 'Setting up Dovecot quota'
# Dovecot quota is disabled when using LDAP or SMTP_ONLY or when explicitly disabled.
if [[ ${ENABLE_LDAP} -eq 1 ]] || [[ ${SMTP_ONLY} -eq 1 ]] || [[ ${ENABLE_QUOTAS} -eq 0 ]]
@ -273,7 +274,7 @@ function _setup_dovecot_quota
if [[ ! -f /tmp/docker-mailserver/dovecot-quotas.cf ]]
then
_notify 'inf' "'/tmp/docker-mailserver/dovecot-quotas.cf' is not provided. Using default quotas."
_log 'trace' "'/tmp/docker-mailserver/dovecot-quotas.cf' is not provided. Using default quotas."
: >/tmp/docker-mailserver/dovecot-quotas.cf
fi
@ -286,13 +287,13 @@ function _setup_dovecot_quota
function _setup_dovecot_local_user
{
_notify 'task' 'Setting up Dovecot Local User'
_log 'debug' 'Setting up Dovecot Local User'
_create_accounts
if [[ ! -f /tmp/docker-mailserver/postfix-accounts.cf ]]
then
_notify 'inf' "'/tmp/docker-mailserver/postfix-accounts.cf' is not provided. No mail account created."
_log 'trace' "'/tmp/docker-mailserver/postfix-accounts.cf' is not provided. No mail account created."
fi
if ! grep '@' /tmp/docker-mailserver/postfix-accounts.cf 2>/dev/null | grep -q '|'
@ -306,8 +307,8 @@ function _setup_dovecot_local_user
function _setup_ldap
{
_notify 'task' 'Setting up LDAP'
_notify 'inf' 'Checking for custom configs'
_log 'debug' 'Setting up LDAP'
_log 'trace' 'Checking for custom configs'
for i in 'users' 'groups' 'aliases' 'domains'
do
@ -318,7 +319,7 @@ function _setup_ldap
fi
done
_notify 'inf' 'Starting to override configs'
_log 'trace' 'Starting to override configs'
local FILES=(
/etc/postfix/ldap-users.cf
@ -339,7 +340,7 @@ function _setup_ldap
configomat.sh "LDAP_" "${FILE}"
done
_notify 'inf' "Configuring dovecot LDAP"
_log 'trace' "Configuring dovecot LDAP"
declare -A DOVECOT_LDAP_MAPPING
@ -368,32 +369,32 @@ function _setup_ldap
# add domainname to vhost
echo "${DOMAINNAME}" >>/tmp/vhost.tmp
_notify 'inf' 'Enabling dovecot LDAP authentification'
_log 'trace' 'Enabling dovecot LDAP authentification'
sed -i -e '/\!include auth-ldap\.conf\.ext/s/^#//' /etc/dovecot/conf.d/10-auth.conf
sed -i -e '/\!include auth-passwdfile\.inc/s/^/#/' /etc/dovecot/conf.d/10-auth.conf
_notify 'inf' "Configuring LDAP"
_log 'trace' "Configuring LDAP"
if [[ -f /etc/postfix/ldap-users.cf ]]
then
postconf -e "virtual_mailbox_maps = ldap:/etc/postfix/ldap-users.cf"
else
_notify 'warn' "'/etc/postfix/ldap-users.cf' not found"
_log 'warn' "'/etc/postfix/ldap-users.cf' not found"
fi
if [[ -f /etc/postfix/ldap-domains.cf ]]
then
postconf -e "virtual_mailbox_domains = /etc/postfix/vhost, ldap:/etc/postfix/ldap-domains.cf"
else
_notify 'warn' "'/etc/postfix/ldap-domains.cf' not found"
_log 'warn' "'/etc/postfix/ldap-domains.cf' not found"
fi
if [[ -f /etc/postfix/ldap-aliases.cf ]] && [[ -f /etc/postfix/ldap-groups.cf ]]
then
postconf -e "virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf, ldap:/etc/postfix/ldap-groups.cf"
else
_notify 'warn' "'/etc/postfix/ldap-aliases.cf' and / or '/etc/postfix/ldap-groups.cf' not found"
_log 'warn' "'/etc/postfix/ldap-aliases.cf' and / or '/etc/postfix/ldap-groups.cf' not found"
fi
# shellcheck disable=SC2016
@ -404,7 +405,7 @@ function _setup_ldap
function _setup_postgrey
{
_notify 'inf' "Configuring postgrey"
_log 'debug' "Configuring postgrey"
sed -i -E \
's|, reject_rbl_client zen.spamhaus.org$|, reject_rbl_client zen.spamhaus.org, check_policy_service inet:127.0.0.1:10023|' \
@ -434,7 +435,7 @@ function _setup_postgrey
function _setup_postfix_postscreen
{
_notify 'inf' "Configuring postscreen"
_log 'debug' "Configuring postscreen"
sed -i \
-e "s|postscreen_dnsbl_action = enforce|postscreen_dnsbl_action = ${POSTSCREEN_ACTION}|" \
-e "s|postscreen_greet_action = enforce|postscreen_greet_action = ${POSTSCREEN_ACTION}|" \
@ -443,31 +444,31 @@ function _setup_postfix_postscreen
function _setup_postfix_sizelimits
{
_notify 'inf' "Configuring postfix message size limit to ${POSTFIX_MESSAGE_SIZE_LIMIT}"
_log 'trace' "Configuring postfix message size limit to ${POSTFIX_MESSAGE_SIZE_LIMIT}"
postconf -e "message_size_limit = ${POSTFIX_MESSAGE_SIZE_LIMIT}"
_notify 'inf' "Configuring postfix mailbox size limit to ${POSTFIX_MAILBOX_SIZE_LIMIT}"
_log 'trace' "Configuring postfix mailbox size limit to ${POSTFIX_MAILBOX_SIZE_LIMIT}"
postconf -e "mailbox_size_limit = ${POSTFIX_MAILBOX_SIZE_LIMIT}"
_notify 'inf' "Configuring postfix virtual mailbox size limit to ${POSTFIX_MAILBOX_SIZE_LIMIT}"
_log 'trace' "Configuring postfix virtual mailbox size limit to ${POSTFIX_MAILBOX_SIZE_LIMIT}"
postconf -e "virtual_mailbox_limit = ${POSTFIX_MAILBOX_SIZE_LIMIT}"
}
function _setup_clamav_sizelimit
{
_notify 'inf' "Configuring ClamAV message scan size limit to ${CLAMAV_MESSAGE_SIZE_LIMIT}"
_log 'trace' "Configuring ClamAV message scan size limit to ${CLAMAV_MESSAGE_SIZE_LIMIT}"
sedfile -i "s/^MaxFileSize.*/MaxFileSize ${CLAMAV_MESSAGE_SIZE_LIMIT}/" /etc/clamav/clamd.conf
}
function _setup_postfix_smtputf8
{
_notify 'inf' "Configuring postfix smtputf8 support (disable)"
_log 'trace' "Configuring postfix smtputf8 support (disable)"
postconf -e "smtputf8_enable = no"
}
function _setup_spoof_protection
{
_notify 'inf' "Configuring Spoof Protection"
_log 'trace' "Configuring Spoof Protection"
sed -i \
's|smtpd_sender_restrictions =|smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch,|' \
/etc/postfix/main.cf
@ -491,7 +492,7 @@ function _setup_spoof_protection
function _setup_postfix_access_control
{
_notify 'inf' 'Configuring user access'
_log 'trace' 'Configuring user access'
if [[ -f /tmp/docker-mailserver/postfix-send-access.cf ]]
then
@ -527,7 +528,7 @@ EOF
function _setup_saslauthd
{
_notify 'task' "Setting up SASLAUTHD"
_log 'debug' "Setting up SASLAUTHD"
# checking env vars and setting defaults
[[ -z ${SASLAUTHD_MECHANISMS:-} ]] && SASLAUTHD_MECHANISMS=pam
@ -577,7 +578,7 @@ function _setup_saslauthd
if [[ ! -f /etc/saslauthd.conf ]]
then
_notify 'inf' 'Creating /etc/saslauthd.conf'
_log 'trace' 'Creating /etc/saslauthd.conf'
cat > /etc/saslauthd.conf << EOF
ldap_servers: ${SASLAUTHD_LDAP_SERVER}
@ -617,13 +618,13 @@ EOF
function _setup_postfix_aliases
{
_notify 'task' 'Setting up Postfix Aliases'
_log 'debug' 'Setting up Postfix aliases'
_create_aliases
}
function _setup_SRS
{
_notify 'task' 'Setting up SRS'
_log 'debug' 'Setting up SRS'
postconf -e "sender_canonical_maps = tcp:localhost:10001"
postconf -e "sender_canonical_classes = ${SRS_SENDER_CLASSES}"
@ -633,7 +634,7 @@ function _setup_SRS
function _setup_dkim
{
_notify 'task' 'Setting up DKIM'
_log 'debug' 'Setting up DKIM'
mkdir -p /etc/opendkim && touch /etc/opendkim/SigningTable
@ -642,13 +643,13 @@ function _setup_dkim
then
cp -a /tmp/docker-mailserver/opendkim/* /etc/opendkim/
_notify 'inf' "DKIM keys added for: $(ls -C /etc/opendkim/keys/)"
_notify 'inf' "Changing permissions on /etc/opendkim"
_log 'trace' "DKIM keys added for: $(ls -C /etc/opendkim/keys/)"
_log 'trace' "Changing permissions on /etc/opendkim"
chown -R opendkim:opendkim /etc/opendkim/
chmod -R 0700 /etc/opendkim/keys/
else
_notify 'warn' 'No DKIM key provided. Check the documentation on how to get your keys.'
_log 'warn' 'No DKIM key provided. Check the documentation on how to get your keys.'
[[ ! -f "/etc/opendkim/KeyTable" ]] && touch "/etc/opendkim/KeyTable"
fi
@ -657,19 +658,19 @@ function _setup_dkim
then
echo "Nameservers $(grep '^nameserver' /etc/resolv.conf | awk -F " " '{print $2}' | paste -sd ',' -)" >> /etc/opendkim.conf
_notify 'inf' "Nameservers added to /etc/opendkim.conf"
_log 'trace' "Nameservers added to /etc/opendkim.conf"
fi
}
function _setup_postfix_vhost
{
_notify 'task' "Setting up Postfix vhost"
_log 'debug' "Setting up Postfix vhost"
_create_postfix_vhost
}
function _setup_postfix_inet_protocols
{
_notify 'task' 'Setting up POSTFIX_INET_PROTOCOLS option'
_log 'trace' 'Setting up POSTFIX_INET_PROTOCOLS option'
postconf -e "inet_protocols = ${POSTFIX_INET_PROTOCOLS}"
}
@ -677,7 +678,7 @@ function _setup_dovecot_inet_protocols
{
local PROTOCOL
_notify 'task' 'Setting up DOVECOT_INET_PROTOCOLS option'
_log 'trace' 'Setting up DOVECOT_INET_PROTOCOLS option'
# https://dovecot.org/doc/dovecot-example.conf
if [[ ${DOVECOT_INET_PROTOCOLS} == "ipv4" ]]
@ -696,7 +697,7 @@ function _setup_dovecot_inet_protocols
function _setup_docker_permit
{
_notify 'task' 'Setting up PERMIT_DOCKER Option'
_log 'debug' 'Setting up PERMIT_DOCKER Option'
local CONTAINER_IP CONTAINER_NETWORK
@ -709,7 +710,7 @@ function _setup_docker_permit
if [[ -z ${CONTAINER_IP} ]]
then
_notify 'err' 'Detecting the container IP address failed.'
_log 'error' 'Detecting the container IP address failed.'
dms_panic__misconfigured 'NETWORK_INTERFACE' 'Network Setup [docker_permit]'
fi
@ -720,7 +721,7 @@ function _setup_docker_permit
case "${PERMIT_DOCKER}" in
( 'none' )
_notify 'inf' "Clearing Postfix's 'mynetworks'"
_log 'trace' "Clearing Postfix's 'mynetworks'"
postconf -e "mynetworks ="
;;
@ -728,7 +729,7 @@ function _setup_docker_permit
for NETWORK in "${CONTAINER_NETWORKS[@]}"
do
NETWORK=$(_sanitize_ipv4_to_subnet_cidr "${NETWORK}")
_notify 'inf' "Adding docker network ${NETWORK} to Postfix's 'mynetworks'"
_log 'trace' "Adding docker network ${NETWORK} to Postfix's 'mynetworks'"
postconf -e "$(postconf | grep '^mynetworks =') ${NETWORK}"
echo "${NETWORK}" >> /etc/opendmarc/ignore.hosts
echo "${NETWORK}" >> /etc/opendkim/TrustedHosts
@ -736,29 +737,29 @@ function _setup_docker_permit
;;
( 'container' )
_notify 'inf' "Adding container IP address to Postfix's 'mynetworks'"
_log 'trace' "Adding container IP address to Postfix's 'mynetworks'"
postconf -e "$(postconf | grep '^mynetworks =') ${CONTAINER_IP}/32"
echo "${CONTAINER_IP}/32" >> /etc/opendmarc/ignore.hosts
echo "${CONTAINER_IP}/32" >> /etc/opendkim/TrustedHosts
;;
( 'host' )
_notify 'inf' "Adding ${CONTAINER_NETWORK}/16 to Postfix's 'mynetworks'"
_log 'trace' "Adding ${CONTAINER_NETWORK}/16 to Postfix's 'mynetworks'"
postconf -e "$(postconf | grep '^mynetworks =') ${CONTAINER_NETWORK}/16"
echo "${CONTAINER_NETWORK}/16" >> /etc/opendmarc/ignore.hosts
echo "${CONTAINER_NETWORK}/16" >> /etc/opendkim/TrustedHosts
;;
( 'network' )
_notify 'inf' "Adding docker network to Postfix's 'mynetworks'"
_log 'trace' "Adding docker network to Postfix's 'mynetworks'"
postconf -e "$(postconf | grep '^mynetworks =') 172.16.0.0/12"
echo 172.16.0.0/12 >> /etc/opendmarc/ignore.hosts
echo 172.16.0.0/12 >> /etc/opendkim/TrustedHosts
;;
( * )
_notify 'warn' "Invalid value for PERMIT_DOCKER: ${PERMIT_DOCKER}"
_notify 'inf' "Clearing Postfix's 'mynetworks'"
_log 'warn' "Invalid value for PERMIT_DOCKER: ${PERMIT_DOCKER}"
_log 'trace' "Clearing Postfix's 'mynetworks'"
postconf -e "mynetworks ="
;;
@ -768,7 +769,7 @@ function _setup_docker_permit
# Requires ENABLE_POSTFIX_VIRTUAL_TRANSPORT=1
function _setup_postfix_virtual_transport
{
_notify 'task' 'Setting up Postfix virtual transport'
_log 'trace' 'Setting up Postfix virtual transport'
if [[ -z ${POSTFIX_DAGENT} ]]
then
@ -781,7 +782,7 @@ function _setup_postfix_virtual_transport
function _setup_postfix_override_configuration
{
_notify 'task' 'Setting up Postfix Override configuration'
_log 'trace' 'Setting up Postfix Override configuration'
if [[ -f /tmp/docker-mailserver/postfix-main.cf ]]
then
@ -794,9 +795,9 @@ function _setup_postfix_override_configuration
postconf -e "${LINE}"
fi
done < /tmp/docker-mailserver/postfix-main.cf
_notify 'inf' "Loaded '/tmp/docker-mailserver/postfix-main.cf'"
_log 'trace' "Loaded '/tmp/docker-mailserver/postfix-main.cf'"
else
_notify 'inf' "No extra postfix settings loaded because optional '/tmp/docker-mailserver/postfix-main.cf' not provided."
_log 'trace' "No extra postfix settings loaded because optional '/tmp/docker-mailserver/postfix-main.cf' not provided."
fi
if [[ -f /tmp/docker-mailserver/postfix-master.cf ]]
@ -808,27 +809,27 @@ function _setup_postfix_override_configuration
postconf -P "${LINE}"
fi
done < /tmp/docker-mailserver/postfix-master.cf
_notify 'inf' "Loaded '/tmp/docker-mailserver/postfix-master.cf'"
_log 'trace' "Loaded '/tmp/docker-mailserver/postfix-master.cf'"
else
_notify 'inf' "No extra postfix settings loaded because optional '/tmp/docker-mailserver/postfix-master.cf' not provided."
_log 'trace' "No extra postfix settings loaded because optional '/tmp/docker-mailserver/postfix-master.cf' not provided."
fi
_notify 'inf' "set the compatibility level to 2"
_log 'trace' "set the compatibility level to 2"
postconf compatibility_level=2
}
function _setup_postfix_sasl_password
{
_notify 'task' 'Setting up Postfix SASL Password'
_log 'debug' 'Setting up Postfix SASL Password'
# support general SASL password
_sasl_passwd_create
if [[ -f /etc/postfix/sasl_passwd ]]
then
_notify 'inf' "Loaded SASL_PASSWD"
_log 'trace' "Loaded SASL_PASSWD"
else
_notify 'inf' "Warning: 'SASL_PASSWD' was not provided. /etc/postfix/sasl_passwd not created."
_log 'debug' "Warning: 'SASL_PASSWD' was not provided. /etc/postfix/sasl_passwd not created."
fi
}
@ -853,22 +854,22 @@ function _setup_dhparam
local DH_DEST=$2
local DH_CUSTOM=/tmp/docker-mailserver/dhparams.pem
_notify 'task' "Setting up ${DH_SERVICE} dhparam"
_log 'debug' "Setting up ${DH_SERVICE} dhparam"
if [[ -f ${DH_CUSTOM} ]]
then # use custom supplied dh params (assumes they're probably insecure)
_notify 'inf' "${DH_SERVICE} will use custom provided DH paramters."
_notify 'warn' "Using self-generated dhparams is considered insecure. Unless you know what you are doing, please remove ${DH_CUSTOM}."
_log 'trace' "${DH_SERVICE} will use custom provided DH paramters."
_log 'warn' "Using self-generated dhparams is considered insecure. Unless you know what you are doing, please remove ${DH_CUSTOM}."
cp -f "${DH_CUSTOM}" "${DH_DEST}"
else # use official standardized dh params (provided via Dockerfile)
_notify 'inf' "${DH_SERVICE} will use official standardized DH parameters (ffdhe4096)."
_log 'trace' "${DH_SERVICE} will use official standardized DH parameters (ffdhe4096)."
fi
}
function _setup_security_stack
{
_notify 'task' "Setting up Security Stack"
_log 'debug' "Setting up Security Stack"
# recreate auto-generated file
local DMS_AMAVIS_FILE=/etc/amavis/conf.d/61-dms_auto_generated
@ -879,11 +880,11 @@ function _setup_security_stack
# SpamAssassin
if [[ ${ENABLE_SPAMASSASSIN} -eq 0 ]]
then
_notify 'warn' "Spamassassin is disabled. You can enable it with 'ENABLE_SPAMASSASSIN=1'"
_log 'warn' "Spamassassin is disabled. You can enable it with 'ENABLE_SPAMASSASSIN=1'"
echo "@bypass_spam_checks_maps = (1);" >>"${DMS_AMAVIS_FILE}"
elif [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]]
then
_notify 'inf' "Enabling and configuring spamassassin"
_log 'debug' "Enabling and configuring spamassassin"
# shellcheck disable=SC2016
sed -i -r 's|^\$sa_tag_level_deflt (.*);|\$sa_tag_level_deflt = '"${SA_TAG}"';|g' /etc/amavis/conf.d/20-debian_defaults
@ -925,12 +926,12 @@ function _setup_security_stack
if [[ ${SPAMASSASSIN_SPAM_TO_INBOX} -eq 1 ]]
then
_notify 'inf' 'Configuring Spamassassin/Amavis to send SPAM to inbox'
_log 'trace' 'Configuring Spamassassin/Amavis to send SPAM to inbox'
sed -i "s|\$final_spam_destiny.*=.*$|\$final_spam_destiny = D_PASS;|g" /etc/amavis/conf.d/49-docker-mailserver
sed -i "s|\$final_bad_header_destiny.*=.*$|\$final_bad_header_destiny = D_PASS;|g" /etc/amavis/conf.d/49-docker-mailserver
else
_notify 'inf' 'Configuring Spamassassin/Amavis to bounce SPAM'
_log 'trace' 'Configuring Spamassassin/Amavis to bounce SPAM'
sed -i "s|\$final_spam_destiny.*=.*$|\$final_spam_destiny = D_BOUNCE;|g" /etc/amavis/conf.d/49-docker-mailserver
sed -i "s|\$final_bad_header_destiny.*=.*$|\$final_bad_header_destiny = D_BOUNCE;|g" /etc/amavis/conf.d/49-docker-mailserver
@ -938,7 +939,7 @@ function _setup_security_stack
if [[ ${ENABLE_SPAMASSASSIN_KAM} -eq 1 ]]
then
_notify 'inf' 'Configuring Spamassassin KAM'
_log 'trace' 'Configuring Spamassassin KAM'
local SPAMASSASSIN_KAM_CRON_FILE=/etc/cron.daily/spamassassin_kam
sa-update --import /etc/spamassassin/kam/kam.sa-channels.mcgrail.com.key
@ -967,11 +968,11 @@ EOM
# ClamAV
if [[ ${ENABLE_CLAMAV} -eq 0 ]]
then
_notify 'warn' "ClamAV is disabled. You can enable it with 'ENABLE_CLAMAV=1'"
_log 'warn' "ClamAV is disabled. You can enable it with 'ENABLE_CLAMAV=1'"
echo '@bypass_virus_checks_maps = (1);' >>"${DMS_AMAVIS_FILE}"
elif [[ ${ENABLE_CLAMAV} -eq 1 ]]
then
_notify 'inf' 'Enabling ClamAV'
_log 'debug' 'Enabling ClamAV'
fi
echo '1; # ensure a defined return' >>"${DMS_AMAVIS_FILE}"
@ -980,7 +981,7 @@ EOM
# Fail2ban
if [[ ${ENABLE_FAIL2BAN} -eq 1 ]]
then
_notify 'inf' 'Fail2ban enabled'
_log 'debug' 'Enabling Fail2Ban'
if [[ -e /tmp/docker-mailserver/fail2ban-fail2ban.cf ]]
then
@ -1004,7 +1005,7 @@ EOM
# Amavis
if [[ ${ENABLE_AMAVIS} -eq 1 ]]
then
_notify 'inf' 'Amavis enabled'
_log 'debug' 'Enabling Amavis'
if [[ -f /tmp/docker-mailserver/amavis.cf ]]
then
cp /tmp/docker-mailserver/amavis.cf /etc/amavis/conf.d/50-user
@ -1018,28 +1019,28 @@ EOM
function _setup_logrotate
{
_notify 'inf' 'Setting up logrotate'
_log 'debug' 'Setting up logrotate'
LOGROTATE='/var/log/mail/mail.log\n{\n compress\n copytruncate\n delaycompress\n'
case "${LOGROTATE_INTERVAL}" in
( 'daily' )
_notify 'inf' 'Setting postfix logrotate interval to daily'
_log 'trace' 'Setting postfix logrotate interval to daily'
LOGROTATE="${LOGROTATE} rotate 4\n daily\n"
;;
( 'weekly' )
_notify 'inf' 'Setting postfix logrotate interval to weekly'
_log 'trace' 'Setting postfix logrotate interval to weekly'
LOGROTATE="${LOGROTATE} rotate 4\n weekly\n"
;;
( 'monthly' )
_notify 'inf' 'Setting postfix logrotate interval to monthly'
_log 'trace' 'Setting postfix logrotate interval to monthly'
LOGROTATE="${LOGROTATE} rotate 4\n monthly\n"
;;
( * )
_notify 'warn' 'LOGROTATE_INTERVAL not found in _setup_logrotate'
_log 'warn' 'LOGROTATE_INTERVAL not found in _setup_logrotate'
;;
esac
@ -1049,11 +1050,11 @@ function _setup_logrotate
function _setup_mail_summary
{
_notify 'inf' "Enable postfix summary with recipient ${PFLOGSUMM_RECIPIENT}"
_log 'debug' "Enable postfix summary with recipient ${PFLOGSUMM_RECIPIENT}"
case "${PFLOGSUMM_TRIGGER}" in
( 'daily_cron' )
_notify 'inf' 'Creating daily cron job for pflogsumm report'
_log 'trace' 'Creating daily cron job for pflogsumm report'
cat >/etc/cron.daily/postfix-summary << EOM
#! /bin/bash
@ -1065,18 +1066,18 @@ EOM
;;
( 'logrotate' )
_notify 'inf' 'Add postrotate action for pflogsumm report'
_log 'trace' 'Add postrotate action for pflogsumm report'
sed -i \
"s|}| postrotate\n /usr/local/bin/postfix-summary ${HOSTNAME} ${PFLOGSUMM_RECIPIENT} ${PFLOGSUMM_SENDER}\n endscript\n}\n|" \
/etc/logrotate.d/maillog
;;
( 'none' )
_notify 'inf' 'Postfix log summary reports disabled.'
_log 'trace' 'Postfix log summary reports disabled.'
;;
( * )
_notify 'err' 'PFLOGSUMM_TRIGGER not found in _setup_mail_summery'
_log 'warn' 'PFLOGSUMM_TRIGGER not found in _setup_mail_summery'
;;
esac
@ -1089,8 +1090,8 @@ function _setup_logwatch
case "${LOGWATCH_INTERVAL}" in
( 'daily' | 'weekly' )
_notify 'inf' "Enable logwatch reports with recipient ${LOGWATCH_RECIPIENT}"
_notify 'inf' "Creating ${LOGWATCH_INTERVAL} cron job for logwatch reports"
_log 'trace' "Enable logwatch reports with recipient ${LOGWATCH_RECIPIENT}"
_log 'trace' "Creating ${LOGWATCH_INTERVAL} cron job for logwatch reports"
local LOGWATCH_FILE INTERVAL
@ -1111,11 +1112,11 @@ EOM
;;
( 'none' )
_notify 'inf' 'Logwatch reports disabled.'
_log 'trace' 'Logwatch reports disabled.'
;;
( * )
_notify 'warn' 'LOGWATCH_INTERVAL not found in _setup_logwatch'
_log 'warn' 'LOGWATCH_INTERVAL not found in _setup_logwatch'
;;
esac
@ -1127,16 +1128,16 @@ function _setup_user_patches
if [[ -f ${USER_PATCHES} ]]
then
_notify 'tasklog' 'Applying user patches'
_log 'info' 'Applying user patches'
/bin/bash "${USER_PATCHES}"
else
_notify 'inf' "No optional '/tmp/docker-mailserver/user-patches.sh' provided. Skipping."
_log 'trace' "No optional '/tmp/docker-mailserver/user-patches.sh' provided. Skipping."
fi
}
function _setup_fail2ban
{
_notify 'task' 'Setting up fail2ban'
_log 'debug' 'Setting up Fail2Ban'
if [[ ${FAIL2BAN_BLOCKTYPE} != "reject" ]]
then
echo -e "[Init]\nblocktype = DROP" > /etc/fail2ban/action.d/iptables-common.local
@ -1145,12 +1146,13 @@ function _setup_fail2ban
function _setup_dnsbl_disable
{
_notify 'task' 'Disabling postfix DNS block list (zen.spamhaus.org)'
_log 'debug' 'Disabling postfix DNS block list (zen.spamhaus.org)'
sedfile -i \
'/^smtpd_recipient_restrictions = / s/, reject_rbl_client zen.spamhaus.org//' \
/etc/postfix/main.cf
_notify 'task' 'Disabling postscreen DNS block lists'
_log 'debug' 'Disabling postscreen DNS block lists'
postconf -e "postscreen_dnsbl_action = ignore"
postconf -e "postscreen_dnsbl_sites = "
}

View File

@ -12,6 +12,7 @@ function setup_file() {
-v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \
-v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \
-e DMS_DEBUG=1 \
-e LOG_LEVEL=trace \
-h mail.my-domain.com -t "${NAME}"
wait_for_finished_setup_in_container mail_changedetector_one
@ -19,6 +20,7 @@ function setup_file() {
-v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \
-v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \
-e DMS_DEBUG=1 \
-e LOG_LEVEL=trace \
-h mail.my-domain.com -t "${NAME}"
wait_for_finished_setup_in_container mail_changedetector_two
}
@ -55,15 +57,15 @@ function teardown_file() {
run docker exec mail_changedetector_two /bin/bash -c "supervisorctl start changedetector"
sleep 15
run docker exec mail_changedetector_one /bin/bash -c "supervisorctl tail changedetector"
assert_output --partial "check-for-changes.sh.lock exists"
assert_output --partial "another execution of 'check-for-changes.sh' is happening"
run docker exec mail_changedetector_two /bin/bash -c "supervisorctl tail changedetector"
assert_output --partial "check-for-changes.sh.lock exists"
assert_output --partial "another execution of 'check-for-changes.sh' is happening"
# Ensure starting a new check-for-changes.sh instance (restarting here) doesn't delete the lock
docker exec mail_changedetector_two /bin/bash -c "rm -f /var/log/supervisor/changedetector.log"
run docker exec mail_changedetector_two /bin/bash -c "supervisorctl restart changedetector"
sleep 5
run docker exec mail_changedetector_two /bin/bash -c "supervisorctl tail changedetector"
refute_output --partial "check-for-changes.sh.lock exists"
refute_output --partial "another execution of 'check-for-changes.sh' is happening"
refute_output --partial "Removed lock"
}
@ -73,8 +75,8 @@ function teardown_file() {
echo "" >> "$(private_config_path mail_changedetector_one)/postfix-accounts.cf"
sleep 15
run docker exec mail_changedetector_one /bin/bash -c "supervisorctl tail changedetector"
assert_output --partial "check-for-changes.sh.lock exists"
assert_output --partial "another execution of 'check-for-changes.sh' is happening"
sleep 65
run docker exec mail_changedetector_one /bin/bash -c "supervisorctl tail -3000 changedetector"
assert_output --partial "Removed stale lock"
assert_output --partial "removing stale lock file"
}

View File

@ -110,6 +110,7 @@ function teardown() {
local TEST_DOCKER_ARGS=(
--volume "${TEST_TMP_CONFIG}/letsencrypt/acme.json:/etc/letsencrypt/acme.json:ro"
--env DMS_DEBUG=1
--env LOG_LEVEL=trace
--env PERMIT_DOCKER='container'
--env SSL_DOMAIN='*.example.test'
--env SSL_TYPE='letsencrypt'