mirror of
https://github.com/docker-mailserver/docker-mailserver.git
synced 2025-08-03 01:24:52 +02:00
The provided default postfix master.cf overwrites the configs for saslauthd within main.cf. To make saslauthd work, we have to comment or in this case delete the lines from master.cf to make the given configs in main.cf work.
958 lines
32 KiB
Bash
958 lines
32 KiB
Bash
#!/bin/bash
|
|
|
|
##########################################################################
|
|
# >> DEFAULT VARS
|
|
#
|
|
# add them here.
|
|
# Example: DEFAULT_VARS["KEY"]="VALUE"
|
|
##########################################################################
|
|
declare -A DEFAULT_VARS
|
|
DEFAULT_VARS["VIRUSMAILS_DELETE_DELAY"]="${VIRUSMAILS_DELETE_DELAY:="7"}"
|
|
##########################################################################
|
|
# << DEFAULT VARS
|
|
##########################################################################
|
|
|
|
|
|
##########################################################################
|
|
# >> REGISTER FUNCTIONS
|
|
#
|
|
# add your new functions/methods here.
|
|
#
|
|
# NOTE: position matters when registering a function in stacks. First in First out
|
|
# Execution Logic:
|
|
# > check functions
|
|
# > setup functions
|
|
# > fix functions
|
|
# > misc functions
|
|
# > start-daemons
|
|
#
|
|
# Example:
|
|
# if [ CONDITION IS MET ]; then
|
|
# _register_{setup,fix,check,start}_{functions,daemons} "$FUNCNAME"
|
|
# fi
|
|
#
|
|
# Implement them in the section-group: {check,setup,fix,start}
|
|
##########################################################################
|
|
function register_functions() {
|
|
notify 'taskgrp' 'Registering check,setup,fix,misc and start-daemons functions'
|
|
|
|
################### >> check funcs
|
|
|
|
_register_check_function "_check_environment_variables"
|
|
_register_check_function "_check_hostname"
|
|
|
|
################### << check funcs
|
|
|
|
################### >> setup funcs
|
|
|
|
_register_setup_function "_setup_default_vars"
|
|
|
|
if [ "$ENABLE_ELK_FORWARDER" = 1 ]; then
|
|
_register_setup_function "_setup_elk_forwarder"
|
|
fi
|
|
|
|
if [ "$SMTP_ONLY" != 1 ]; then
|
|
_register_setup_function "_setup_dovecot"
|
|
_register_setup_function "_setup_dovecot_local_user"
|
|
fi
|
|
|
|
if [ "$ENABLE_LDAP" = 1 ];then
|
|
_register_setup_function "_setup_ldap"
|
|
fi
|
|
|
|
if [ "$ENABLE_SASLAUTHD" = 1 ];then
|
|
_register_setup_function "_setup_saslauthd"
|
|
fi
|
|
|
|
_register_setup_function "_setup_dkim"
|
|
_register_setup_function "_setup_ssl"
|
|
_register_setup_function "_setup_docker_permit"
|
|
|
|
_register_setup_function "_setup_mailname"
|
|
|
|
_register_setup_function "_setup_postfix_override_configuration"
|
|
_register_setup_function "_setup_postfix_sasl_password"
|
|
_register_setup_function "_setup_security_stack"
|
|
_register_setup_function "_setup_postfix_aliases"
|
|
_register_setup_function "_setup_postfix_vhost"
|
|
_register_setup_function "_setup_postfix_relay_amazon_ses"
|
|
|
|
################### << setup funcs
|
|
|
|
################### >> fix funcs
|
|
|
|
_register_fix_function "_fix_var_mail_permissions"
|
|
|
|
################### << fix funcs
|
|
|
|
################### >> misc funcs
|
|
|
|
_register_misc_function "_misc_save_states"
|
|
|
|
################### << misc funcs
|
|
|
|
################### >> daemon funcs
|
|
|
|
_register_start_daemon "_start_daemons_sys"
|
|
|
|
if [ "$ENABLE_ELK_FORWARDER" = 1 ]; then
|
|
_register_start_daemon "_start_daemons_filebeat"
|
|
fi
|
|
|
|
if [ "$SMTP_ONLY" != 1 ]; then
|
|
_register_start_daemon "_start_daemons_dovecot"
|
|
fi
|
|
|
|
# needs to be started before saslauthd
|
|
_register_start_daemon "_start_daemons_opendkim"
|
|
_register_start_daemon "_start_daemons_opendmarc"
|
|
_register_start_daemon "_start_daemons_postfix"
|
|
|
|
if [ "$ENABLE_SASLAUTHD" = 1 ];then
|
|
_register_start_daemon "_start_daemons_saslauthd"
|
|
fi
|
|
|
|
# care needs to run after postfix
|
|
if [ "$ENABLE_FAIL2BAN" = 1 ]; then
|
|
_register_start_daemon "_start_daemons_fail2ban"
|
|
fi
|
|
|
|
if [ "$ENABLE_FETCHMAIL" = 1 ]; then
|
|
_register_start_daemon "_start_daemons_fetchmail"
|
|
fi
|
|
|
|
if ! [ "$DISABLE_CLAMAV" = 1 ]; then
|
|
_register_start_daemon "_start_daemons_clamav"
|
|
fi
|
|
|
|
if ! [ "$DISABLE_AMAVIS" = 1 ]; then
|
|
_register_start_daemon "_start_daemons_amavis"
|
|
fi
|
|
################### << daemon funcs
|
|
}
|
|
##########################################################################
|
|
# << REGISTER FUNCTIONS
|
|
##########################################################################
|
|
|
|
|
|
|
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
# ! CARE --> DON'T CHANGE, unless you exactly know what you are doing
|
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
# >>
|
|
|
|
|
|
##########################################################################
|
|
# >> CONSTANTS
|
|
##########################################################################
|
|
declare -a FUNCS_SETUP
|
|
declare -a FUNCS_FIX
|
|
declare -a FUNCS_CHECK
|
|
declare -a FUNCS_MISC
|
|
declare -a DAEMONS_START
|
|
declare -A HELPERS_EXEC_STATE
|
|
##########################################################################
|
|
# << CONSTANTS
|
|
##########################################################################
|
|
|
|
|
|
##########################################################################
|
|
# >> protected register_functions
|
|
##########################################################################
|
|
function _register_start_daemon() {
|
|
DAEMONS_START+=($1)
|
|
notify 'inf' "$1() registered"
|
|
}
|
|
|
|
function _register_setup_function() {
|
|
FUNCS_SETUP+=($1)
|
|
notify 'inf' "$1() registered"
|
|
}
|
|
|
|
function _register_fix_function() {
|
|
FUNCS_FIX+=($1)
|
|
notify 'inf' "$1() registered"
|
|
}
|
|
|
|
function _register_check_function() {
|
|
FUNCS_CHECK+=($1)
|
|
notify 'inf' "$1() registered"
|
|
}
|
|
|
|
function _register_misc_function() {
|
|
FUNCS_MISC+=($1)
|
|
notify 'inf' "$1() registered"
|
|
}
|
|
##########################################################################
|
|
# << protected register_functions
|
|
##########################################################################
|
|
|
|
|
|
function notify () {
|
|
c_red="\e[0;31m"
|
|
c_green="\e[0;32m"
|
|
c_blue="\e[0;34m"
|
|
c_bold="\033[1m"
|
|
c_reset="\e[0m"
|
|
|
|
notification_type=$1
|
|
notification_msg=$2
|
|
|
|
case "${notification_type}" in
|
|
'inf')
|
|
msg="${c_green} * ${c_reset}${notification_msg}"
|
|
;;
|
|
'err')
|
|
msg="${c_red} * ${c_reset}${notification_msg}"
|
|
;;
|
|
'warn')
|
|
msg="${c_blue} * ${c_reset}${notification_msg}"
|
|
;;
|
|
'task')
|
|
msg=" >>>> ${notification_msg}"
|
|
;;
|
|
'taskgrp')
|
|
msg="${c_bold}${notification_msg}${c_reset}"
|
|
;;
|
|
'fatal')
|
|
msg="${c_bold} >>>> ${notification_msg} <<<<${c_reset}"
|
|
;;
|
|
*)
|
|
msg=""
|
|
;;
|
|
esac
|
|
|
|
[[ ! -z "${msg}" ]] && echo -e "${msg}"
|
|
}
|
|
|
|
function defunc() {
|
|
notify 'fatal' "Please fix the failures. Exiting ..."
|
|
exit 1
|
|
}
|
|
|
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
# ! CARE --> DON'T CHANGE, except you know exactly what you are doing
|
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
# <<
|
|
|
|
|
|
|
|
##########################################################################
|
|
# >> Check Stack
|
|
#
|
|
# Description: Place functions for initial check of container sanity
|
|
##########################################################################
|
|
function check() {
|
|
notify 'taskgrp' 'Checking configuration sanity:'
|
|
for _func in "${FUNCS_CHECK[@]}";do
|
|
$_func
|
|
[ $? != 0 ] && defunc
|
|
done
|
|
}
|
|
|
|
function _check_hostname() {
|
|
notify "task" "Check that hostname/domainname is provided (no default docker hostname) [$FUNCNAME]"
|
|
|
|
if ( ! echo $(hostname) | grep -E '^(\S+[.]\S+)$' ); then
|
|
notify 'err' "Setting hostname/domainname is required"
|
|
return 1
|
|
else
|
|
notify 'inf' "Hostname has been set"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
function _check_environment_variables() {
|
|
notify "task" "Check that there are no conflicts with env variables [$FUNCNAME]"
|
|
return 0
|
|
}
|
|
##########################################################################
|
|
# << Check Stack
|
|
##########################################################################
|
|
|
|
|
|
##########################################################################
|
|
# >> Setup Stack
|
|
#
|
|
# Description: Place functions for functional configurations here
|
|
##########################################################################
|
|
function setup() {
|
|
notify 'taskgrp' 'Setting up the Container:'
|
|
|
|
for _func in "${FUNCS_SETUP[@]}";do
|
|
$_func
|
|
[ $? != 0 ] && defunc
|
|
done
|
|
}
|
|
|
|
function _setup_default_vars() {
|
|
notify 'task' "Setting up default variables [$FUNCNAME]"
|
|
|
|
for var in ${!DEFAULT_VARS[@]}; do
|
|
echo "export $var=${DEFAULT_VARS[$var]}" >> /root/.bashrc
|
|
[ $? != 0 ] && notify 'err' "Unable to set $var=${DEFAULT_VARS[$var]}" && return 1
|
|
notify 'inf' "$var=${DEFAULT_VARS[$var]} set"
|
|
done
|
|
}
|
|
|
|
function _setup_mailname() {
|
|
notify 'task' 'Setting up Mailname'
|
|
|
|
echo "Creating /etc/mailname"
|
|
echo $(hostname -d) > /etc/mailname
|
|
}
|
|
|
|
function _setup_dovecot() {
|
|
notify 'task' '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)
|
|
mv /etc/dovecot/protocols.d/pop3d.protocol /etc/dovecot/protocols.d/pop3d.protocol.disab
|
|
mv /etc/dovecot/protocols.d/managesieved.protocol /etc/dovecot/protocols.d/managesieved.protocol.disab
|
|
sed -i -e 's/#ssl = yes/ssl = yes/g' /etc/dovecot/conf.d/10-master.conf
|
|
sed -i -e 's/#port = 993/port = 993/g' /etc/dovecot/conf.d/10-master.conf
|
|
sed -i -e 's/#port = 995/port = 995/g' /etc/dovecot/conf.d/10-master.conf
|
|
sed -i -e 's/#ssl = yes/ssl = required/g' /etc/dovecot/conf.d/10-ssl.conf
|
|
|
|
# Enable Managesieve service by setting the symlink
|
|
# to the configuration file Dovecot will actually find
|
|
if [ "$ENABLE_MANAGESIEVE" = 1 ]; then
|
|
echo "Sieve management enabled"
|
|
mv /etc/dovecot/protocols.d/managesieved.protocol.disab /etc/dovecot/protocols.d/managesieved.protocol
|
|
fi
|
|
}
|
|
|
|
function _setup_dovecot_local_user() {
|
|
notify 'task' 'Setting up Dovecot Local User'
|
|
echo -n > /etc/postfix/vmailbox
|
|
echo -n > /etc/dovecot/userdb
|
|
if [ -f /tmp/docker-mailserver/postfix-accounts.cf -a "$ENABLE_LDAP" != 1 ]; then
|
|
echo "Checking file line endings"
|
|
sed -i 's/\r//g' /tmp/docker-mailserver/postfix-accounts.cf
|
|
echo "Regenerating postfix 'vmailbox' and 'virtual' for given users"
|
|
echo "# WARNING: this file is auto-generated. Modify config/postfix-accounts.cf to edit user list." > /etc/postfix/vmailbox
|
|
|
|
# Checking that /tmp/docker-mailserver/postfix-accounts.cf ends with a newline
|
|
sed -i -e '$a\' /tmp/docker-mailserver/postfix-accounts.cf
|
|
|
|
chown dovecot:dovecot /etc/dovecot/userdb
|
|
chmod 640 /etc/dovecot/userdb
|
|
|
|
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
|
|
|
|
# Creating users
|
|
# 'pass' is encrypted
|
|
while IFS=$'|' read login pass
|
|
do
|
|
# Setting variables for better readability
|
|
user=$(echo ${login} | cut -d @ -f1)
|
|
domain=$(echo ${login} | cut -d @ -f2)
|
|
# Let's go!
|
|
echo "user '${user}' for domain '${domain}' with password '********'"
|
|
echo "${login} ${domain}/${user}/" >> /etc/postfix/vmailbox
|
|
# User database for dovecot has the following format:
|
|
# user:password:uid:gid:(gecos):home:(shell):extra_fields
|
|
# Example :
|
|
# ${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::userdb_mail=maildir:/var/mail/${domain}/${user}
|
|
echo "${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::" >> /etc/dovecot/userdb
|
|
mkdir -p /var/mail/${domain}
|
|
if [ ! -d "/var/mail/${domain}/${user}" ]; then
|
|
maildirmake.dovecot "/var/mail/${domain}/${user}"
|
|
maildirmake.dovecot "/var/mail/${domain}/${user}/.Sent"
|
|
maildirmake.dovecot "/var/mail/${domain}/${user}/.Trash"
|
|
maildirmake.dovecot "/var/mail/${domain}/${user}/.Drafts"
|
|
echo -e "INBOX\nSent\nTrash\nDrafts" >> "/var/mail/${domain}/${user}/subscriptions"
|
|
touch "/var/mail/${domain}/${user}/.Sent/maildirfolder"
|
|
fi
|
|
# Copy user provided sieve file, if present
|
|
test -e /tmp/docker-mailserver/${login}.dovecot.sieve && cp /tmp/docker-mailserver/${login}.dovecot.sieve /var/mail/${domain}/${user}/.dovecot.sieve
|
|
echo ${domain} >> /tmp/vhost.tmp
|
|
done < /tmp/docker-mailserver/postfix-accounts.cf
|
|
else
|
|
echo "==> Warning: 'config/docker-mailserver/postfix-accounts.cf' is not provided. No mail account created."
|
|
fi
|
|
}
|
|
|
|
function _setup_ldap() {
|
|
notify 'task' 'Setting up Ldap'
|
|
for i in 'users' 'groups' 'aliases'; do
|
|
sed -i -e 's|^server_host.*|server_host = '${LDAP_SERVER_HOST:="mail.domain.com"}'|g' \
|
|
-e 's|^search_base.*|search_base = '${LDAP_SEARCH_BASE:="ou=people,dc=domain,dc=com"}'|g' \
|
|
-e 's|^bind_dn.*|bind_dn = '${LDAP_BIND_DN:="cn=admin,dc=domain,dc=com"}'|g' \
|
|
-e 's|^bind_pw.*|bind_pw = '${LDAP_BIND_PW:="admin"}'|g' \
|
|
/etc/postfix/ldap-${i}.cf
|
|
done
|
|
|
|
echo "Configuring dovecot LDAP authentification"
|
|
sed -i -e 's|^hosts.*|hosts = '${LDAP_SERVER_HOST:="mail.domain.com"}'|g' \
|
|
-e 's|^base.*|base = '${LDAP_SEARCH_BASE:="ou=people,dc=domain,dc=com"}'|g' \
|
|
-e 's|^dn\s*=.*|dn = '${LDAP_BIND_DN:="cn=admin,dc=domain,dc=com"}'|g' \
|
|
-e 's|^dnpass\s*=.*|dnpass = '${LDAP_BIND_PW:="admin"}'|g' \
|
|
/etc/dovecot/dovecot-ldap.conf.ext
|
|
|
|
# Add domainname to vhost.
|
|
echo $(hostname -d) >> /tmp/vhost.tmp
|
|
|
|
echo "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
|
|
|
|
echo "Configuring LDAP"
|
|
[ -f /etc/postfix/ldap-users.cf ] && \
|
|
postconf -e "virtual_mailbox_maps = ldap:/etc/postfix/ldap-users.cf" || \
|
|
echo '==> Warning: /etc/postfix/ldap-user.cf not found'
|
|
|
|
[ -f /etc/postfix/ldap-aliases.cf -a -f /etc/postfix/ldap-groups.cf ] && \
|
|
postconf -e "virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf, ldap:/etc/postfix/ldap-groups.cf" || \
|
|
echo '==> Warning: /etc/postfix/ldap-aliases.cf or /etc/postfix/ldap-groups.cf not found'
|
|
|
|
[ ! -f /etc/postfix/sasl/smtpd.conf ] && cat > /etc/postfix/sasl/smtpd.conf << EOF
|
|
pwcheck_method: saslauthd
|
|
mech_list: plain login
|
|
EOF
|
|
return 0
|
|
}
|
|
|
|
function _setup_saslauthd() {
|
|
notify 'task' 'Setting up Saslauthd'
|
|
|
|
echo "Configuring Cyrus SASL"
|
|
# checking env vars and setting defaults
|
|
[ -z $SASLAUTHD_MECHANISMS ] && SASLAUTHD_MECHANISMS=pam
|
|
[ -z $SASLAUTHD_LDAP_SEARCH_BASE ] && SASLAUTHD_MECHANISMS=pam
|
|
[ -z $SASLAUTHD_LDAP_SERVER ] && SASLAUTHD_LDAP_SERVER=localhost
|
|
[ -z $SASLAUTHD_LDAP_FILTER ] && SASLAUTHD_LDAP_FILTER='(&(uniqueIdentifier=%u)(mailEnabled=TRUE))'
|
|
([ -z $SASLAUTHD_LDAP_SSL ] || [ $SASLAUTHD_LDAP_SSL == 0 ]) && SASLAUTHD_LDAP_PROTO='ldap://' || SASLAUTHD_LDAP_PROTO='ldaps://'
|
|
|
|
if [ ! -f /etc/saslauthd.conf ]; then
|
|
echo "Creating /etc/saslauthd.conf"
|
|
cat > /etc/saslauthd.conf << EOF
|
|
ldap_servers: ${SASLAUTHD_LDAP_PROTO}${SASLAUTHD_LDAP_SERVER}
|
|
|
|
ldap_auth_method: bind
|
|
ldap_bind_dn: ${SASLAUTHD_LDAP_BIND_DN}
|
|
ldap_bind_pw: ${SASLAUTHD_LDAP_PASSWORD}
|
|
|
|
ldap_search_base: ${SASLAUTHD_LDAP_SEARCH_BASE}
|
|
ldap_filter: ${SASLAUTHD_LDAP_FILTER}
|
|
|
|
ldap_referrals: yes
|
|
log_level: 10
|
|
EOF
|
|
fi
|
|
|
|
sed -i \
|
|
-e "/^[^#].*smtpd_sasl_type.*/s/^/#/g" \
|
|
-e "/^[^#].*smtpd_sasl_path.*/s/^/#/g" \
|
|
etc/postfix/master.cf
|
|
|
|
sed -i \
|
|
-e "s|^START=.*|START=yes|g" \
|
|
-e "s|^MECHANISMS=.*|MECHANISMS="\"$SASLAUTHD_MECHANISMS\""|g" \
|
|
-e "s|^MECH_OPTIONS=.*|MECH_OPTIONS="\"$SASLAUTHD_MECH_OPTIONS\""|g" \
|
|
/etc/default/saslauthd
|
|
sed -i \
|
|
-e "/smtpd_sasl_path =.*/d" \
|
|
-e "/smtpd_sasl_type =.*/d" \
|
|
-e "/dovecot_destination_recipient_limit =.*/d" \
|
|
/etc/postfix/main.cf
|
|
gpasswd -a postfix sasl
|
|
}
|
|
|
|
function _setup_postfix_aliases() {
|
|
notify 'task' 'Setting up Postfix Aliases'
|
|
|
|
echo -n > /etc/postfix/virtual
|
|
echo -n > /etc/postfix/regexp
|
|
if [ -f /tmp/docker-mailserver/postfix-virtual.cf ]; then
|
|
# Copying virtual file
|
|
cp -f /tmp/docker-mailserver/postfix-virtual.cf /etc/postfix/virtual
|
|
while read from to
|
|
do
|
|
# Setting variables for better readability
|
|
uname=$(echo ${from} | cut -d @ -f1)
|
|
domain=$(echo ${from} | cut -d @ -f2)
|
|
# if they are equal it means the line looks like: "user1 other@domain.tld"
|
|
test "$uname" != "$domain" && echo ${domain} >> /tmp/vhost.tmp
|
|
done < /tmp/docker-mailserver/postfix-virtual.cf
|
|
else
|
|
echo "==> Warning: 'config/postfix-virtual.cf' is not provided. No mail alias/forward created."
|
|
fi
|
|
if [ -f /tmp/docker-mailserver/postfix-regexp.cf ]; then
|
|
# Copying regexp alias file
|
|
echo "Adding regexp alias file postfix-regexp.cf"
|
|
cp -f /tmp/docker-mailserver/postfix-regexp.cf /etc/postfix/regexp
|
|
sed -i -e '/^virtual_alias_maps/{
|
|
s/ regexp:.*//
|
|
s/$/ regexp:\/etc\/postfix\/regexp/
|
|
}' /etc/postfix/main.cf
|
|
fi
|
|
}
|
|
|
|
function _setup_dkim() {
|
|
notify 'task' 'Setting up DKIM'
|
|
|
|
# Check if keys are already available
|
|
if [ -e "/tmp/docker-mailserver/opendkim/KeyTable" ]; then
|
|
mkdir -p /etc/opendkim
|
|
cp -a /tmp/docker-mailserver/opendkim/* /etc/opendkim/
|
|
echo "DKIM keys added for: `ls -C /etc/opendkim/keys/`"
|
|
echo "Changing permissions on /etc/opendkim"
|
|
# chown entire directory
|
|
chown -R opendkim:opendkim /etc/opendkim/
|
|
# And make sure permissions are right
|
|
chmod -R 0700 /etc/opendkim/keys/
|
|
else
|
|
echo "No DKIM key provided. Check the documentation to find how to get your keys."
|
|
fi
|
|
}
|
|
|
|
function _setup_ssl() {
|
|
notify 'task' 'Setting up SSL'
|
|
|
|
# SSL Configuration
|
|
case $SSL_TYPE in
|
|
"letsencrypt" )
|
|
# letsencrypt folders and files mounted in /etc/letsencrypt
|
|
if [ -e "/etc/letsencrypt/live/$(hostname)/cert.pem" ] \
|
|
&& [ -e "/etc/letsencrypt/live/$(hostname)/fullchain.pem" ]; then
|
|
KEY=""
|
|
if [ -e "/etc/letsencrypt/live/$(hostname)/privkey.pem" ]; then
|
|
KEY="privkey"
|
|
elif [ -e "/etc/letsencrypt/live/$(hostname)/key.pem" ]; then
|
|
KEY="key"
|
|
fi
|
|
if [ -n "$KEY" ]; then
|
|
echo "Adding $(hostname) SSL certificate"
|
|
|
|
# Postfix configuration
|
|
sed -i -r 's~smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem~smtpd_tls_cert_file=/etc/letsencrypt/live/'$(hostname)'/fullchain.pem~g' /etc/postfix/main.cf
|
|
sed -i -r 's~smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key~smtpd_tls_key_file=/etc/letsencrypt/live/'$(hostname)'/'"$KEY"'\.pem~g' /etc/postfix/main.cf
|
|
|
|
# Dovecot configuration
|
|
sed -i -e 's~ssl_cert = </etc/dovecot/dovecot\.pem~ssl_cert = </etc/letsencrypt/live/'$(hostname)'/fullchain\.pem~g' /etc/dovecot/conf.d/10-ssl.conf
|
|
sed -i -e 's~ssl_key = </etc/dovecot/private/dovecot\.pem~ssl_key = </etc/letsencrypt/live/'$(hostname)'/'"$KEY"'\.pem~g' /etc/dovecot/conf.d/10-ssl.conf
|
|
|
|
echo "SSL configured with 'letsencrypt' certificates"
|
|
fi
|
|
fi
|
|
;;
|
|
"custom" )
|
|
# Adding CA signed SSL certificate if provided in 'postfix/ssl' folder
|
|
if [ -e "/tmp/docker-mailserver/ssl/$(hostname)-full.pem" ]; then
|
|
echo "Adding $(hostname) SSL certificate"
|
|
mkdir -p /etc/postfix/ssl
|
|
cp "/tmp/docker-mailserver/ssl/$(hostname)-full.pem" /etc/postfix/ssl
|
|
|
|
# Postfix configuration
|
|
sed -i -r 's~smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem~smtpd_tls_cert_file=/etc/postfix/ssl/'$(hostname)'-full.pem~g' /etc/postfix/main.cf
|
|
sed -i -r 's~smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key~smtpd_tls_key_file=/etc/postfix/ssl/'$(hostname)'-full.pem~g' /etc/postfix/main.cf
|
|
|
|
# Dovecot configuration
|
|
sed -i -e 's~ssl_cert = </etc/dovecot/dovecot\.pem~ssl_cert = </etc/postfix/ssl/'$(hostname)'-full\.pem~g' /etc/dovecot/conf.d/10-ssl.conf
|
|
sed -i -e 's~ssl_key = </etc/dovecot/private/dovecot\.pem~ssl_key = </etc/postfix/ssl/'$(hostname)'-full\.pem~g' /etc/dovecot/conf.d/10-ssl.conf
|
|
|
|
echo "SSL configured with 'CA signed/custom' certificates"
|
|
fi
|
|
;;
|
|
"manual" )
|
|
# Lets you manually specify the location of the SSL Certs to use. This gives you some more control over this whole processes (like using kube-lego to generate certs)
|
|
if [ -n "$SSL_CERT_PATH" ] \
|
|
&& [ -n "$SSL_KEY_PATH" ]; then
|
|
echo "Configuring certificates using cert $SSL_CERT_PATH and key $SSL_KEY_PATH"
|
|
mkdir -p /etc/postfix/ssl
|
|
cp "$SSL_CERT_PATH" /etc/postfix/ssl/cert
|
|
cp "$SSL_KEY_PATH" /etc/postfix/ssl/key
|
|
chmod 600 /etc/postfix/ssl/cert
|
|
chmod 600 /etc/postfix/ssl/key
|
|
|
|
# Postfix configuration
|
|
sed -i -r 's~smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem~smtpd_tls_cert_file=/etc/postfix/ssl/cert~g' /etc/postfix/main.cf
|
|
sed -i -r 's~smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key~smtpd_tls_key_file=/etc/postfix/ssl/key~g' /etc/postfix/main.cf
|
|
|
|
# Dovecot configuration
|
|
sed -i -e 's~ssl_cert = </etc/dovecot/dovecot\.pem~ssl_cert = </etc/postfix/ssl/cert~g' /etc/dovecot/conf.d/10-ssl.conf
|
|
sed -i -e 's~ssl_key = </etc/dovecot/private/dovecot\.pem~ssl_key = </etc/postfix/ssl/key~g' /etc/dovecot/conf.d/10-ssl.conf
|
|
|
|
echo "SSL configured with 'Manual' certificates"
|
|
fi
|
|
;;
|
|
"self-signed" )
|
|
# Adding self-signed SSL certificate if provided in 'postfix/ssl' folder
|
|
if [ -e "/tmp/docker-mailserver/ssl/$(hostname)-cert.pem" ] \
|
|
&& [ -e "/tmp/docker-mailserver/ssl/$(hostname)-key.pem" ] \
|
|
&& [ -e "/tmp/docker-mailserver/ssl/$(hostname)-combined.pem" ] \
|
|
&& [ -e "/tmp/docker-mailserver/ssl/demoCA/cacert.pem" ]; then
|
|
echo "Adding $(hostname) SSL certificate"
|
|
mkdir -p /etc/postfix/ssl
|
|
cp "/tmp/docker-mailserver/ssl/$(hostname)-cert.pem" /etc/postfix/ssl
|
|
cp "/tmp/docker-mailserver/ssl/$(hostname)-key.pem" /etc/postfix/ssl
|
|
# Force permission on key file
|
|
chmod 600 /etc/postfix/ssl/$(hostname)-key.pem
|
|
cp "/tmp/docker-mailserver/ssl/$(hostname)-combined.pem" /etc/postfix/ssl
|
|
cp /tmp/docker-mailserver/ssl/demoCA/cacert.pem /etc/postfix/ssl
|
|
|
|
# Postfix configuration
|
|
sed -i -r 's~smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem~smtpd_tls_cert_file=/etc/postfix/ssl/'$(hostname)'-cert.pem~g' /etc/postfix/main.cf
|
|
sed -i -r 's~smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key~smtpd_tls_key_file=/etc/postfix/ssl/'$(hostname)'-key.pem~g' /etc/postfix/main.cf
|
|
sed -i -r 's~#smtpd_tls_CAfile=~smtpd_tls_CAfile=/etc/postfix/ssl/cacert.pem~g' /etc/postfix/main.cf
|
|
sed -i -r 's~#smtp_tls_CAfile=~smtp_tls_CAfile=/etc/postfix/ssl/cacert.pem~g' /etc/postfix/main.cf
|
|
ln -s /etc/postfix/ssl/cacert.pem "/etc/ssl/certs/cacert-$(hostname).pem"
|
|
|
|
# Dovecot configuration
|
|
sed -i -e 's~ssl_cert = </etc/dovecot/dovecot\.pem~ssl_cert = </etc/postfix/ssl/'$(hostname)'-combined\.pem~g' /etc/dovecot/conf.d/10-ssl.conf
|
|
sed -i -e 's~ssl_key = </etc/dovecot/private/dovecot\.pem~ssl_key = </etc/postfix/ssl/'$(hostname)'-key\.pem~g' /etc/dovecot/conf.d/10-ssl.conf
|
|
|
|
echo "SSL configured with 'self-signed' certificates"
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function _setup_postfix_vhost() {
|
|
notify 'task' "Setting up Postfix vhost"
|
|
|
|
if [ -f /tmp/vhost.tmp ]; then
|
|
cat /tmp/vhost.tmp | sort | uniq > /etc/postfix/vhost && rm /tmp/vhost.tmp
|
|
fi
|
|
}
|
|
|
|
function _setup_docker_permit() {
|
|
notify 'task' 'Setting up PERMIT_DOCKER Option'
|
|
|
|
container_ip=$(ip addr show eth0 | grep 'inet ' | sed 's/[^0-9\.\/]*//g' | cut -d '/' -f 1)
|
|
container_network="$(echo $container_ip | cut -d '.' -f1-2).0.0"
|
|
|
|
case $PERMIT_DOCKER in
|
|
"host" )
|
|
echo "Adding $container_network/16 to my networks"
|
|
postconf -e "$(postconf | grep '^mynetworks =') $container_network/16"
|
|
bash -c "echo $container_network/16 >> /etc/opendmarc/ignore.hosts"
|
|
bash -c "echo $container_network/16 >> /etc/opendkim/TrustedHosts"
|
|
;;
|
|
|
|
"network" )
|
|
echo "Adding docker network in my networks"
|
|
postconf -e "$(postconf | grep '^mynetworks =') 172.16.0.0/12"
|
|
bash -c "echo 172.16.0.0/12 >> /etc/opendmarc/ignore.hosts"
|
|
bash -c "echo 172.16.0.0/12 >> /etc/opendkim/TrustedHosts"
|
|
;;
|
|
|
|
* )
|
|
echo "Adding container ip in my networks"
|
|
postconf -e "$(postconf | grep '^mynetworks =') $container_ip/32"
|
|
bash -c "echo $container_ip/32 >> /etc/opendmarc/ignore.hosts"
|
|
bash -c "echo $container_ip/32 >> /etc/opendkim/TrustedHosts"
|
|
;;
|
|
esac
|
|
|
|
# @TODO fix: bash: /etc/opendkim/TrustedHosts: No such file or directory
|
|
# temporary workarround return success
|
|
return 0
|
|
}
|
|
|
|
function _setup_postfix_override_configuration() {
|
|
notify 'task' 'Setting up Postfix Override configuration'
|
|
|
|
if [ -f /tmp/docker-mailserver/postfix-main.cf ]; then
|
|
while read line; do
|
|
postconf -e "$line"
|
|
done < /tmp/docker-mailserver/postfix-main.cf
|
|
echo "Loaded 'config/postfix-main.cf'"
|
|
else
|
|
echo "No extra postfix settings loaded because optional '/tmp/docker-mailserver/postfix-main.cf' not provided."
|
|
fi
|
|
}
|
|
|
|
function _setup_postfix_sasl_password() {
|
|
notify 'task' 'Setting up Postfix SASL Password'
|
|
|
|
# Support general SASL password
|
|
rm -f /etc/postfix/sasl_passwd
|
|
if [ ! -z "$SASL_PASSWD" ]; then
|
|
echo "$SASL_PASSWD" >> /etc/postfix/sasl_passwd
|
|
fi
|
|
|
|
# Install SASL passwords
|
|
if [ -f /etc/postfix/sasl_passwd ]; then
|
|
chown root:root /etc/postfix/sasl_passwd
|
|
chmod 0600 /etc/postfix/sasl_passwd
|
|
echo "Loaded SASL_PASSWD"
|
|
else
|
|
echo "==> Warning: 'SASL_PASSWD' is not provided. /etc/postfix/sasl_passwd not created."
|
|
fi
|
|
}
|
|
|
|
function _setup_postfix_relay_amazon_ses() {
|
|
notify 'task' 'Setting up Postfix Relay Amazon SES'
|
|
|
|
if [ ! -z "$AWS_SES_HOST" -a ! -z "$AWS_SES_USERPASS" ]; then
|
|
if [ -z "$AWS_SES_PORT" ];then
|
|
AWS_SES_PORT=25
|
|
fi
|
|
echo "Setting up outgoing email via AWS SES host $AWS_SES_HOST:$AWS_SES_PORT"
|
|
echo "[$AWS_SES_HOST]:$AWS_SES_PORT $AWS_SES_USERPASS" >> /etc/postfix/sasl_passwd
|
|
postconf -e \
|
|
"relayhost = [$AWS_SES_HOST]:$AWS_SES_PORT" \
|
|
"smtp_sasl_auth_enable = yes" \
|
|
"smtp_sasl_security_options = noanonymous" \
|
|
"smtp_sasl_password_maps = texthash:/etc/postfix/sasl_passwd" \
|
|
"smtp_use_tls = yes" \
|
|
"smtp_tls_security_level = encrypt" \
|
|
"smtp_tls_note_starttls_offer = yes" \
|
|
"smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
|
|
fi
|
|
}
|
|
|
|
|
|
function _setup_security_stack() {
|
|
notify 'task' 'Setting up Security Stack'
|
|
|
|
echo "Configuring Spamassassin"
|
|
SA_TAG=${SA_TAG:="2.0"} && sed -i -r 's/^\$sa_tag_level_deflt (.*);/\$sa_tag_level_deflt = '$SA_TAG';/g' /etc/amavis/conf.d/20-debian_defaults
|
|
SA_TAG2=${SA_TAG2:="6.31"} && sed -i -r 's/^\$sa_tag2_level_deflt (.*);/\$sa_tag2_level_deflt = '$SA_TAG2';/g' /etc/amavis/conf.d/20-debian_defaults
|
|
SA_KILL=${SA_KILL:="6.31"} && sed -i -r 's/^\$sa_kill_level_deflt (.*);/\$sa_kill_level_deflt = '$SA_KILL';/g' /etc/amavis/conf.d/20-debian_defaults
|
|
test -e /tmp/docker-mailserver/spamassassin-rules.cf && cp /tmp/docker-mailserver/spamassassin-rules.cf /etc/spamassassin/
|
|
|
|
if [ "$ENABLE_FAIL2BAN" = 1 ]; then
|
|
echo "Fail2ban enabled"
|
|
test -e /tmp/docker-mailserver/fail2ban-jail.cf && cp /tmp/docker-mailserver/fail2ban-jail.cf /etc/fail2ban/jail.local
|
|
else
|
|
# Disable logrotate config for fail2ban if not enabled
|
|
rm -f /etc/logrotate.d/fail2ban
|
|
fi
|
|
|
|
# Fix cron.daily for spamassassin
|
|
sed -i -e 's~invoke-rc.d spamassassin reload~/etc/init\.d/spamassassin reload~g' /etc/cron.daily/spamassassin
|
|
|
|
# Copy user provided configuration files if provided
|
|
if [ -f /tmp/docker-mailserver/amavis.cf ]; then
|
|
cp /tmp/docker-mailserver/amavis.cf /etc/amavis/conf.d/50-user
|
|
fi
|
|
}
|
|
|
|
function _setup_elk_forwarder() {
|
|
notify 'task' 'Setting up Elk forwarder'
|
|
|
|
ELK_PORT=${ELK_PORT:="5044"}
|
|
ELK_HOST=${ELK_HOST:="elk"}
|
|
echo "Enabling log forwarding to ELK ($ELK_HOST:$ELK_PORT)"
|
|
cat /etc/filebeat/filebeat.yml.tmpl \
|
|
| sed "s@\$ELK_HOST@$ELK_HOST@g" \
|
|
| sed "s@\$ELK_PORT@$ELK_PORT@g" \
|
|
> /etc/filebeat/filebeat.yml
|
|
}
|
|
##########################################################################
|
|
# << Setup Stack
|
|
##########################################################################
|
|
|
|
|
|
##########################################################################
|
|
# >> Fix Stack
|
|
#
|
|
# Description: Place functions for temporary workarounds and fixes here
|
|
##########################################################################
|
|
function fix() {
|
|
notify 'taskgrg' "Starting to fix:"
|
|
for _func in "${FUNCS_FIX[@]}";do
|
|
$_func
|
|
[ $? != 0 ] && defunc
|
|
done
|
|
}
|
|
|
|
function _fix_var_mail_permissions() {
|
|
notify 'task' 'Fixing /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 \) | grep -c .` != 0 ]; then
|
|
chown -R 5000:5000 /var/mail
|
|
echo "/var/mail permissions fixed"
|
|
else
|
|
echo "Permissions in /var/mail look OK"
|
|
fi
|
|
}
|
|
##########################################################################
|
|
# << Fix Stack
|
|
##########################################################################
|
|
|
|
|
|
##########################################################################
|
|
# >> Misc Stack
|
|
#
|
|
# Description: Place functions that do not fit in the sections above here
|
|
##########################################################################
|
|
function misc() {
|
|
notify 'taskgrp' 'Starting Misc:'
|
|
|
|
for _func in "${FUNCS_MISC[@]}";do
|
|
$_func
|
|
[ $? != 0 ] && defunc
|
|
done
|
|
}
|
|
|
|
function _misc_save_states() {
|
|
# Consolidate all state that should be persisted across container restarts into one mounted
|
|
# directory
|
|
statedir=/var/mail-state
|
|
if [ "$ONE_DIR" = 1 -a -d $statedir ]; then
|
|
echo "Consolidating all state onto $statedir"
|
|
for d in /var/spool/postfix /var/lib/postfix /var/lib/amavis /var/lib/clamav /var/lib/spamassasin /var/lib/fail2ban; do
|
|
dest=$statedir/`echo $d | sed -e 's/.var.//; s/\//-/g'`
|
|
if [ -d $dest ]; then
|
|
echo " Destination $dest exists, linking $d to it"
|
|
rm -rf $d
|
|
ln -s $dest $d
|
|
elif [ -d $d ]; then
|
|
echo " Moving contents of $d to $dest:" `ls $d`
|
|
mv $d $dest
|
|
ln -s $dest $d
|
|
else
|
|
echo " Linking $d to $dest"
|
|
mkdir -p $dest
|
|
ln -s $dest $d
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
|
|
##########################################################################
|
|
# >> Start Daemons
|
|
##########################################################################
|
|
function start_daemons() {
|
|
notify 'taskgrp' 'Starting Daemons'
|
|
|
|
for _func in "${DAEMONS_START[@]}";do
|
|
$_func
|
|
[ $? != 0 ] && defunc
|
|
done
|
|
}
|
|
|
|
function _start_daemons_sys() {
|
|
notify 'task' 'Starting Cron'
|
|
cron
|
|
|
|
notify 'task' 'Starting rsyslog'
|
|
/etc/init.d/rsyslog start
|
|
}
|
|
|
|
function _start_daemons_saslauthd() {
|
|
notify "task" "Starting saslauthd"
|
|
/etc/init.d/saslauthd start
|
|
}
|
|
|
|
function _start_daemons_fail2ban() {
|
|
notify 'task' 'Starting fail2ban'
|
|
touch /var/log/auth.log
|
|
# Delete fail2ban.sock that probably was left here after container restart
|
|
if [ -e /var/run/fail2ban/fail2ban.sock ]; then
|
|
rm /var/run/fail2ban/fail2ban.sock
|
|
fi
|
|
/etc/init.d/fail2ban start
|
|
}
|
|
|
|
function _start_daemons_opendkim() {
|
|
notify 'task' 'Starting opendkim'
|
|
/etc/init.d/opendkim start
|
|
}
|
|
|
|
function _start_daemons_opendmarc() {
|
|
notify 'task' 'Starting opendmarc'
|
|
/etc/init.d/opendmarc start
|
|
}
|
|
|
|
function _start_daemons_postfix() {
|
|
notify 'task' 'Starting postfix'
|
|
/etc/init.d/postfix start
|
|
}
|
|
|
|
function _start_daemons_dovecot() {
|
|
# Here we are starting sasl and imap, not pop3 because it's disabled by default
|
|
notify 'task' "Starting dovecot services"
|
|
/usr/sbin/dovecot -c /etc/dovecot/dovecot.conf
|
|
|
|
if [ "$ENABLE_POP3" = 1 ]; then
|
|
echo "Starting POP3 services"
|
|
mv /etc/dovecot/protocols.d/pop3d.protocol.disab /etc/dovecot/protocols.d/pop3d.protocol
|
|
/usr/sbin/dovecot reload
|
|
fi
|
|
|
|
if [ -f /tmp/docker-mailserver/dovecot.cf ]; then
|
|
echo 'Adding file "dovecot.cf" to the Dovecot configuration'
|
|
cp /tmp/docker-mailserver/dovecot.cf /etc/dovecot/local.conf
|
|
/usr/sbin/dovecot reload
|
|
fi
|
|
|
|
# @TODO fix: on integration test
|
|
# doveadm: Error: userdb lookup: connect(/var/run/dovecot/auth-userdb) failed: No such file or directory
|
|
# doveadm: Fatal: user listing failed
|
|
|
|
#if [ "$ENABLE_LDAP" != 1 ]; then
|
|
#echo "Listing users"
|
|
#/usr/sbin/dovecot user '*'
|
|
#fi
|
|
}
|
|
|
|
function _start_daemons_filebeat() {
|
|
notify 'task' 'Starting FileBeat'
|
|
/etc/init.d/filebeat start
|
|
}
|
|
|
|
function _start_daemons_fetchmail() {
|
|
notify 'task' 'Starting fetchmail'
|
|
/usr/local/bin/setup-fetchmail
|
|
echo "Fetchmail enabled"
|
|
/etc/init.d/fetchmail start
|
|
}
|
|
|
|
function _start_daemons_clamav() {
|
|
notify 'task' "Starting clamav"
|
|
/etc/init.d/clamav-daemon start
|
|
}
|
|
|
|
function _start_daemons_amavis() {
|
|
notify 'task' 'Starting Daemon Amavis'
|
|
/etc/init.d/amavis start
|
|
|
|
# @TODO fix: on integration test of mail_with_ldap amavis fails because of:
|
|
# Starting amavisd: The value of variable $myhostname is "ldap", but should have been
|
|
# a fully qualified domain name; perhaps uname(3) did not provide such.
|
|
# You must explicitly assign a FQDN of this host to variable $myhostname
|
|
# in /etc/amavis/conf.d/05-node_id, or fix what uname(3) provides as a host's
|
|
# network name!
|
|
|
|
# > temporary workaround to passe integration test
|
|
return 0
|
|
}
|
|
##########################################################################
|
|
# << Start Daemons
|
|
##########################################################################
|
|
|
|
|
|
|
|
|
|
|
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
# ! CARE --> DON'T CHANGE, unless you exactly know what you are doing
|
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
# >>
|
|
|
|
|
|
register_functions
|
|
|
|
check
|
|
setup
|
|
fix
|
|
misc
|
|
start_daemons
|
|
|
|
tail -f /var/log/mail/mail.log
|
|
|
|
|
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
# ! CARE --> DON'T CHANGE, unless you exactly know what you are doing
|
|
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
# <<
|
|
|
|
exit 0
|