#!/bin/bash fail() { echo "FAIL: ${*}" >&2 exit 1 } # clamav needs access to read the spool files from amavis if ! usermod -a -G amavis clamav; then fail "usermod -a -G amavis clamav" fi # postfix needs access to the opendkim socket if ! usermod -a -G opendkim postfix; then fail "usermod -a -G opendkim postfix" fi # clamd couldn't access amavis/tmp if ! chmod g+rx /var/lib/amavis/tmp; then fail "chmod g+rx /var/lib/amavis/tmp" fi # directory is not being created by /etc/init.d/opendkim for dir in opendkim ilter-greylist; do if [[ ! -d "/var/spool/${dir}" ]]; then if ! mkdir -p "/var/spool/postfix/${dir}"; then fail "mkdir -p /var/spool/postfix/${dir}" fi fi done if ! chown opendkim:opendkim /var/spool/postfix/opendkim; then fail "chown opendkim:opendkim /var/spool/postfix/opendkim" fi # opendkim needs to read its private data if ! chown -R opendkim:root /etc/opendkim-private; then fail "chown -R opendkim:root /etc/opendkim-private" fi if ! chown root:root /var/log; then fail "chown root:root /var/log" fi for log in syslog "mail.*" "dovecot*.log" auth.log; do if ! touch "/var/log/${log}"; then fail "touch /var/log/${log}" fi if ! chmod a+rwX "/var/log/${log}"; then fail "chmod a+rwX /var/log/${log}" fi done if [[ -e /run/rsyslogd.pid ]]; then if ! rm /run/rsyslogd.pid; then fail "rm /run/rsyslogd.pid" fi fi if [[ -e /var/run/dovecot/master.pid ]]; then if ! rm /var/run/dovecot/master.pid; then fail "rm /var/run/dovecot/master.pid" fi fi # Set opendkim.sock ownership and permissions find /var/log -name 'dovecot*' | while read -r file; do if ! chown dovecot:postfix "${file}"; then fail "chown dovecot:postfix ${file}" fi if ! chmod g+rwX "${file}"; then fail "chmod g+rwX ${file}" fi done if false; then # host accounts into the container PAM files for file in passwd group shadow gshadow; do cp "/etc/${file}" "/etc/${file}.container" while IFS= read -r account; do id="${account%%:*}" id="${account%%:*}" if ! grep -q "^${id}:" "/etc/${file}"; then echo "${account}" >> "/etc/${file}" fi done < "/etc/system${file}" done sed -i -E 's,(passwd|group|shadow|gshadow):.*files$,\1: files [NOTFOUND=return] system\1: files,g' /etc/nsswitch.conf else # use ldap if ! sed -i -E 's#^base dc=example.*#base dc=ketrenos,dc=net#g' /etc/ldap.conf; then fail "sed 1" fi if ! sed -i -E 's#^uri ldap.*#uri ldap://192.168.1.78/#g' /etc/ldap.conf; then fail "sed 2" fi if ! sed -i -E 's#(passwd|group|shadow|gshadow):.*files$#\1: files ldap#g' /etc/nsswitch.conf; then fail "sed 3" fi fi update_keys() { echo "Key rotation on ${1}" if [[ "${2}" -ne 0 ]]; then echo "Restarting postfix and dovecot." /etc/init.d/dovecot restart /etc/init.d/postfix restart fi } update_map() { echo "Map update ${1}." postmap "${1}" if [[ "${2}" -ne 0 ]]; then echo "Restarting postfix." /etc/init.d/postfix reload fi } update_alias() { echo "Alias update ${1}." postalias "${1}" if [[ "${2}" -ne 0 ]]; then echo "Restarting postfix." /etc/init.d/postfix reload fi } declare -a watches=( "/etc/letsencrypt/archive:update_keys" "/etc/postfix/sender_checks:update_map" "/etc/postfix/sender_restrictions:update_map" "/etc/postfix/recipient_restrictions:update_map" "/opt/mailman/postfix_lmtp:update_map" "/etc/postfix/aliases:update_alias" ) # # Update postfix DBs called out in watches # for entry in "${watches[@]}"; do file=${entry%%:*} fn="${entry##*:}" if [[ "${fn}" =~ update_ ]]; then ${fn} "${file}" 0 fi done while true; do /usr/sbin/rsyslogd -n echo "rsyslogd died: $?" sleep 5 done & /etc/init.d/opendkim start #while true; do # /usr/sbin/opendkim -x /etc/opendkim.conf -f # echo "opendkim died: $?" # sleep 5 #done & /etc/init.d/dovecot start #while true; do # /usr/sbin/dovecot -F # echo "dovecot died: $?" # sleep 5 #done & # greylist.conf is installed into /etc/milter-greylist, however # /etc/init.d/milter-greylist uses the default, which looks in # /etc/mail/greylist.conf if [[ -e /etc/mail/greylist.conf ]]; then rm /etc/mail/greylist.conf fi ln -s ../milter-greylist/greylist.conf /etc/mail/greylist.conf while true; do /usr/sbin/milter-greylist -D -P /var/run/greylist.pid -u postfix -p /var/spool/postfix/milter-greylist/milter-greylist.sock echo "milter-greylist died: $?" sleep 5 done & /etc/init.d/amavis start #while true; do # /usr/sbin/amavisd-new foreground # echo "amavisd-new died: $?" # sleep 5 #done & #while true; do # /usr/bin/python /usr/lib/mailman/bin/mailmanctl -s start # echo "mailmain died: $?" # sleep 5 #done & /etc/init.d/clamav-daemon start #while true; do # /usr/sbin/clamd --foreground=true # echo "clamd died: $?" # sleep 5 #done & /etc/init.d/clamav-freshclam start #while true; do # /usr/bin/freshclam -d --foreground=true # echo "freshclam died: $?" # sleep 5 #done & /etc/init.d/spamassassin start #while true; do # /usr/bin/perl -T -w /usr/sbin/spamd --pidfile=/var/run/spamd.pid --create-prefs --max-children 5 --helper-home-dir --ipv4-only # echo "spamd died: $?" # sleep 5 #done & /etc/init.d/postfix start #while true; do # /usr/sbin/postfix start-fg # echo "postfix died: $?" # sleep 5 #done & # # Watch for letsencrypt and various config changes, taking appropriate # actions when the files changed. # declare -a watch_files=() for entry in "${watches[@]}"; do file=${entry%%:*} watch_files=("${watch_files[@]}" "${file}") done while true; do inotifywait -e modify "${watch_files[@]}" | while read -r changed_file status; do for entry in "${watches[@]}"; do file=${entry%%:*} if [[ "${changed_file}" == "${file}" ]]; then fn="${entry##*:}" ${fn} "${file}" 1 fi done done done