2022-10-17 08:40:09 +00:00
#!/bin/bash
2021-02-23 19:03:01 +00:00
2022-05-15 21:37:21 +00:00
function _setup
2021-02-23 19:03:01 +00:00
{
2022-03-21 06:07:52 +00:00
_log 'info' 'Configuring mail server'
2021-02-23 19:03:01 +00:00
for FUNC in " ${ FUNCS_SETUP [@] } "
do
${ FUNC }
done
2022-06-04 23:59:54 +00:00
# All startup modifications to configs should have taken place before calling this:
_prepare_for_change_detection
2021-02-23 19:03:01 +00:00
}
function _setup_supervisor
{
2022-08-22 06:31:32 +00:00
SUPERVISOR_LOGLEVEL = " ${ SUPERVISOR_LOGLEVEL :- warn } "
2021-02-23 19:03:01 +00:00
if ! grep -q " loglevel = ${ SUPERVISOR_LOGLEVEL } " /etc/supervisor/supervisord.conf
then
case " ${ SUPERVISOR_LOGLEVEL } " in
2022-03-17 10:24:30 +00:00
( 'critical' | 'error' | 'info' | 'debug' )
2021-02-23 19:03:01 +00:00
sed -i -E \
2021-02-25 09:57:20 +00:00
" s|(loglevel).*|\1 = ${ SUPERVISOR_LOGLEVEL } |g " \
2021-02-23 19:03:01 +00:00
/etc/supervisor/supervisord.conf
2021-02-25 09:57:20 +00:00
supervisorctl reload
2021-12-29 16:36:29 +00:00
exit
2021-02-25 09:57:20 +00:00
; ;
2022-08-22 06:31:32 +00:00
( 'warn' ) ; ;
2021-02-23 19:03:01 +00:00
2022-03-17 10:24:30 +00:00
( * )
2022-03-21 06:07:52 +00:00
_log 'warn' \
2021-02-25 09:57:20 +00:00
" SUPERVISOR_LOGLEVEL ' ${ SUPERVISOR_LOGLEVEL } ' unknown. Using default 'warn' "
2021-02-23 19:03:01 +00:00
; ;
esac
fi
2021-02-25 09:57:20 +00:00
return 0
2021-02-23 19:03:01 +00:00
}
# File/folder permissions are fine when using docker volumes, but may be wrong
# when file system folders are mounted into the container.
# Set the expected values and create missing folders/files just in case.
function _setup_file_permissions
{
2022-03-26 09:17:08 +00:00
_log 'debug' 'Setting file and directory permissions'
2021-02-23 19:03:01 +00:00
mkdir -p /var/log/supervisor
mkdir -p /var/log/mail
chown syslog:root /var/log/mail
touch /var/log/mail/clamav.log
chown clamav:adm /var/log/mail/clamav.log
chmod 640 /var/log/mail/clamav.log
touch /var/log/mail/freshclam.log
chown clamav:adm /var/log/mail/freshclam.log
chmod 640 /var/log/mail/freshclam.log
}
function _setup_mailname
{
2022-03-26 09:17:08 +00:00
_log 'debug' "Setting up mailname and creating '/etc/mailname'"
2021-02-23 19:03:01 +00:00
echo " ${ DOMAINNAME } " >/etc/mailname
}
function _setup_amavis
{
2021-03-28 13:37:48 +00:00
if [ [ ${ ENABLE_AMAVIS } -eq 1 ] ]
then
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up Amavis'
2021-03-28 13:37:48 +00:00
sed -i \
" s|^#\$myhostname = \"mail.example.com\";|\$myhostname = \" ${ HOSTNAME } \";| " \
/etc/amavis/conf.d/05-node_id
else
2022-03-26 09:17:08 +00:00
_log 'debug' "Removing Amavis from Postfix's configuration"
2021-03-28 13:37:48 +00:00
sed -i 's|content_filter =.*|content_filter =|' /etc/postfix/main.cf
2022-10-16 09:52:53 +00:00
_log 'debug' 'Disabling Amavis cron job'
mv /etc/cron.d/amavisd-new /etc/cron.d/amavisd-new.disabled
chmod 0 /etc/cron.d/amavisd-new.disabled
2022-03-21 06:07:52 +00:00
[ [ ${ 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.'
2021-03-28 13:37:48 +00:00
fi
2021-02-23 19:03:01 +00:00
}
function _setup_dmarc_hostname
{
2022-03-26 09:17:08 +00:00
_log 'debug' 'Setting up DMARC'
2021-02-23 19:03:01 +00:00
sed -i -e \
2021-11-10 11:21:26 +00:00
" s|^AuthservID.* $|AuthservID ${ HOSTNAME } |g " \
-e " s|^TrustedAuthservIDs.* $|TrustedAuthservIDs ${ HOSTNAME } |g " \
2021-02-23 19:03:01 +00:00
/etc/opendmarc.conf
}
function _setup_postfix_hostname
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Applying hostname and domainname to Postfix'
2022-08-29 11:26:44 +00:00
postconf " myhostname = ${ HOSTNAME } "
postconf " mydomain = ${ DOMAINNAME } "
2021-02-23 19:03:01 +00:00
}
function _setup_dovecot_hostname
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Applying hostname to Dovecot'
2021-02-23 19:03:01 +00:00
sed -i \
" s|^#hostname =.* $|hostname = ' ${ HOSTNAME } '|g " \
/etc/dovecot/conf.d/15-lda.conf
}
function _setup_dovecot
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up Dovecot'
2021-02-23 19:03:01 +00:00
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
sed -i 's|^postmaster_address = .*$|postmaster_address = ' " ${ POSTMASTER_ADDRESS } " '|g' /etc/dovecot/conf.d/15-lda.conf
2021-12-12 11:08:34 +00:00
if ! grep -q -E '^stats_writer_socket_path=' /etc/dovecot/dovecot.conf
then
2022-05-05 15:48:21 +00:00
printf '\n%s\n' 'stats_writer_socket_path=' >>/etc/dovecot/dovecot.conf
2021-12-12 11:08:34 +00:00
fi
2021-02-23 19:03:01 +00:00
# set mail_location according to mailbox format
case " ${ DOVECOT_MAILBOX_FORMAT } " in
2022-03-21 06:07:52 +00:00
( 'sdbox' | 'mdbox' )
_log 'trace' " Dovecot ${ DOVECOT_MAILBOX_FORMAT } format configured "
2021-02-23 19:03:01 +00:00
sed -i -e \
" s|^mail_location = .* $|mail_location = ${ DOVECOT_MAILBOX_FORMAT } :\/var\/mail\/%d\/%n|g " \
/etc/dovecot/conf.d/10-mail.conf
2022-03-21 06:07:52 +00:00
_log 'trace' 'Enabling cron job for dbox purge'
2021-02-23 19:03:01 +00:00
mv /etc/cron.d/dovecot-purge.disabled /etc/cron.d/dovecot-purge
chmod 644 /etc/cron.d/dovecot-purge
; ;
2022-03-17 10:24:30 +00:00
( * )
2022-03-26 09:17:08 +00:00
_log 'trace' 'Dovecot default format (maildir) configured'
2021-02-23 19:03:01 +00:00
sed -i -e 's|^mail_location = .*$|mail_location = maildir:\/var\/mail\/%d\/%n|g' /etc/dovecot/conf.d/10-mail.conf
; ;
esac
# enable Managesieve service by setting the symlink
# to the configuration file Dovecot will actually find
if [ [ ${ ENABLE_MANAGESIEVE } -eq 1 ] ]
then
2022-03-21 06:07:52 +00:00
_log 'trace' 'Sieve management enabled'
2021-02-23 19:03:01 +00:00
mv /etc/dovecot/protocols.d/managesieved.protocol.disab /etc/dovecot/protocols.d/managesieved.protocol
fi
# copy pipe and filter programs, if any
rm -f /usr/lib/dovecot/sieve-filter/*
rm -f /usr/lib/dovecot/sieve-pipe/*
[ [ -d /tmp/docker-mailserver/sieve-filter ] ] && cp /tmp/docker-mailserver/sieve-filter/* /usr/lib/dovecot/sieve-filter/
[ [ -d /tmp/docker-mailserver/sieve-pipe ] ] && cp /tmp/docker-mailserver/sieve-pipe/* /usr/lib/dovecot/sieve-pipe/
# create global sieve directories
mkdir -p /usr/lib/dovecot/sieve-global/before
mkdir -p /usr/lib/dovecot/sieve-global/after
if [ [ -f /tmp/docker-mailserver/before.dovecot.sieve ] ]
then
cp /tmp/docker-mailserver/before.dovecot.sieve /usr/lib/dovecot/sieve-global/before/50-before.dovecot.sieve
sievec /usr/lib/dovecot/sieve-global/before/50-before.dovecot.sieve
else
rm -f /usr/lib/dovecot/sieve-global/before/50-before.dovecot.sieve /usr/lib/dovecot/sieve-global/before/50-before.dovecot.svbin
fi
if [ [ -f /tmp/docker-mailserver/after.dovecot.sieve ] ]
then
cp /tmp/docker-mailserver/after.dovecot.sieve /usr/lib/dovecot/sieve-global/after/50-after.dovecot.sieve
sievec /usr/lib/dovecot/sieve-global/after/50-after.dovecot.sieve
else
rm -f /usr/lib/dovecot/sieve-global/after/50-after.dovecot.sieve /usr/lib/dovecot/sieve-global/after/50-after.dovecot.svbin
fi
# 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
2022-03-26 09:17:08 +00:00
_log 'debug' 'Spam messages will be moved to the Junk folder'
2021-02-23 19:03:01 +00:00
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
rm -f /usr/lib/dovecot/sieve-global/before/60-spam.sieve /usr/lib/dovecot/sieve-global/before/60-spam.svbin
fi
chown docker:docker -R /usr/lib/dovecot/sieve*
chmod 550 -R /usr/lib/dovecot/sieve*
chmod -f +x /usr/lib/dovecot/sieve-pipe/*
}
function _setup_dovecot_quota
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up Dovecot quota'
2021-02-23 19:03:01 +00:00
# Dovecot quota is disabled when using LDAP or SMTP_ONLY or when explicitly disabled.
2022-08-22 06:31:32 +00:00
if [ [ ${ ACCOUNT_PROVISIONER } != 'FILE' ] ] || [ [ ${ SMTP_ONLY } -eq 1 ] ] || [ [ ${ ENABLE_QUOTAS } -eq 0 ] ]
2021-02-23 19:03:01 +00:00
then
# disable dovecot quota in docevot confs
if [ [ -f /etc/dovecot/conf.d/90-quota.conf ] ]
then
mv /etc/dovecot/conf.d/90-quota.conf /etc/dovecot/conf.d/90-quota.conf.disab
sed -i \
"s|mail_plugins = \$mail_plugins quota|mail_plugins = \$mail_plugins|g" \
/etc/dovecot/conf.d/10-mail.conf
sed -i \
"s|mail_plugins = \$mail_plugins imap_quota|mail_plugins = \$mail_plugins|g" \
/etc/dovecot/conf.d/20-imap.conf
fi
# disable quota policy check in postfix
sed -i "s|check_policy_service inet:localhost:65265||g" /etc/postfix/main.cf
else
if [ [ -f /etc/dovecot/conf.d/90-quota.conf.disab ] ]
then
mv /etc/dovecot/conf.d/90-quota.conf.disab /etc/dovecot/conf.d/90-quota.conf
sed -i \
"s|mail_plugins = \$mail_plugins|mail_plugins = \$mail_plugins quota|g" \
/etc/dovecot/conf.d/10-mail.conf
sed -i \
"s|mail_plugins = \$mail_plugin|mail_plugins = \$mail_plugins imap_quota|g" \
/etc/dovecot/conf.d/20-imap.conf
fi
local MESSAGE_SIZE_LIMIT_MB = $(( POSTFIX_MESSAGE_SIZE_LIMIT / 1000000 ))
local MAILBOX_LIMIT_MB = $(( POSTFIX_MAILBOX_SIZE_LIMIT / 1000000 ))
sed -i \
" s|quota_max_mail_size =.*|quota_max_mail_size = ${ MESSAGE_SIZE_LIMIT_MB } $( [ [ ${ MESSAGE_SIZE_LIMIT_MB } -eq 0 ] ] && echo "" || echo "M" ) |g " \
/etc/dovecot/conf.d/90-quota.conf
sed -i \
" s|quota_rule = \*:storage=.*|quota_rule = *:storage= ${ MAILBOX_LIMIT_MB } $( [ [ ${ MAILBOX_LIMIT_MB } -eq 0 ] ] && echo "" || echo "M" ) |g " \
/etc/dovecot/conf.d/90-quota.conf
2022-03-26 09:17:08 +00:00
if [ [ -d /tmp/docker-mailserver ] ] && [ [ ! -f /tmp/docker-mailserver/dovecot-quotas.cf ] ]
2021-02-23 19:03:01 +00:00
then
2022-03-21 06:07:52 +00:00
_log 'trace' "'/tmp/docker-mailserver/dovecot-quotas.cf' is not provided. Using default quotas."
2021-02-23 19:03:01 +00:00
: >/tmp/docker-mailserver/dovecot-quotas.cf
fi
# enable quota policy check in postfix
sed -i \
"s|reject_unknown_recipient_domain, reject_rbl_client zen.spamhaus.org|reject_unknown_recipient_domain, check_policy_service inet:localhost:65265, reject_rbl_client zen.spamhaus.org|g" \
/etc/postfix/main.cf
fi
}
function _setup_dovecot_local_user
{
2022-08-22 06:31:32 +00:00
[ [ ${ SMTP_ONLY } -eq 1 ] ] && return 0
[ [ ${ ACCOUNT_PROVISIONER } = = 'FILE' ] ] || return 0
2021-02-23 19:03:01 +00:00
2022-08-22 06:31:32 +00:00
_log 'debug' 'Setting up Dovecot Local User'
2021-02-23 19:03:01 +00:00
2021-11-20 20:33:49 +00:00
if [ [ ! -f /tmp/docker-mailserver/postfix-accounts.cf ] ]
then
2022-08-21 22:44:23 +00:00
_log 'trace' "No mail accounts to create - '/tmp/docker-mailserver/postfix-accounts.cf' is missing"
2021-02-23 19:03:01 +00:00
fi
2022-08-21 22:44:23 +00:00
function __wait_until_an_account_is_added_or_shutdown
{
local SLEEP_PERIOD = '10'
2022-04-18 08:48:48 +00:00
2022-08-21 22:44:23 +00:00
for ( ( COUNTER = 11 ; COUNTER >= 0 ; COUNTER-- ) )
do
if [ [ $( grep -cE '.+@.+\|' /tmp/docker-mailserver/postfix-accounts.cf 2>/dev/null || printf '%s' '0' ) -ge 1 ] ]
then
return 0
else
_log 'warn' " You need at least one mail account to start Dovecot ( $(( ( COUNTER + 1 ) * SLEEP_PERIOD )) s left for account creation before shutdown) "
sleep " ${ SLEEP_PERIOD } "
fi
done
_shutdown 'No accounts provided - Dovecot could not be started'
}
__wait_until_an_account_is_added_or_shutdown
_create_accounts
2021-02-23 19:03:01 +00:00
}
function _setup_ldap
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up LDAP'
_log 'trace' 'Checking for custom configs'
2021-02-23 19:03:01 +00:00
for i in 'users' 'groups' 'aliases' 'domains'
do
local FPATH = " /tmp/docker-mailserver/ldap- ${ i } .cf "
if [ [ -f ${ FPATH } ] ]
then
cp " ${ FPATH } " " /etc/postfix/ldap- ${ i } .cf "
fi
done
2022-03-21 06:07:52 +00:00
_log 'trace' 'Starting to override configs'
2021-02-23 19:03:01 +00:00
local FILES = (
/etc/postfix/ldap-users.cf
/etc/postfix/ldap-groups.cf
/etc/postfix/ldap-aliases.cf
/etc/postfix/ldap-domains.cf
2021-04-17 20:40:19 +00:00
/etc/postfix/ldap-senders.cf
2021-02-23 19:03:01 +00:00
/etc/postfix/maps/sender_login_maps.ldap
)
for FILE in " ${ FILES [@] } "
do
[ [ ${ FILE } = ~ ldap-user ] ] && export LDAP_QUERY_FILTER = " ${ LDAP_QUERY_FILTER_USER } "
[ [ ${ FILE } = ~ ldap-group ] ] && export LDAP_QUERY_FILTER = " ${ LDAP_QUERY_FILTER_GROUP } "
[ [ ${ FILE } = ~ ldap-aliases ] ] && export LDAP_QUERY_FILTER = " ${ LDAP_QUERY_FILTER_ALIAS } "
[ [ ${ FILE } = ~ ldap-domains ] ] && export LDAP_QUERY_FILTER = " ${ LDAP_QUERY_FILTER_DOMAIN } "
2021-04-17 20:40:19 +00:00
[ [ ${ FILE } = ~ ldap-senders ] ] && export LDAP_QUERY_FILTER = " ${ LDAP_QUERY_FILTER_SENDERS } "
2022-07-28 18:55:21 +00:00
_log debug " $( configomat.sh "LDAP_" " ${ FILE } " 2>& 1) "
2021-02-23 19:03:01 +00:00
done
2022-03-26 09:17:08 +00:00
_log 'trace' "Configuring Dovecot LDAP"
2021-02-23 19:03:01 +00:00
2021-04-19 07:02:03 +00:00
declare -A DOVECOT_LDAP_MAPPING
2021-02-23 19:03:01 +00:00
2022-03-26 09:17:08 +00:00
DOVECOT_LDAP_MAPPING[ 'DOVECOT_BASE' ] = " ${ DOVECOT_BASE : = " ${ LDAP_SEARCH_BASE } " } "
DOVECOT_LDAP_MAPPING[ 'DOVECOT_DN' ] = " ${ DOVECOT_DN : = " ${ LDAP_BIND_DN } " } "
DOVECOT_LDAP_MAPPING[ 'DOVECOT_DNPASS' ] = " ${ DOVECOT_DNPASS : = " ${ LDAP_BIND_PW } " } "
DOVECOT_LDAP_MAPPING[ 'DOVECOT_URIS' ] = " ${ DOVECOT_URIS : = " ${ DOVECOT_HOSTS : = " ${ LDAP_SERVER_HOST } " } " } "
2021-02-23 19:03:01 +00:00
2021-04-19 07:02:03 +00:00
# Add protocol to DOVECOT_URIS so that we can use dovecot's "uris" option:
# https://doc.dovecot.org/configuration_manual/authentication/ldap/
2021-12-21 16:01:40 +00:00
if [ [ ${ DOVECOT_LDAP_MAPPING [ "DOVECOT_URIS" ] } != *'://' * ] ]
2021-04-19 07:02:03 +00:00
then
2022-03-26 09:17:08 +00:00
DOVECOT_LDAP_MAPPING[ 'DOVECOT_URIS' ] = " ldap:// ${ DOVECOT_LDAP_MAPPING [ "DOVECOT_URIS" ] } "
2021-04-19 07:02:03 +00:00
fi
# Default DOVECOT_PASS_FILTER to the same value as DOVECOT_USER_FILTER
2022-03-26 09:17:08 +00:00
DOVECOT_LDAP_MAPPING[ 'DOVECOT_PASS_FILTER' ] = " ${ DOVECOT_PASS_FILTER : = " ${ DOVECOT_USER_FILTER } " } "
2021-02-23 19:03:01 +00:00
2021-04-19 07:02:03 +00:00
for VAR in " ${ !DOVECOT_LDAP_MAPPING[@] } "
2021-02-23 19:03:01 +00:00
do
2021-04-19 07:02:03 +00:00
export " ${ VAR } = ${ DOVECOT_LDAP_MAPPING [ ${ VAR } ] } "
2021-02-23 19:03:01 +00:00
done
2022-07-28 18:55:21 +00:00
_log debug " $( configomat.sh "DOVECOT_" "/etc/dovecot/dovecot-ldap.conf.ext" 2>& 1) "
2021-02-23 19:03:01 +00:00
2022-04-19 00:53:45 +00:00
_log 'trace' 'Enabling Dovecot LDAP authentication'
2021-02-23 19:03:01 +00:00
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
2022-03-21 06:07:52 +00:00
_log 'trace' "Configuring LDAP"
2021-02-23 19:03:01 +00:00
if [ [ -f /etc/postfix/ldap-users.cf ] ]
then
2022-08-29 11:26:44 +00:00
postconf 'virtual_mailbox_maps = ldap:/etc/postfix/ldap-users.cf'
2022-02-11 20:20:45 +00:00
else
2022-03-21 06:07:52 +00:00
_log 'warn' "'/etc/postfix/ldap-users.cf' not found"
2021-02-23 19:03:01 +00:00
fi
if [ [ -f /etc/postfix/ldap-domains.cf ] ]
then
2022-08-29 11:26:44 +00:00
postconf 'virtual_mailbox_domains = /etc/postfix/vhost, ldap:/etc/postfix/ldap-domains.cf'
2022-02-11 20:20:45 +00:00
else
2022-03-21 06:07:52 +00:00
_log 'warn' "'/etc/postfix/ldap-domains.cf' not found"
2021-02-23 19:03:01 +00:00
fi
if [ [ -f /etc/postfix/ldap-aliases.cf ] ] && [ [ -f /etc/postfix/ldap-groups.cf ] ]
then
2022-08-29 11:26:44 +00:00
postconf 'virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf, ldap:/etc/postfix/ldap-groups.cf'
2022-02-11 20:20:45 +00:00
else
2022-03-21 06:07:52 +00:00
_log 'warn' "'/etc/postfix/ldap-aliases.cf' and / or '/etc/postfix/ldap-groups.cf' not found"
2021-02-23 19:03:01 +00:00
fi
# shellcheck disable=SC2016
sed -i 's|mydestination = \$myhostname, |mydestination = |' /etc/postfix/main.cf
return 0
}
2022-08-22 06:31:32 +00:00
function _setup_oidc
{
_shutdown 'OIDC user account provisioning is not yet implemented'
}
2021-02-23 19:03:01 +00:00
function _setup_postgrey
{
2022-03-26 09:17:08 +00:00
_log 'debug' 'Configuring Postgrey'
2021-02-23 19:03:01 +00:00
2022-11-07 08:28:47 +00:00
sedfile -i -E \
's|(^smtpd_recipient_restrictions =.*)|\1, check_policy_service inet:127.0.0.1:10023|' \
2021-02-23 19:03:01 +00:00
/etc/postfix/main.cf
sed -i -e \
" s|\"--inet=127.0.0.1:10023\"|\"--inet=127.0.0.1:10023 --delay= ${ POSTGREY_DELAY } --max-age= ${ POSTGREY_MAX_AGE } --auto-whitelist-clients= ${ POSTGREY_AUTO_WHITELIST_CLIENTS } \"| " \
/etc/default/postgrey
2022-03-26 09:17:08 +00:00
TEXT_FOUND = $( grep -c -i 'POSTGREY_TEXT' /etc/default/postgrey)
2021-02-23 19:03:01 +00:00
if [ [ ${ TEXT_FOUND } -eq 0 ] ]
then
2022-03-26 09:17:08 +00:00
printf 'POSTGREY_TEXT=\"%s\"\n\n' " ${ POSTGREY_TEXT } " >>/etc/default/postgrey
2021-02-23 19:03:01 +00:00
fi
if [ [ -f /tmp/docker-mailserver/whitelist_clients.local ] ]
then
cp -f /tmp/docker-mailserver/whitelist_clients.local /etc/postgrey/whitelist_clients.local
fi
if [ [ -f /tmp/docker-mailserver/whitelist_recipients ] ]
then
cp -f /tmp/docker-mailserver/whitelist_recipients /etc/postgrey/whitelist_recipients
fi
}
function _setup_postfix_postscreen
{
2022-03-26 09:17:08 +00:00
_log 'debug' 'Configuring Postscreen'
2021-02-23 19:03:01 +00:00
sed -i \
-e " s|postscreen_dnsbl_action = enforce|postscreen_dnsbl_action = ${ POSTSCREEN_ACTION } | " \
-e " s|postscreen_greet_action = enforce|postscreen_greet_action = ${ POSTSCREEN_ACTION } | " \
-e " s|postscreen_bare_newline_action = enforce|postscreen_bare_newline_action = ${ POSTSCREEN_ACTION } | " /etc/postfix/main.cf
}
function _setup_postfix_sizelimits
{
2022-03-26 09:17:08 +00:00
_log 'trace' " Configuring Postfix message size limit to ' ${ POSTFIX_MESSAGE_SIZE_LIMIT } ' "
2022-08-29 11:26:44 +00:00
postconf " message_size_limit = ${ POSTFIX_MESSAGE_SIZE_LIMIT } "
2021-02-23 19:03:01 +00:00
2022-03-26 09:17:08 +00:00
_log 'trace' " Configuring Postfix mailbox size limit to ' ${ POSTFIX_MAILBOX_SIZE_LIMIT } ' "
2022-08-29 11:26:44 +00:00
postconf " mailbox_size_limit = ${ POSTFIX_MAILBOX_SIZE_LIMIT } "
2021-02-23 19:03:01 +00:00
2022-03-26 09:17:08 +00:00
_log 'trace' " Configuring Postfix virtual mailbox size limit to ' ${ POSTFIX_MAILBOX_SIZE_LIMIT } ' "
2022-08-29 11:26:44 +00:00
postconf " virtual_mailbox_limit = ${ POSTFIX_MAILBOX_SIZE_LIMIT } "
2021-02-23 19:03:01 +00:00
}
2022-03-03 15:17:01 +00:00
function _setup_clamav_sizelimit
{
2022-03-26 09:17:08 +00:00
_log 'trace' " Setting ClamAV message scan size limit to ' ${ CLAMAV_MESSAGE_SIZE_LIMIT } ' "
2022-03-03 15:17:01 +00:00
sedfile -i " s/^MaxFileSize.*/MaxFileSize ${ CLAMAV_MESSAGE_SIZE_LIMIT } / " /etc/clamav/clamd.conf
}
2021-02-23 19:03:01 +00:00
function _setup_postfix_smtputf8
{
2022-03-26 09:17:08 +00:00
_log 'trace' "Disabling Postfix's smtputf8 support"
2022-08-29 11:26:44 +00:00
postconf 'smtputf8_enable = no'
2021-02-23 19:03:01 +00:00
}
function _setup_spoof_protection
{
2022-03-26 09:17:08 +00:00
_log 'trace' 'Configuring spoof protection'
2021-02-23 19:03:01 +00:00
sed -i \
's|smtpd_sender_restrictions =|smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch,|' \
/etc/postfix/main.cf
2022-08-22 06:31:32 +00:00
if [ [ ${ ACCOUNT_PROVISIONER } = = 'LDAP' ] ]
2021-02-23 19:03:01 +00:00
then
2022-03-26 09:17:08 +00:00
if [ [ -z ${ LDAP_QUERY_FILTER_SENDERS } ] ]
then
2022-08-29 11:26:44 +00:00
postconf 'smtpd_sender_login_maps = ldap:/etc/postfix/ldap-users.cf ldap:/etc/postfix/ldap-aliases.cf ldap:/etc/postfix/ldap-groups.cf'
2021-04-17 20:40:19 +00:00
else
2022-08-29 11:26:44 +00:00
postconf 'smtpd_sender_login_maps = ldap:/etc/postfix/ldap-senders.cf'
2021-04-17 20:40:19 +00:00
fi
2021-02-23 19:03:01 +00:00
else
if [ [ -f /etc/postfix/regexp ] ]
then
2022-08-29 11:26:44 +00:00
postconf 'smtpd_sender_login_maps = unionmap:{ texthash:/etc/postfix/virtual, hash:/etc/aliases, pcre:/etc/postfix/maps/sender_login_maps.pcre, pcre:/etc/postfix/regexp }'
2021-02-23 19:03:01 +00:00
else
2022-08-29 11:26:44 +00:00
postconf 'smtpd_sender_login_maps = texthash:/etc/postfix/virtual, hash:/etc/aliases, pcre:/etc/postfix/maps/sender_login_maps.pcre'
2021-02-23 19:03:01 +00:00
fi
fi
}
function _setup_postfix_access_control
{
2022-03-21 06:07:52 +00:00
_log 'trace' 'Configuring user access'
2021-02-23 19:03:01 +00:00
if [ [ -f /tmp/docker-mailserver/postfix-send-access.cf ] ]
then
sed -i 's|smtpd_sender_restrictions =|smtpd_sender_restrictions = check_sender_access texthash:/tmp/docker-mailserver/postfix-send-access.cf,|' /etc/postfix/main.cf
fi
if [ [ -f /tmp/docker-mailserver/postfix-receive-access.cf ] ]
then
sed -i 's|smtpd_recipient_restrictions =|smtpd_recipient_restrictions = check_recipient_access texthash:/tmp/docker-mailserver/postfix-receive-access.cf,|' /etc/postfix/main.cf
fi
}
function _setup_postfix_sasl
{
if [ [ ${ ENABLE_SASLAUTHD } -eq 1 ] ] && [ [ ! -f /etc/postfix/sasl/smtpd.conf ] ]
then
cat >/etc/postfix/sasl/smtpd.conf << EOF
pwcheck_method: saslauthd
mech_list: plain login
EOF
fi
if [ [ ${ ENABLE_SASLAUTHD } -eq 0 ] ] && [ [ ${ SMTP_ONLY } -eq 1 ] ]
then
sed -i -E \
's|^smtpd_sasl_auth_enable =.*|smtpd_sasl_auth_enable = no|g' \
/etc/postfix/main.cf
sed -i -E \
's|^ -o smtpd_sasl_auth_enable=.*| -o smtpd_sasl_auth_enable=no|g' \
/etc/postfix/master.cf
fi
}
function _setup_saslauthd
{
2022-03-26 09:17:08 +00:00
_log 'debug' 'Setting up SASLAUTHD'
2021-02-23 19:03:01 +00:00
if [ [ ! -f /etc/saslauthd.conf ] ]
then
2022-03-21 06:07:52 +00:00
_log 'trace' 'Creating /etc/saslauthd.conf'
2021-02-23 19:03:01 +00:00
cat > /etc/saslauthd.conf << EOF
2021-05-22 20:52:56 +00:00
ldap_servers: ${ SASLAUTHD_LDAP_SERVER }
2021-02-23 19:03:01 +00:00
ldap_auth_method: ${ SASLAUTHD_LDAP_AUTH_METHOD }
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_start_tls: ${ SASLAUTHD_LDAP_START_TLS }
ldap_tls_check_peer: ${ SASLAUTHD_LDAP_TLS_CHECK_PEER }
${ SASLAUTHD_LDAP_TLS_CACERT_FILE }
${ SASLAUTHD_LDAP_TLS_CACERT_DIR }
${ SASLAUTHD_LDAP_PASSWORD_ATTR }
${ SASLAUTHD_LDAP_MECH }
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 "/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
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up Postfix aliases'
2021-11-20 20:33:49 +00:00
_create_aliases
2021-02-23 19:03:01 +00:00
}
function _setup_SRS
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up SRS'
2021-02-23 19:03:01 +00:00
2022-08-29 11:26:44 +00:00
postconf 'sender_canonical_maps = tcp:localhost:10001'
postconf " sender_canonical_classes = ${ SRS_SENDER_CLASSES } "
postconf 'recipient_canonical_maps = tcp:localhost:10002'
postconf 'recipient_canonical_classes = envelope_recipient,header_recipient'
2021-02-23 19:03:01 +00:00
}
function _setup_dkim
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up DKIM'
2021-02-23 19:03:01 +00:00
2021-02-24 09:12:20 +00:00
mkdir -p /etc/opendkim && touch /etc/opendkim/SigningTable
2021-02-23 19:03:01 +00:00
# check if any keys are available
if [ [ -e "/tmp/docker-mailserver/opendkim/KeyTable" ] ]
then
cp -a /tmp/docker-mailserver/opendkim/* /etc/opendkim/
2022-03-26 09:17:08 +00:00
_log 'trace' " DKIM keys added for: $( ls /etc/opendkim/keys/) "
_log 'trace' "Changing permissions on '/etc/opendkim'"
2021-02-23 19:03:01 +00:00
chown -R opendkim:opendkim /etc/opendkim/
chmod -R 0700 /etc/opendkim/keys/
else
2022-04-29 17:03:16 +00:00
_log 'debug' 'No DKIM key(s) provided - check the documentation on how to get your keys'
2022-03-26 09:17:08 +00:00
[ [ ! -f /etc/opendkim/KeyTable ] ] && touch /etc/opendkim/KeyTable
2021-02-23 19:03:01 +00:00
fi
2022-04-02 08:41:46 +00:00
# setup nameservers parameter from /etc/resolv.conf if not defined
2021-02-23 19:03:01 +00:00
if ! grep '^Nameservers' /etc/opendkim.conf
then
2022-03-26 09:17:08 +00:00
echo " Nameservers $( grep '^nameserver' /etc/resolv.conf | awk -F " " '{print $2}' | paste -sd ',' -) " >>/etc/opendkim.conf
2021-02-23 19:03:01 +00:00
2022-03-26 09:17:08 +00:00
_log 'trace' "Nameservers added to '/etc/opendkim.conf'"
2021-02-23 19:03:01 +00:00
fi
}
function _setup_postfix_vhost
{
2022-03-26 09:17:08 +00:00
_log 'debug' 'Setting up Postfix vhost'
2021-11-20 20:33:49 +00:00
_create_postfix_vhost
2021-02-23 19:03:01 +00:00
}
2022-01-05 23:53:18 +00:00
function _setup_postfix_inet_protocols
2021-02-23 19:03:01 +00:00
{
2022-03-21 06:07:52 +00:00
_log 'trace' 'Setting up POSTFIX_INET_PROTOCOLS option'
2022-08-29 11:26:44 +00:00
postconf " inet_protocols = ${ POSTFIX_INET_PROTOCOLS } "
2021-02-23 19:03:01 +00:00
}
2022-01-05 23:53:18 +00:00
function _setup_dovecot_inet_protocols
{
local PROTOCOL
2022-03-21 06:07:52 +00:00
_log 'trace' 'Setting up DOVECOT_INET_PROTOCOLS option'
2022-01-05 23:53:18 +00:00
# https://dovecot.org/doc/dovecot-example.conf
if [ [ ${ DOVECOT_INET_PROTOCOLS } = = "ipv4" ] ]
then
PROTOCOL = '*' # IPv4 only
elif [ [ ${ DOVECOT_INET_PROTOCOLS } = = "ipv6" ] ]
then
PROTOCOL = '[::]' # IPv6 only
else
# Unknown value, panic.
dms_panic__invalid_value 'DOVECOT_INET_PROTOCOLS' " ${ DOVECOT_INET_PROTOCOLS } "
fi
sedfile -i " s|^#listen =.*|listen = ${ PROTOCOL } |g " /etc/dovecot/dovecot.conf
}
2021-02-23 19:03:01 +00:00
function _setup_docker_permit
{
2022-03-26 09:17:08 +00:00
_log 'debug' 'Setting up PERMIT_DOCKER option'
2021-02-23 19:03:01 +00:00
local CONTAINER_IP CONTAINER_NETWORK
unset CONTAINER_NETWORKS
declare -a CONTAINER_NETWORKS
CONTAINER_IP = $( ip addr show " ${ NETWORK_INTERFACE } " | \
grep 'inet ' | sed 's|[^0-9\.\/]*||g' | cut -d '/' -f 1)
2022-05-05 08:28:38 +00:00
CONTAINER_NETWORK = $( echo " ${ CONTAINER_IP } " | cut -d '.' -f1-2) .0.0
2021-02-23 19:03:01 +00:00
2021-06-19 20:24:06 +00:00
if [ [ -z ${ CONTAINER_IP } ] ]
then
2022-03-26 09:17:08 +00:00
_log 'error' 'Detecting the container IP address failed'
fix: Remove `mkcert.sh` usage + `_setup_ssl` refactor. (#2196)
* chore(refactor): DRY up the `_setup_ssl` method
- `/etc/postfix/ssl` was a bit misleading in usage here. As a maintainer (of my own contribution!) I was confused why only `/etc/postfix/ssl` was referenced and not `/etc/dovecot/ssl`.
- The postfix specific path is unnecessary, dovecot was referencing it via it's config, the same can be done from postfix to a generic DMS specific config location instead.
- This location is defined and created early as `/etc/dms/tls` (with var `DMS_TLS_PATH`). All usage of `/etc/postfix/ssl` has been replaced, making it easier to grok. Several `mkdir` commands related to this have been dropped as a result.
- Likewise, a related `TMP_DMS_TLS_PATH` var provides a reference to the config volume path `/tmp/docker-mailserver` which is used for conditions on presently hard-coded paths.
- Other values that benefit from being DRY have been lifted up into vars. Definitely easier to follow now and makes some further opportunities clearer to tackle in a future refactor.
- `chmod` has been updated where appropriate. Public key/cert is acceptable to have as readable by non-root users (644). The custom type with single fullchain file was not root accessible only, but should as it contains a private key.
- That said, the security benefit can be a bit moot due to source files that were copied remain present, the user would be responsible to ensure similar permissions on their source files.
- I've not touched LetsEncrypt section as I don't have time to investigate into that yet (not familiar with that portion).
---
* chore: Remove mkcert logic and dovecot cert
- No longer serving a purpose.
- Our own TLS startup script handles a variety of cert scenarios, while the dropped code was always generating a self-signed cert and persisting an unused cert regardless with `ONE_DIR=1`.
- To avoid similar issues that DH params had with doveadm validating filepath values in the SSL config, the default dummy values match postfix pointing to "snakeoil" cert. That serves the same purpose as mkcert was covering in the image.
- Bonus, no more hassle with differing mkcert target paths for users replacing our supplied Dovecot with the latest community edition.
---
* Error handling for SSL_TYPE
- Added a panic utility to exit early when SSL_TYPE conditions are misconfigured.
- Some info text had order of key/cert occurrence swapped to be consistent with key then cert.
- Some existing comments moved and rephrased.
- Additional comments added.
- `-f` test for cert files instead of `-e` (true also for directories/devices/symlinks).
- _notify messages lifted out of conditionals so that they always output when the case is hit.
- ~~Empty SSL_TYPE collapsed into catch all panic, while it's contents is now mapped to a new 'disabled' value.~~
---
* Use sedfile + improve sed expressions + update case style
- Uses sedfile when appropriate (file change intentional, not optional match/check).
- sed expressions modified to be DRY and reduce escaping via `-r` flag (acceptable if actual text content contains no `?`,`+`,`()` or `{}` characters, [otherwise they must be escaped](https://www.gnu.org/software/sed/manual/html_node/Extended-regexps.html)).
- sed captures anything matched between the parenthesis`()` and inserts it via `\1` as part of the replacement.
- case statements adopt the `(` prefix, adopting recent shell style for consistency.
---
* Refactor SSL_TYPE=disabled
- Postfix is also disabled now.
- Included heavy inline documentation reference for maintainers.
- Dropped an obsolete postfix config option 'use_tls' on the relayhost function, it was replaced by 'security_level'.
---
* I'm a friggin' sed wizard now
- The `modern` TLS_LEVEL is the default values for the configs they modify. As such, `sedfile` outputs an "Error" which isn't an actual concern, back to regular `sed`.
- I realized that multiple edits for the same file can all be done at once via `-e` (assuming other sed options are the same for each operation), and that `g` suffix is global scope for single line match, not whole file (default as sed iterates through individual lines).
- Some postfix replacements have `smtp` and `smtpd` lines, collapsed into a single `smtpd?` instead now that I know sed better.
---
* tests(fix): Tests that require SSL/TLS to pass
- SSL_TYPE=snakeoil added as temporary workaround.
- nmap tests are being dropped. These were added about 4-5 years ago, I have since made these redundant with the `testssl.sh` tests.
- Additionally the `--link` option is deprecated and IIRC these grades were a bit misleading when I initially used nmap in my own TLS cipher suite update PRs in the past.
- The removed SSL test is already handled in mail_ssl_manual.bats
ldap test:
- Replace `--link` alias option with `--network` and alias assignment.
- Parameterized some values and added the `SSL_TYPE` to resolve the starttls test failure.
privacy test:
- Also needed `SSL_TYPE` to pass the starttls test.
`tests.bats` had another starttls test for imap:
- Workaround for now is to give the main test container `SSL_TYPE=snakeoil`.
---
* Remove the expired lets-encrypt cert
This expired in March 2021. It was originally required when first added back in 2016 as LetsEncrypt was fairly new and not as broadly accepted into OS trust stores.
No longer the case today.
---
* chore: Housekeeping
Not required for this PR branch, little bit of tidying up while working on these two test files.
- privacy test copied over content when extracted from `tests.bats` that isn't relevant.
- ldap test was not as easy to identify the source of DOVECOT_TLS. Added comment to make the prefix connection to `configomat.sh` and `.ext` files more easier to find.
- Additionally converted the two localhost FQDN to vars.
---
* Default SSL_TYPE becomes `''` (aka equivalent to desired `disabled` case)
- This is to prevent other tests from failing by hitting the panic catchall case.
- More ideal would be adjusting tests to default to `disabled`, rather than treating `disabled` as an empty / unset SSL_TYPE value.
---
* Add inline documentation for `dms_panic`
- This could later be better formatted and placed into contributor docs.
Panic with kill (shutdown) not exit (errex):
- `kill 1` from `_shutdown` will send SIGTERM signal to PID 1 (init process).
- `exit 1` within the `start-mailserver.sh` init scripts context, will just exit the initialization script leaving the container running when it shouldn't.
The two previous `_shutdown` methods can benefit from using `dms_panic` wrapper instead to standardize on panic messages.
2021-09-19 12:31:11 +00:00
dms_panic__misconfigured 'NETWORK_INTERFACE' 'Network Setup [docker_permit]'
2021-06-19 20:24:06 +00:00
fi
2021-02-23 19:03:01 +00:00
while read -r IP
do
CONTAINER_NETWORKS += ( " ${ IP } " )
done < <( ip -o -4 addr show type veth | grep -E -o '[0-9\.]+/[0-9]+' )
case " ${ PERMIT_DOCKER } " in
2022-03-17 10:24:30 +00:00
( 'none' )
2022-03-21 06:07:52 +00:00
_log 'trace' "Clearing Postfix's 'mynetworks'"
2022-08-29 11:26:44 +00:00
postconf "mynetworks ="
2022-02-09 09:25:09 +00:00
; ;
2022-03-17 10:24:30 +00:00
( 'connected-networks' )
2021-02-23 19:03:01 +00:00
for NETWORK in " ${ CONTAINER_NETWORKS [@] } "
do
NETWORK = $( _sanitize_ipv4_to_subnet_cidr " ${ NETWORK } " )
2022-03-26 09:17:08 +00:00
_log 'trace' " Adding Docker network ' ${ NETWORK } ' to Postfix's 'mynetworks' "
2022-08-29 11:26:44 +00:00
postconf " $( postconf | grep '^mynetworks =' ) ${ NETWORK } "
2021-02-23 19:03:01 +00:00
echo " ${ NETWORK } " >> /etc/opendmarc/ignore.hosts
echo " ${ NETWORK } " >> /etc/opendkim/TrustedHosts
done
; ;
2022-03-17 10:24:30 +00:00
( 'container' )
2022-03-21 06:07:52 +00:00
_log 'trace' "Adding container IP address to Postfix's 'mynetworks'"
2022-08-29 11:26:44 +00:00
postconf " $( postconf | grep '^mynetworks =' ) ${ CONTAINER_IP } /32 "
2021-02-23 19:03:01 +00:00
echo " ${ CONTAINER_IP } /32 " >> /etc/opendmarc/ignore.hosts
echo " ${ CONTAINER_IP } /32 " >> /etc/opendkim/TrustedHosts
; ;
2022-03-17 10:24:30 +00:00
( 'host' )
2022-03-26 09:17:08 +00:00
_log 'trace' " Adding ' ${ CONTAINER_NETWORK } /16' to Postfix's 'mynetworks' "
2022-08-29 11:26:44 +00:00
postconf " $( postconf | grep '^mynetworks =' ) ${ CONTAINER_NETWORK } /16 "
2022-03-02 15:03:40 +00:00
echo " ${ CONTAINER_NETWORK } /16 " >> /etc/opendmarc/ignore.hosts
echo " ${ CONTAINER_NETWORK } /16 " >> /etc/opendkim/TrustedHosts
; ;
2022-03-17 10:24:30 +00:00
( 'network' )
2022-03-26 09:17:08 +00:00
_log 'trace' "Adding Docker network to Postfix's 'mynetworks'"
2022-08-29 11:26:44 +00:00
postconf " $( postconf | grep '^mynetworks =' ) 172.16.0.0/12 "
2022-03-02 15:03:40 +00:00
echo 172.16.0.0/12 >> /etc/opendmarc/ignore.hosts
echo 172.16.0.0/12 >> /etc/opendkim/TrustedHosts
; ;
2022-03-17 10:24:30 +00:00
( * )
2022-03-26 09:17:08 +00:00
_log 'warn' " Invalid value for PERMIT_DOCKER: ' ${ PERMIT_DOCKER } ' "
_log 'warn' "Clearing Postfix's 'mynetworks'"
2022-08-29 11:26:44 +00:00
postconf "mynetworks ="
2022-03-02 15:03:40 +00:00
; ;
2021-02-23 19:03:01 +00:00
esac
}
fix: Remove `mkcert.sh` usage + `_setup_ssl` refactor. (#2196)
* chore(refactor): DRY up the `_setup_ssl` method
- `/etc/postfix/ssl` was a bit misleading in usage here. As a maintainer (of my own contribution!) I was confused why only `/etc/postfix/ssl` was referenced and not `/etc/dovecot/ssl`.
- The postfix specific path is unnecessary, dovecot was referencing it via it's config, the same can be done from postfix to a generic DMS specific config location instead.
- This location is defined and created early as `/etc/dms/tls` (with var `DMS_TLS_PATH`). All usage of `/etc/postfix/ssl` has been replaced, making it easier to grok. Several `mkdir` commands related to this have been dropped as a result.
- Likewise, a related `TMP_DMS_TLS_PATH` var provides a reference to the config volume path `/tmp/docker-mailserver` which is used for conditions on presently hard-coded paths.
- Other values that benefit from being DRY have been lifted up into vars. Definitely easier to follow now and makes some further opportunities clearer to tackle in a future refactor.
- `chmod` has been updated where appropriate. Public key/cert is acceptable to have as readable by non-root users (644). The custom type with single fullchain file was not root accessible only, but should as it contains a private key.
- That said, the security benefit can be a bit moot due to source files that were copied remain present, the user would be responsible to ensure similar permissions on their source files.
- I've not touched LetsEncrypt section as I don't have time to investigate into that yet (not familiar with that portion).
---
* chore: Remove mkcert logic and dovecot cert
- No longer serving a purpose.
- Our own TLS startup script handles a variety of cert scenarios, while the dropped code was always generating a self-signed cert and persisting an unused cert regardless with `ONE_DIR=1`.
- To avoid similar issues that DH params had with doveadm validating filepath values in the SSL config, the default dummy values match postfix pointing to "snakeoil" cert. That serves the same purpose as mkcert was covering in the image.
- Bonus, no more hassle with differing mkcert target paths for users replacing our supplied Dovecot with the latest community edition.
---
* Error handling for SSL_TYPE
- Added a panic utility to exit early when SSL_TYPE conditions are misconfigured.
- Some info text had order of key/cert occurrence swapped to be consistent with key then cert.
- Some existing comments moved and rephrased.
- Additional comments added.
- `-f` test for cert files instead of `-e` (true also for directories/devices/symlinks).
- _notify messages lifted out of conditionals so that they always output when the case is hit.
- ~~Empty SSL_TYPE collapsed into catch all panic, while it's contents is now mapped to a new 'disabled' value.~~
---
* Use sedfile + improve sed expressions + update case style
- Uses sedfile when appropriate (file change intentional, not optional match/check).
- sed expressions modified to be DRY and reduce escaping via `-r` flag (acceptable if actual text content contains no `?`,`+`,`()` or `{}` characters, [otherwise they must be escaped](https://www.gnu.org/software/sed/manual/html_node/Extended-regexps.html)).
- sed captures anything matched between the parenthesis`()` and inserts it via `\1` as part of the replacement.
- case statements adopt the `(` prefix, adopting recent shell style for consistency.
---
* Refactor SSL_TYPE=disabled
- Postfix is also disabled now.
- Included heavy inline documentation reference for maintainers.
- Dropped an obsolete postfix config option 'use_tls' on the relayhost function, it was replaced by 'security_level'.
---
* I'm a friggin' sed wizard now
- The `modern` TLS_LEVEL is the default values for the configs they modify. As such, `sedfile` outputs an "Error" which isn't an actual concern, back to regular `sed`.
- I realized that multiple edits for the same file can all be done at once via `-e` (assuming other sed options are the same for each operation), and that `g` suffix is global scope for single line match, not whole file (default as sed iterates through individual lines).
- Some postfix replacements have `smtp` and `smtpd` lines, collapsed into a single `smtpd?` instead now that I know sed better.
---
* tests(fix): Tests that require SSL/TLS to pass
- SSL_TYPE=snakeoil added as temporary workaround.
- nmap tests are being dropped. These were added about 4-5 years ago, I have since made these redundant with the `testssl.sh` tests.
- Additionally the `--link` option is deprecated and IIRC these grades were a bit misleading when I initially used nmap in my own TLS cipher suite update PRs in the past.
- The removed SSL test is already handled in mail_ssl_manual.bats
ldap test:
- Replace `--link` alias option with `--network` and alias assignment.
- Parameterized some values and added the `SSL_TYPE` to resolve the starttls test failure.
privacy test:
- Also needed `SSL_TYPE` to pass the starttls test.
`tests.bats` had another starttls test for imap:
- Workaround for now is to give the main test container `SSL_TYPE=snakeoil`.
---
* Remove the expired lets-encrypt cert
This expired in March 2021. It was originally required when first added back in 2016 as LetsEncrypt was fairly new and not as broadly accepted into OS trust stores.
No longer the case today.
---
* chore: Housekeeping
Not required for this PR branch, little bit of tidying up while working on these two test files.
- privacy test copied over content when extracted from `tests.bats` that isn't relevant.
- ldap test was not as easy to identify the source of DOVECOT_TLS. Added comment to make the prefix connection to `configomat.sh` and `.ext` files more easier to find.
- Additionally converted the two localhost FQDN to vars.
---
* Default SSL_TYPE becomes `''` (aka equivalent to desired `disabled` case)
- This is to prevent other tests from failing by hitting the panic catchall case.
- More ideal would be adjusting tests to default to `disabled`, rather than treating `disabled` as an empty / unset SSL_TYPE value.
---
* Add inline documentation for `dms_panic`
- This could later be better formatted and placed into contributor docs.
Panic with kill (shutdown) not exit (errex):
- `kill 1` from `_shutdown` will send SIGTERM signal to PID 1 (init process).
- `exit 1` within the `start-mailserver.sh` init scripts context, will just exit the initialization script leaving the container running when it shouldn't.
The two previous `_shutdown` methods can benefit from using `dms_panic` wrapper instead to standardize on panic messages.
2021-09-19 12:31:11 +00:00
# Requires ENABLE_POSTFIX_VIRTUAL_TRANSPORT=1
2021-02-23 19:03:01 +00:00
function _setup_postfix_virtual_transport
{
2022-03-21 06:07:52 +00:00
_log 'trace' 'Setting up Postfix virtual transport'
2021-02-23 19:03:01 +00:00
if [ [ -z ${ POSTFIX_DAGENT } ] ]
then
fix: Remove `mkcert.sh` usage + `_setup_ssl` refactor. (#2196)
* chore(refactor): DRY up the `_setup_ssl` method
- `/etc/postfix/ssl` was a bit misleading in usage here. As a maintainer (of my own contribution!) I was confused why only `/etc/postfix/ssl` was referenced and not `/etc/dovecot/ssl`.
- The postfix specific path is unnecessary, dovecot was referencing it via it's config, the same can be done from postfix to a generic DMS specific config location instead.
- This location is defined and created early as `/etc/dms/tls` (with var `DMS_TLS_PATH`). All usage of `/etc/postfix/ssl` has been replaced, making it easier to grok. Several `mkdir` commands related to this have been dropped as a result.
- Likewise, a related `TMP_DMS_TLS_PATH` var provides a reference to the config volume path `/tmp/docker-mailserver` which is used for conditions on presently hard-coded paths.
- Other values that benefit from being DRY have been lifted up into vars. Definitely easier to follow now and makes some further opportunities clearer to tackle in a future refactor.
- `chmod` has been updated where appropriate. Public key/cert is acceptable to have as readable by non-root users (644). The custom type with single fullchain file was not root accessible only, but should as it contains a private key.
- That said, the security benefit can be a bit moot due to source files that were copied remain present, the user would be responsible to ensure similar permissions on their source files.
- I've not touched LetsEncrypt section as I don't have time to investigate into that yet (not familiar with that portion).
---
* chore: Remove mkcert logic and dovecot cert
- No longer serving a purpose.
- Our own TLS startup script handles a variety of cert scenarios, while the dropped code was always generating a self-signed cert and persisting an unused cert regardless with `ONE_DIR=1`.
- To avoid similar issues that DH params had with doveadm validating filepath values in the SSL config, the default dummy values match postfix pointing to "snakeoil" cert. That serves the same purpose as mkcert was covering in the image.
- Bonus, no more hassle with differing mkcert target paths for users replacing our supplied Dovecot with the latest community edition.
---
* Error handling for SSL_TYPE
- Added a panic utility to exit early when SSL_TYPE conditions are misconfigured.
- Some info text had order of key/cert occurrence swapped to be consistent with key then cert.
- Some existing comments moved and rephrased.
- Additional comments added.
- `-f` test for cert files instead of `-e` (true also for directories/devices/symlinks).
- _notify messages lifted out of conditionals so that they always output when the case is hit.
- ~~Empty SSL_TYPE collapsed into catch all panic, while it's contents is now mapped to a new 'disabled' value.~~
---
* Use sedfile + improve sed expressions + update case style
- Uses sedfile when appropriate (file change intentional, not optional match/check).
- sed expressions modified to be DRY and reduce escaping via `-r` flag (acceptable if actual text content contains no `?`,`+`,`()` or `{}` characters, [otherwise they must be escaped](https://www.gnu.org/software/sed/manual/html_node/Extended-regexps.html)).
- sed captures anything matched between the parenthesis`()` and inserts it via `\1` as part of the replacement.
- case statements adopt the `(` prefix, adopting recent shell style for consistency.
---
* Refactor SSL_TYPE=disabled
- Postfix is also disabled now.
- Included heavy inline documentation reference for maintainers.
- Dropped an obsolete postfix config option 'use_tls' on the relayhost function, it was replaced by 'security_level'.
---
* I'm a friggin' sed wizard now
- The `modern` TLS_LEVEL is the default values for the configs they modify. As such, `sedfile` outputs an "Error" which isn't an actual concern, back to regular `sed`.
- I realized that multiple edits for the same file can all be done at once via `-e` (assuming other sed options are the same for each operation), and that `g` suffix is global scope for single line match, not whole file (default as sed iterates through individual lines).
- Some postfix replacements have `smtp` and `smtpd` lines, collapsed into a single `smtpd?` instead now that I know sed better.
---
* tests(fix): Tests that require SSL/TLS to pass
- SSL_TYPE=snakeoil added as temporary workaround.
- nmap tests are being dropped. These were added about 4-5 years ago, I have since made these redundant with the `testssl.sh` tests.
- Additionally the `--link` option is deprecated and IIRC these grades were a bit misleading when I initially used nmap in my own TLS cipher suite update PRs in the past.
- The removed SSL test is already handled in mail_ssl_manual.bats
ldap test:
- Replace `--link` alias option with `--network` and alias assignment.
- Parameterized some values and added the `SSL_TYPE` to resolve the starttls test failure.
privacy test:
- Also needed `SSL_TYPE` to pass the starttls test.
`tests.bats` had another starttls test for imap:
- Workaround for now is to give the main test container `SSL_TYPE=snakeoil`.
---
* Remove the expired lets-encrypt cert
This expired in March 2021. It was originally required when first added back in 2016 as LetsEncrypt was fairly new and not as broadly accepted into OS trust stores.
No longer the case today.
---
* chore: Housekeeping
Not required for this PR branch, little bit of tidying up while working on these two test files.
- privacy test copied over content when extracted from `tests.bats` that isn't relevant.
- ldap test was not as easy to identify the source of DOVECOT_TLS. Added comment to make the prefix connection to `configomat.sh` and `.ext` files more easier to find.
- Additionally converted the two localhost FQDN to vars.
---
* Default SSL_TYPE becomes `''` (aka equivalent to desired `disabled` case)
- This is to prevent other tests from failing by hitting the panic catchall case.
- More ideal would be adjusting tests to default to `disabled`, rather than treating `disabled` as an empty / unset SSL_TYPE value.
---
* Add inline documentation for `dms_panic`
- This could later be better formatted and placed into contributor docs.
Panic with kill (shutdown) not exit (errex):
- `kill 1` from `_shutdown` will send SIGTERM signal to PID 1 (init process).
- `exit 1` within the `start-mailserver.sh` init scripts context, will just exit the initialization script leaving the container running when it shouldn't.
The two previous `_shutdown` methods can benefit from using `dms_panic` wrapper instead to standardize on panic messages.
2021-09-19 12:31:11 +00:00
dms_panic__no_env 'POSTFIX_DAGENT' 'Postfix Setup [virtual_transport]'
2021-02-23 19:03:01 +00:00
return 1
fi
2022-08-29 11:26:44 +00:00
postconf " virtual_transport = ${ POSTFIX_DAGENT } "
2021-02-23 19:03:01 +00:00
}
function _setup_postfix_override_configuration
{
2022-06-06 07:30:10 +00:00
_log 'debug' 'Overriding / adjusting Postfix configuration with user-supplied values'
2021-02-23 19:03:01 +00:00
if [ [ -f /tmp/docker-mailserver/postfix-main.cf ] ]
then
2022-06-06 07:30:10 +00:00
cat /tmp/docker-mailserver/postfix-main.cf >>/etc/postfix/main.cf
# do not directly output to 'main.cf' as this causes a read-write-conflict
postconf -n >/tmp/postfix-main-new.cf 2>/dev/null
mv /tmp/postfix-main-new.cf /etc/postfix/main.cf
_log 'trace' "Adjusted '/etc/postfix/main.cf' according to '/tmp/docker-mailserver/postfix-main.cf'"
2021-02-23 19:03:01 +00:00
else
2022-03-26 09:17:08 +00:00
_log 'trace' "No extra Postfix settings loaded because optional '/tmp/docker-mailserver/postfix-main.cf' was not provided"
2021-02-23 19:03:01 +00:00
fi
if [ [ -f /tmp/docker-mailserver/postfix-master.cf ] ]
then
while read -r LINE
do
if [ [ ${ LINE } = ~ ^[ 0-9a-z] ] ]
then
postconf -P " ${ LINE } "
fi
done < /tmp/docker-mailserver/postfix-master.cf
2022-06-06 07:30:10 +00:00
_log 'trace' "Adjusted '/etc/postfix/master.cf' according to '/tmp/docker-mailserver/postfix-master.cf'"
2021-02-23 19:03:01 +00:00
else
2022-03-26 09:17:08 +00:00
_log 'trace' "No extra Postfix settings loaded because optional '/tmp/docker-mailserver/postfix-master.cf' was not provided"
2021-02-23 19:03:01 +00:00
fi
}
function _setup_postfix_relay_hosts
{
2021-11-20 20:33:49 +00:00
_setup_relayhost
2021-02-23 19:03:01 +00:00
}
function _setup_postfix_dhparam
{
2022-03-26 09:17:08 +00:00
_setup_dhparam 'Postfix' '/etc/postfix/dhparams.pem'
2021-02-23 19:03:01 +00:00
}
function _setup_dovecot_dhparam
{
2022-03-26 09:17:08 +00:00
_setup_dhparam 'Dovecot' '/etc/dovecot/dh.pem'
2021-09-15 08:28:04 +00:00
}
2021-02-23 19:03:01 +00:00
2021-09-15 08:28:04 +00:00
function _setup_dhparam
{
local DH_SERVICE = $1
local DH_DEST = $2
2022-03-26 09:17:08 +00:00
local DH_CUSTOM = '/tmp/docker-mailserver/dhparams.pem'
2021-02-23 19:03:01 +00:00
2022-03-21 06:07:52 +00:00
_log 'debug' " Setting up ${ DH_SERVICE } dhparam "
2021-02-23 19:03:01 +00:00
2021-09-15 08:28:04 +00:00
if [ [ -f ${ DH_CUSTOM } ] ]
then # use custom supplied dh params (assumes they're probably insecure)
2022-03-26 09:17:08 +00:00
_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 } ' "
2021-02-23 19:03:01 +00:00
2021-09-15 08:28:04 +00:00
cp -f " ${ DH_CUSTOM } " " ${ DH_DEST } "
else # use official standardized dh params (provided via Dockerfile)
2022-03-21 06:07:52 +00:00
_log 'trace' " ${ DH_SERVICE } will use official standardized DH parameters (ffdhe4096). "
2021-02-23 19:03:01 +00:00
fi
}
function _setup_security_stack
{
2022-03-26 09:17:08 +00:00
_log 'debug' 'Setting up Security Stack'
2021-02-23 19:03:01 +00:00
# recreate auto-generated file
local DMS_AMAVIS_FILE = /etc/amavis/conf.d/61-dms_auto_generated
echo "# WARNING: this file is auto-generated." >" ${ DMS_AMAVIS_FILE } "
echo "use strict;" >>" ${ DMS_AMAVIS_FILE } "
2021-03-28 20:07:52 +00:00
# SpamAssassin
2021-02-23 19:03:01 +00:00
if [ [ ${ ENABLE_SPAMASSASSIN } -eq 0 ] ]
then
2022-04-05 14:21:07 +00:00
_log 'debug' 'SpamAssassin is disabled'
2021-02-23 19:03:01 +00:00
echo "@bypass_spam_checks_maps = (1);" >>" ${ DMS_AMAVIS_FILE } "
elif [ [ ${ ENABLE_SPAMASSASSIN } -eq 1 ] ]
then
2022-04-05 14:21:07 +00:00
_log 'debug' 'Enabling and configuring SpamAssassin'
2021-02-23 19:03:01 +00:00
# shellcheck disable=SC2016
2021-11-02 10:51:36 +00:00
sed -i -r 's|^\$sa_tag_level_deflt (.*);|\$sa_tag_level_deflt = ' " ${ SA_TAG } " ';|g' /etc/amavis/conf.d/20-debian_defaults
2021-02-23 19:03:01 +00:00
# shellcheck disable=SC2016
2021-11-02 10:51:36 +00:00
sed -i -r 's|^\$sa_tag2_level_deflt (.*);|\$sa_tag2_level_deflt = ' " ${ SA_TAG2 } " ';|g' /etc/amavis/conf.d/20-debian_defaults
2021-02-23 19:03:01 +00:00
# shellcheck disable=SC2016
2021-11-02 10:51:36 +00:00
sed -i -r 's|^\$sa_kill_level_deflt (.*);|\$sa_kill_level_deflt = ' " ${ SA_KILL } " ';|g' /etc/amavis/conf.d/20-debian_defaults
2021-02-23 19:03:01 +00:00
2022-03-26 09:17:08 +00:00
if [ [ ${ SA_SPAM_SUBJECT } = = 'undef' ] ]
2021-02-23 19:03:01 +00:00
then
# shellcheck disable=SC2016
sed -i -r 's|^\$sa_spam_subject_tag (.*);|\$sa_spam_subject_tag = undef;|g' /etc/amavis/conf.d/20-debian_defaults
else
# shellcheck disable=SC2016
sed -i -r 's|^\$sa_spam_subject_tag (.*);|\$sa_spam_subject_tag = ' " ' ${ SA_SPAM_SUBJECT } ' " ';|g' /etc/amavis/conf.d/20-debian_defaults
fi
# activate short circuits when SA BAYES is certain it has spam or ham.
if [ [ ${ SA_SHORTCIRCUIT_BAYES_SPAM } -eq 1 ] ]
then
# automatically activate the Shortcircuit Plugin
sed -i -r 's|^# loadplugin Mail::SpamAssassin::Plugin::Shortcircuit|loadplugin Mail::SpamAssassin::Plugin::Shortcircuit|g' /etc/spamassassin/v320.pre
sed -i -r 's|^# shortcircuit BAYES_99|shortcircuit BAYES_99|g' /etc/spamassassin/local.cf
fi
if [ [ ${ SA_SHORTCIRCUIT_BAYES_HAM } -eq 1 ] ]
then
# automatically activate the Shortcircuit Plugin
sed -i -r 's|^# loadplugin Mail::SpamAssassin::Plugin::Shortcircuit|loadplugin Mail::SpamAssassin::Plugin::Shortcircuit|g' /etc/spamassassin/v320.pre
sed -i -r 's|^# shortcircuit BAYES_00|shortcircuit BAYES_00|g' /etc/spamassassin/local.cf
fi
if [ [ -e /tmp/docker-mailserver/spamassassin-rules.cf ] ]
then
cp /tmp/docker-mailserver/spamassassin-rules.cf /etc/spamassassin/
fi
if [ [ ${ SPAMASSASSIN_SPAM_TO_INBOX } -eq 1 ] ]
then
2022-03-21 06:07:52 +00:00
_log 'trace' 'Configuring Spamassassin/Amavis to send SPAM to inbox'
2021-02-23 19:03:01 +00:00
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
2022-03-21 06:07:52 +00:00
_log 'trace' 'Configuring Spamassassin/Amavis to bounce SPAM'
2021-09-20 07:35:03 +00:00
2021-02-23 19:03:01 +00:00
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
fi
2022-02-21 09:48:28 +00:00
if [ [ ${ ENABLE_SPAMASSASSIN_KAM } -eq 1 ] ]
then
2022-03-21 06:07:52 +00:00
_log 'trace' 'Configuring Spamassassin KAM'
2022-02-21 09:48:28 +00:00
local SPAMASSASSIN_KAM_CRON_FILE = /etc/cron.daily/spamassassin_kam
sa-update --import /etc/spamassassin/kam/kam.sa-channels.mcgrail.com.key
2022-03-17 10:24:30 +00:00
2022-02-21 09:48:28 +00:00
cat >" ${ SPAMASSASSIN_KAM_CRON_FILE } " <<"EOM"
2022-10-17 08:40:09 +00:00
#!/bin/bash
2022-02-21 09:48:28 +00:00
2022-05-05 08:28:38 +00:00
RESULT = $( sa-update --gpgkey 24C063D8 --channel kam.sa-channels.mcgrail.com 2>& 1)
2022-03-17 10:24:30 +00:00
EXIT_CODE = ${ ? }
# see https://spamassassin.apache.org/full/3.1.x/doc/sa-update.html#exit_codes
if [ [ ${ EXIT_CODE } -ge 4 ] ]
then
echo -e " Updating SpamAssassin KAM failed:\n ${ RESULT } \n " >& 2
exit 1
fi
exit 0
2022-02-21 09:48:28 +00:00
EOM
chmod +x " ${ SPAMASSASSIN_KAM_CRON_FILE } "
fi
2021-02-23 19:03:01 +00:00
fi
2022-03-03 15:17:01 +00:00
# ClamAV
2021-02-23 19:03:01 +00:00
if [ [ ${ ENABLE_CLAMAV } -eq 0 ] ]
then
2022-04-05 14:21:07 +00:00
_log 'debug' 'ClamAV is disabled'
2021-02-23 19:03:01 +00:00
echo '@bypass_virus_checks_maps = (1);' >>" ${ DMS_AMAVIS_FILE } "
elif [ [ ${ ENABLE_CLAMAV } -eq 1 ] ]
then
2022-03-21 06:07:52 +00:00
_log 'debug' 'Enabling ClamAV'
2021-02-23 19:03:01 +00:00
fi
echo '1; # ensure a defined return' >>" ${ DMS_AMAVIS_FILE } "
chmod 444 " ${ DMS_AMAVIS_FILE } "
# Fail2ban
if [ [ ${ ENABLE_FAIL2BAN } -eq 1 ] ]
then
2022-03-21 06:07:52 +00:00
_log 'debug' 'Enabling Fail2Ban'
2021-02-23 19:03:01 +00:00
if [ [ -e /tmp/docker-mailserver/fail2ban-fail2ban.cf ] ]
then
cp /tmp/docker-mailserver/fail2ban-fail2ban.cf /etc/fail2ban/fail2ban.local
fi
if [ [ -e /tmp/docker-mailserver/fail2ban-jail.cf ] ]
then
2021-04-11 15:33:39 +00:00
cp /tmp/docker-mailserver/fail2ban-jail.cf /etc/fail2ban/jail.d/user-jail.local
2021-02-23 19:03:01 +00:00
fi
else
# disable logrotate config for fail2ban if not enabled
rm -f /etc/logrotate.d/fail2ban
fi
# fix cron.daily for spamassassin
2022-03-17 10:24:30 +00:00
sed -i \
's|invoke-rc.d spamassassin reload|/etc/init\.d/spamassassin reload|g' \
/etc/cron.daily/spamassassin
2021-02-23 19:03:01 +00:00
2021-03-28 13:37:48 +00:00
# Amavis
if [ [ ${ ENABLE_AMAVIS } -eq 1 ] ]
2021-02-23 19:03:01 +00:00
then
2022-03-21 06:07:52 +00:00
_log 'debug' 'Enabling Amavis'
2021-03-28 13:37:48 +00:00
if [ [ -f /tmp/docker-mailserver/amavis.cf ] ]
then
cp /tmp/docker-mailserver/amavis.cf /etc/amavis/conf.d/50-user
fi
2021-05-06 21:51:45 +00:00
sed -i -E \
" s|(log_level).*|\1 = ${ AMAVIS_LOGLEVEL } ;|g " \
/etc/amavis/conf.d/49-docker-mailserver
2021-02-23 19:03:01 +00:00
fi
}
function _setup_logrotate
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up logrotate'
2021-02-23 19:03:01 +00:00
LOGROTATE = '/var/log/mail/mail.log\n{\n compress\n copytruncate\n delaycompress\n'
case " ${ LOGROTATE_INTERVAL } " in
2022-03-17 10:24:30 +00:00
( 'daily' )
2022-03-21 06:07:52 +00:00
_log 'trace' 'Setting postfix logrotate interval to daily'
2021-02-23 19:03:01 +00:00
LOGROTATE = " ${ LOGROTATE } rotate 4\n daily\n "
; ;
2022-03-17 10:24:30 +00:00
( 'weekly' )
2022-03-21 06:07:52 +00:00
_log 'trace' 'Setting postfix logrotate interval to weekly'
2021-02-23 19:03:01 +00:00
LOGROTATE = " ${ LOGROTATE } rotate 4\n weekly\n "
; ;
2022-03-17 10:24:30 +00:00
( 'monthly' )
2022-03-21 06:07:52 +00:00
_log 'trace' 'Setting postfix logrotate interval to monthly'
2021-02-23 19:03:01 +00:00
LOGROTATE = " ${ LOGROTATE } rotate 4\n monthly\n "
; ;
2022-03-17 10:24:30 +00:00
( * )
2022-03-21 06:07:52 +00:00
_log 'warn' 'LOGROTATE_INTERVAL not found in _setup_logrotate'
2021-02-23 19:03:01 +00:00
; ;
esac
echo -e " ${ LOGROTATE } } " >/etc/logrotate.d/maillog
}
function _setup_mail_summary
{
2022-03-26 09:17:08 +00:00
local ENABLED_MESSAGE
ENABLED_MESSAGE = " Enabling Postfix log summary reports with recipient ' ${ PFLOGSUMM_RECIPIENT } ' "
2021-02-23 19:03:01 +00:00
case " ${ PFLOGSUMM_TRIGGER } " in
2022-03-17 10:24:30 +00:00
( 'daily_cron' )
2022-03-26 09:17:08 +00:00
_log 'debug' " ${ ENABLED_MESSAGE } "
2022-03-21 06:07:52 +00:00
_log 'trace' 'Creating daily cron job for pflogsumm report'
2021-02-23 19:03:01 +00:00
2022-03-17 10:24:30 +00:00
cat >/etc/cron.daily/postfix-summary << EOM
2022-10-17 08:40:09 +00:00
#!/bin/bash
2022-03-17 10:24:30 +00:00
/usr/local/bin/report-pflogsumm-yesterday ${ HOSTNAME } ${ PFLOGSUMM_RECIPIENT } ${ PFLOGSUMM_SENDER }
EOM
2021-02-23 19:03:01 +00:00
chmod +x /etc/cron.daily/postfix-summary
; ;
2022-03-17 10:24:30 +00:00
( 'logrotate' )
2022-03-26 09:17:08 +00:00
_log 'debug' " ${ ENABLED_MESSAGE } "
2022-03-21 06:07:52 +00:00
_log 'trace' 'Add postrotate action for pflogsumm report'
2021-02-23 19:03:01 +00:00
sed -i \
" s|}| postrotate\n /usr/local/bin/postfix-summary ${ HOSTNAME } ${ PFLOGSUMM_RECIPIENT } ${ PFLOGSUMM_SENDER } \n endscript\n}\n| " \
/etc/logrotate.d/maillog
; ;
2022-03-17 10:24:30 +00:00
( 'none' )
2022-03-26 09:17:08 +00:00
_log 'debug' 'Postfix log summary reports disabled'
2021-02-23 19:03:01 +00:00
; ;
2022-03-17 10:24:30 +00:00
( * )
2022-03-26 09:17:08 +00:00
_log 'warn' " Invalid value for PFLOGSUMM_TRIGGER: ' ${ PFLOGSUMM_TRIGGER } ' "
2021-02-23 19:03:01 +00:00
; ;
esac
}
function _setup_logwatch
{
echo 'LogFile = /var/log/mail/freshclam.log' >>/etc/logwatch/conf/logfiles/clam-update.conf
2022-03-17 10:24:30 +00:00
echo " MailFrom = ${ LOGWATCH_SENDER } " >>/etc/logwatch/conf/logwatch.conf
2022-01-10 11:29:11 +00:00
2021-02-23 19:03:01 +00:00
case " ${ LOGWATCH_INTERVAL } " in
2022-03-17 10:24:30 +00:00
( 'daily' | 'weekly' )
2022-03-26 09:17:08 +00:00
_log 'debug' " Enabling logwatch reports with recipient ' ${ LOGWATCH_RECIPIENT } ' "
2022-03-21 06:07:52 +00:00
_log 'trace' " Creating ${ LOGWATCH_INTERVAL } cron job for logwatch reports "
2021-02-23 19:03:01 +00:00
2022-03-17 10:24:30 +00:00
local LOGWATCH_FILE INTERVAL
LOGWATCH_FILE = " /etc/cron. ${ LOGWATCH_INTERVAL } /logwatch "
INTERVAL = '--range Yesterday'
if [ [ ${ LOGWATCH_INTERVAL } = = 'weekly' ] ]
then
INTERVAL = "--range 'between -7 days and -1 days'"
fi
cat >" ${ LOGWATCH_FILE } " << EOM
2022-10-17 08:40:09 +00:00
#!/bin/bash
2022-03-17 10:24:30 +00:00
/usr/sbin/logwatch ${ INTERVAL } --hostname ${ HOSTNAME } --mailto ${ LOGWATCH_RECIPIENT }
EOM
chmod 744 " ${ LOGWATCH_FILE } "
2021-02-23 19:03:01 +00:00
; ;
2022-03-17 10:24:30 +00:00
( 'none' )
2022-03-26 09:17:08 +00:00
_log 'debug' 'Logwatch reports disabled.'
2021-02-23 19:03:01 +00:00
; ;
2022-03-17 10:24:30 +00:00
( * )
2022-03-26 09:17:08 +00:00
_log 'warn' " Invalid value for LOGWATCH_INTERVAL: ' ${ LOGWATCH_INTERVAL } ' "
2021-02-23 19:03:01 +00:00
; ;
esac
}
function _setup_user_patches
{
2022-03-26 09:17:08 +00:00
local USER_PATCHES = '/tmp/docker-mailserver/user-patches.sh'
2021-02-23 19:03:01 +00:00
if [ [ -f ${ USER_PATCHES } ] ]
then
2022-03-26 09:17:08 +00:00
_log 'debug' 'Applying user patches'
2021-11-20 09:38:40 +00:00
/bin/bash " ${ USER_PATCHES } "
2021-02-23 19:03:01 +00:00
else
2022-03-26 09:17:08 +00:00
_log 'trace' " No optional ' ${ USER_PATCHES } ' provided "
2021-02-23 19:03:01 +00:00
fi
}
2021-04-18 10:55:43 +00:00
function _setup_fail2ban
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Setting up Fail2Ban'
2022-04-19 08:44:51 +00:00
2022-03-26 09:17:08 +00:00
if [ [ ${ FAIL2BAN_BLOCKTYPE } != 'reject' ] ]
2021-04-18 10:55:43 +00:00
then
2022-04-05 13:13:59 +00:00
echo -e '[Init]\nblocktype = drop' >/etc/fail2ban/action.d/nftables-common.local
2021-04-18 10:55:43 +00:00
fi
2022-04-19 08:44:51 +00:00
echo '[Definition]' >/etc/fail2ban/filter.d/custom.conf
2021-04-18 10:55:43 +00:00
}
2022-01-03 21:03:46 +00:00
function _setup_dnsbl_disable
{
2022-03-21 06:07:52 +00:00
_log 'debug' 'Disabling postfix DNS block list (zen.spamhaus.org)'
2022-03-17 10:24:30 +00:00
sedfile -i \
2022-11-07 08:28:47 +00:00
'/^smtpd_recipient_restrictions = / s/, reject_rbl_client zen.spamhaus.org=127.0.0.\[2..11\]//' \
2022-03-17 10:24:30 +00:00
/etc/postfix/main.cf
2022-01-03 21:03:46 +00:00
2022-03-21 06:07:52 +00:00
_log 'debug' 'Disabling postscreen DNS block lists'
2022-08-29 11:26:44 +00:00
postconf 'postscreen_dnsbl_action = ignore'
postconf 'postscreen_dnsbl_sites = '
2022-01-03 21:03:46 +00:00
}
2022-03-27 07:43:39 +00:00
function _setup_fetchmail
{
_log 'trace' 'Preparing Fetchmail configuration'
local CONFIGURATION FETCHMAILRC
CONFIGURATION = '/tmp/docker-mailserver/fetchmail.cf'
FETCHMAILRC = '/etc/fetchmailrc'
if [ [ -f ${ CONFIGURATION } ] ]
then
cat /etc/fetchmailrc_general " ${ CONFIGURATION } " >" ${ FETCHMAILRC } "
else
cat /etc/fetchmailrc_general >" ${ FETCHMAILRC } "
fi
chmod 700 " ${ FETCHMAILRC } "
chown fetchmail:root " ${ FETCHMAILRC } "
}
function _setup_fetchmail_parallel
{
_log 'trace' 'Setting up Fetchmail parallel'
mkdir /etc/fetchmailrc.d/
# Split the content of /etc/fetchmailrc into
# smaller fetchmailrc files per server [poll] entries. Each
# separate fetchmailrc file is stored in /etc/fetchmailrc.d
#
# The sole purpose for this is to work around what is known
# as the Fetchmail IMAP idle issue.
function _fetchmailrc_split
{
local FETCHMAILRC = '/etc/fetchmailrc'
local FETCHMAILRCD = '/etc/fetchmailrc.d'
local DEFAULT_FILE = " ${ FETCHMAILRCD } /defaults "
if [ [ ! -r ${ FETCHMAILRC } ] ]
then
_log 'warn' " File ' ${ FETCHMAILRC } ' not found "
return 1
fi
if [ [ ! -d ${ FETCHMAILRCD } ] ]
then
if ! mkdir " ${ FETCHMAILRCD } "
then
_log 'warn' " Unable to create folder ' ${ FETCHMAILRCD } ' "
return 1
fi
fi
local COUNTER = 0 SERVER = 0
while read -r LINE
do
if [ [ ${ LINE } = ~ poll ] ]
then
# If we read "poll" then we reached a new server definition
# We need to create a new file with fetchmail defaults from
# /etc/fetcmailrc
COUNTER = $(( COUNTER + 1 ))
SERVER = 1
cat " ${ DEFAULT_FILE } " >" ${ FETCHMAILRCD } /fetchmail- ${ COUNTER } .rc "
echo " ${ LINE } " >>" ${ FETCHMAILRCD } /fetchmail- ${ COUNTER } .rc "
elif [ [ ${ SERVER } -eq 0 ] ]
then
# We have not yet found "poll". Let's assume we are still reading
# the default settings from /etc/fetchmailrc file
echo " ${ LINE } " >>" ${ DEFAULT_FILE } "
else
# Just the server settings that need to be added to the specific rc.d file
echo " ${ LINE } " >>" ${ FETCHMAILRCD } /fetchmail- ${ COUNTER } .rc "
fi
2022-06-06 13:07:30 +00:00
done < <( _get_valid_lines_from_file " ${ FETCHMAILRC } " )
2022-03-27 07:43:39 +00:00
rm " ${ DEFAULT_FILE } "
}
_fetchmailrc_split
local COUNTER = 0
for RC in /etc/fetchmailrc.d/fetchmail-*.rc
do
COUNTER = $(( COUNTER + 1 ))
cat >" /etc/supervisor/conf.d/fetchmail- ${ COUNTER } .conf " << EOF
[ program:fetchmail-${ COUNTER } ]
startsecs = 0
autostart = false
autorestart = true
stdout_logfile = /var/log/supervisor/%( program_name) s.log
stderr_logfile = /var/log/supervisor/%( program_name) s.log
user = fetchmail
command = /usr/bin/fetchmail -f ${ RC } -v --nodetach --daemon %( ENV_FETCHMAIL_POLL) s -i /var/lib/fetchmail/.fetchmail-UIDL-cache --pidfile /var/run/fetchmail/%( program_name) s.pid
EOF
chmod 700 " ${ RC } "
chown fetchmail:root " ${ RC } "
done
supervisorctl reread
supervisorctl update
}
2022-04-06 14:48:41 +00:00
function _setup_timezone
{
2022-08-22 06:31:32 +00:00
[ [ -n ${ TZ } ] ] || return 0
2022-04-06 14:48:41 +00:00
_log 'debug' " Setting timezone to ' ${ TZ } ' "
local ZONEINFO_FILE = " /usr/share/zoneinfo/ ${ TZ } "
if [ [ ! -e ${ ZONEINFO_FILE } ] ]
then
_log 'warn' " Cannot find timezone ' ${ TZ } ' "
return 1
fi
if ln -fs " ${ ZONEINFO_FILE } " /etc/localtime \
&& dpkg-reconfigure -f noninteractive tzdata & >/dev/null
then
_log 'trace' " Set time zone to ' ${ TZ } ' "
else
_log 'warn' " Setting timezone to ' ${ TZ } ' failed "
return 1
fi
}