From 24031ae36587caa0bbf0dd0c30e35812f077a536 Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Mon, 21 Mar 2022 07:07:52 +0100 Subject: [PATCH] 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 --- docs/content/config/environment.md | 8 + docs/content/contributing/coding-style.md | 6 +- mailserver.env | 8 + target/bin/print-environment | 2 +- target/scripts/helpers/accounts.sh | 20 +- target/scripts/helpers/aliases.sh | 8 +- target/scripts/helpers/error.sh | 17 +- target/scripts/helpers/lock.sh | 11 +- target/scripts/helpers/log.sh | 95 ++++++++++ target/scripts/helpers/relay.sh | 14 +- target/scripts/helpers/ssl.sh | 44 ++--- target/scripts/start-mailserver.sh | 22 ++- target/scripts/startup/check-stack.sh | 28 ++- target/scripts/startup/daemons-stack.sh | 38 ++-- target/scripts/startup/fixes-stack.sh | 24 +-- target/scripts/startup/misc-stack.sh | 12 +- target/scripts/startup/setup-stack.sh | 218 +++++++++++----------- test/mail_changedetector.bats | 12 +- test/mail_ssl_letsencrypt.bats | 1 + 19 files changed, 367 insertions(+), 221 deletions(-) diff --git a/docs/content/config/environment.md b/docs/content/config/environment.md index 4636db9b..e0251db3 100644 --- a/docs/content/config/environment.md +++ b/docs/content/config/environment.md @@ -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 diff --git a/docs/content/contributing/coding-style.md b/docs/content/contributing/coding-style.md index 202344e9..11d95d47 100644 --- a/docs/content/contributing/coding-style.md +++ b/docs/content/contributing/coding-style.md @@ -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 ... diff --git a/mailserver.env b/mailserver.env index 48a07d37..28f6414d 100644 --- a/mailserver.env +++ b/mailserver.env @@ -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 diff --git a/target/bin/print-environment b/target/bin/print-environment index 389fe8b6..468c3f76 100755 --- a/target/bin/print-environment +++ b/target/bin/print-environment @@ -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 diff --git a/target/scripts/helpers/accounts.sh b/target/scripts/helpers/accounts.sh index cf1e483e..56cf5a3e 100644 --- a/target/scripts/helpers/accounts.sh +++ b/target/scripts/helpers/accounts.sh @@ -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 diff --git a/target/scripts/helpers/aliases.sh b/target/scripts/helpers/aliases.sh index 07e24614..1a4febc1 100644 --- a/target/scripts/helpers/aliases.sh +++ b/target/scripts/helpers/aliases.sh @@ -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 diff --git a/target/scripts/helpers/error.sh b/target/scripts/helpers/error.sh index 01a530a0..57151533 100644 --- a/target/scripts/helpers/error.sh +++ b/target/scripts/helpers/error.sh @@ -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 } diff --git a/target/scripts/helpers/lock.sh b/target/scripts/helpers/lock.sh index 1f45130d..63693ae4 100644 --- a/target/scripts/helpers/lock.sh +++ b/target/scripts/helpers/lock.sh @@ -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 } diff --git a/target/scripts/helpers/log.sh b/target/scripts/helpers/log.sh index d963c97d..a61d0c16 100644 --- a/target/scripts/helpers/log.sh +++ b/target/scripts/helpers/log.sh @@ -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 diff --git a/target/scripts/helpers/relay.sh b/target/scripts/helpers/relay.sh index dd0fe210..676481ef 100644 --- a/target/scripts/helpers/relay.sh +++ b/target/scripts/helpers/relay.sh @@ -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 diff --git a/target/scripts/helpers/ssl.sh b/target/scripts/helpers/ssl.sh index 7731e6d8..a928656d 100644 --- a/target/scripts/helpers/ssl.sh +++ b/target/scripts/helpers/ssl.sh @@ -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//', tried: '${SSL_DOMAIN}', '${HOSTNAME}', '${DOMAINNAME}'" + _log 'warn' "Cannot find a valid DOMAIN for '/etc/letsencrypt/live//', 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 diff --git a/target/scripts/start-mailserver.sh b/target/scripts/start-mailserver.sh index 340e40c1..7e078f6b 100755 --- a/target/scripts/start-mailserver.sh +++ b/target/scripts/start-mailserver.sh @@ -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 $(/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 diff --git a/target/scripts/startup/check-stack.sh b/target/scripts/startup/check-stack.sh index a5c09503..bff7d425 100644 --- a/target/scripts/startup/check-stack.sh +++ b/target/scripts/startup/check-stack.sh @@ -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 +} diff --git a/target/scripts/startup/daemons-stack.sh b/target/scripts/startup/daemons-stack.sh index b45d1e97..035b38a9 100644 --- a/target/scripts/startup/daemons-stack.sh +++ b/target/scripts/startup/daemons-stack.sh @@ -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' } diff --git a/target/scripts/startup/fixes-stack.sh b/target/scripts/startup/fixes-stack.sh index 3d9a58f4..7a26c76e 100644 --- a/target/scripts/startup/fixes-stack.sh +++ b/target/scripts/startup/fixes-stack.sh @@ -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' } } diff --git a/target/scripts/startup/misc-stack.sh b/target/scripts/startup/misc-stack.sh index 43626fd5..979f4292 100644 --- a/target/scripts/startup/misc-stack.sh +++ b/target/scripts/startup/misc-stack.sh @@ -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 diff --git a/target/scripts/startup/setup-stack.sh b/target/scripts/startup/setup-stack.sh index 2844587d..8b6c2af7 100644 --- a/target/scripts/startup/setup-stack.sh +++ b/target/scripts/startup/setup-stack.sh @@ -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 = " } diff --git a/test/mail_changedetector.bats b/test/mail_changedetector.bats index 7c43e4e0..90867019 100644 --- a/test/mail_changedetector.bats +++ b/test/mail_changedetector.bats @@ -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" } diff --git a/test/mail_ssl_letsencrypt.bats b/test/mail_ssl_letsencrypt.bats index 231d6c14..91ef7233 100644 --- a/test/mail_ssl_letsencrypt.bats +++ b/test/mail_ssl_letsencrypt.bats @@ -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'