From 84a7a1a2e7e0015018f23f2e10a7fc1c89711dca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Tue, 14 Nov 2017 10:44:00 +0100 Subject: [PATCH] [Compose] New images, Nginx checks for SOGo before bootstrapping [PHP-FPM] Some more modules (primarily for Horde) [Fail2ban] Do not log matches of local and private ips [Watchdog] Some changes in log system for further processing (wip) [ACME] Fixes #745 --- data/Dockerfiles/acme/docker-entrypoint.sh | 11 ++-- data/Dockerfiles/fail2ban/logwatch.py | 3 ++ data/Dockerfiles/phpfpm/Dockerfile | 8 +-- data/Dockerfiles/watchdog/watchdog.sh | 58 ++++++++++------------ docker-compose.yml | 9 ++-- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/data/Dockerfiles/acme/docker-entrypoint.sh b/data/Dockerfiles/acme/docker-entrypoint.sh index 6d3d7273..a859684d 100755 --- a/data/Dockerfiles/acme/docker-entrypoint.sh +++ b/data/Dockerfiles/acme/docker-entrypoint.sh @@ -2,6 +2,12 @@ set -o pipefail exec 5>&1 +if [[ "${SKIP_LETS_ENCRYPT}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + log_f "SKIP_LETS_ENCRYPT=y, skipping Let's Encrypt..." + sleep 365d + exec $(readlink -f "$0") +fi + ACME_BASE=/var/lib/acme SSL_EXAMPLE=/var/lib/ssl-example @@ -102,11 +108,6 @@ while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do done while true; do - if [[ "${SKIP_LETS_ENCRYPT}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then - log_f "SKIP_LETS_ENCRYPT=y, skipping Let's Encrypt..." - sleep 365d - exec $(readlink -f "$0") - fi if [[ "${SKIP_IP_CHECK}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then SKIP_IP_CHECK=y fi diff --git a/data/Dockerfiles/fail2ban/logwatch.py b/data/Dockerfiles/fail2ban/logwatch.py index f1954489..6be96023 100644 --- a/data/Dockerfiles/fail2ban/logwatch.py +++ b/data/Dockerfiles/fail2ban/logwatch.py @@ -147,6 +147,9 @@ def watch(): result = re.search(rule_regex, item['data']) if result: addr = result.group(1) + ip = ipaddress.ip_address(addr.decode('ascii')) + if ip.is_private or ip.is_loopback: + continue print "%s matched rule id %d" % (addr, rule_id) log['time'] = int(round(time.time())) log['priority'] = "warn" diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index 6a1e90a3..84a1f67b 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -32,6 +32,8 @@ RUN apk add -U --no-cache libxml2-dev \ imagemagick-dev \ imagemagick \ libtool \ + gettext-dev \ + openldap-dev \ librsvg \ && pear install channel://pear.php.net/Net_IDNA2-0.2.0 \ channel://pear.php.net/Auth_SASL-1.1.0 \ @@ -43,7 +45,7 @@ RUN apk add -U --no-cache libxml2-dev \ && docker-php-ext-enable redis apcu memcached imagick \ && pecl clear-cache \ && docker-php-ext-configure intl \ - && docker-php-ext-install -j 4 intl pdo pdo_mysql xmlrpc gd zip pcntl opcache \ + && docker-php-ext-install -j 4 intl gettext ldap sockets soap pdo pdo_mysql xmlrpc gd zip pcntl opcache \ && docker-php-ext-configure imap --with-imap --with-imap-ssl \ && docker-php-ext-install -j 4 imap \ && apk del --purge autoconf g++ make libxml2-dev icu-dev imap-dev openssl-dev cyrus-sasl-dev pcre-dev libpng-dev libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev imagemagick-dev \ @@ -55,9 +57,7 @@ RUN apk add -U --no-cache libxml2-dev \ echo 'opcache.memory_consumption=128'; \ echo 'opcache.save_comments=1'; \ echo 'opcache.revalidate_freq=1'; \ -} > /usr/local/etc/php/conf.d/opcache-recommended.ini \ - && rm -rf /usr/src/php* - +} > /usr/local/etc/php/conf.d/opcache-recommended.ini COPY ./docker-entrypoint.sh / diff --git a/data/Dockerfiles/watchdog/watchdog.sh b/data/Dockerfiles/watchdog/watchdog.sh index d7351936..902f66dc 100755 --- a/data/Dockerfiles/watchdog/watchdog.sh +++ b/data/Dockerfiles/watchdog/watchdog.sh @@ -28,13 +28,19 @@ progress() { [[ ${CURRENT} -gt ${TOTAL} ]] && return [[ ${CURRENT} -lt 0 ]] && CURRENT=0 PERCENT=$(( 200 * ${CURRENT} / ${TOTAL} % 2 + 100 * ${CURRENT} / ${TOTAL} )) - echo -ne "$(date) - ${SERVICE} health level: \e[7m${PERCENT}%\e[0m (${CURRENT}/${TOTAL}), health trend: " - [[ ${DIFF} =~ ^-[1-9] ]] && echo -en '[\e[41m \e[0m] ' || echo -en '[\e[42m \e[0m] ' - echo "(${DIFF})" + log_msg "${SERVICE} health level: ${PERCENT}% (${CURRENT}/${TOTAL}), health trend: ${DIFF}" + log_data "$(printf "%d,%d,%d,%d" ${PERCENT} ${CURRENT} ${TOTAL} ${DIFF})" "${SERVICE}" } -log_to_redis() { - redis-cli -h redis LPUSH WATCHDOG_LOG "{\"time\":\"$(date +%s)\",\"message\":\"$(printf '%s' "${1}")\"}" +log_msg() { + redis-cli -h redis LPUSH WATCHDOG_LOG "{\"time\":\"$(date +%s)\",\"message\":\"$(printf '%s' "${1}")\"}" > /dev/null + echo $(date) $(printf '%s\n' "${1}") +} + +log_data() { + [[ -z ${1} ]] && return 1 + [[ -z ${2} ]] && return 2 + redis-cli -h redis LPUSH WATCHDOG_DATA "{\"time\":\"$(date +%s)\",\"service\":\"data\",\"$(printf '%s' "${2}")\":\"$(printf '%s' "${1}")\"}" > /dev/null } function mail_error() { @@ -43,8 +49,7 @@ function mail_error() { RCPT_DOMAIN=$(echo ${1} | awk -F @ {'print $NF'}) RCPT_MX=$(dig +short ${RCPT_DOMAIN} mx | sort -n | awk '{print $2; exit}') if [[ -z ${RCPT_MX} ]]; then - log_to_redis "Cannot determine MX for ${1}, skipping email notification..." - echo "Cannot determine MX for ${1}" + log_msg "Cannot determine MX for ${1}, skipping email notification..." return 1 fi ./smtp-cli --missing-modules-ok \ @@ -54,6 +59,7 @@ function mail_error() { --from="watchdog@${MAILCOW_HOSTNAME}" \ --server="${RCPT_MX}" \ --hello-host=${MAILCOW_HOSTNAME} + log_msg "Sent notification email to ${1}" } @@ -66,8 +72,8 @@ get_container_ip() { sleep 1 CONTAINER_ID=$(curl --silent http://dockerapi:8080/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"${1}\")) | .id") if [[ ! -z ${CONTAINER_ID} ]]; then - CONTAINER_IP=$(curl --silent http://dockerapi:8080/containers/${CONTAINER_ID}/json | jq -r '.NetworkSettings.Networks[].IPAddress') - fi + CONTAINER_IP=$(curl --silent http://dockerapi:8080/containers/${CONTAINER_ID}/json | jq -r '.NetworkSettings.Networks[].IPAddress') + fi LOOP_C=$((LOOP_C + 1)) done [[ ${LOOP_C} -gt 5 ]] && echo 240.0.0.0 || echo ${CONTAINER_IP} @@ -253,9 +259,8 @@ dns_checks() { ( while true; do if ! nginx_checks; then - log_to_redis "Nginx hit error limit" + log_msg "Nginx hit error limit" [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "nginx-mailcow" - echo -e "\e[31m$(date) - Nginx hit error limit\e[0m" echo nginx-mailcow > /tmp/com_pipe fi done @@ -265,9 +270,8 @@ BACKGROUND_TASKS+=($!) ( while true; do if ! mysql_checks; then - log_to_redis "MySQL hit error limit" + log_msg "MySQL hit error limit" [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "mysql-mailcow" - echo -e "\e[31m$(date) - MySQL hit error limit\e[0m" echo mysql-mailcow > /tmp/com_pipe fi done @@ -277,9 +281,8 @@ BACKGROUND_TASKS+=($!) ( while true; do if ! phpfpm_checks; then - log_to_redis "PHP-FPM hit error limit" + log_msg "PHP-FPM hit error limit" [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "php-fpm-mailcow" - echo -e "\e[31m$(date) - PHP-FPM hit error limit\e[0m" echo php-fpm-mailcow > /tmp/com_pipe fi done @@ -289,9 +292,8 @@ BACKGROUND_TASKS+=($!) ( while true; do if ! sogo_checks; then - log_to_redis "SOGo hit error limit" + log_msg "SOGo hit error limit" [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "sogo-mailcow" - echo -e "\e[31m$(date) - SOGo hit error limit\e[0m" echo sogo-mailcow > /tmp/com_pipe fi done @@ -301,9 +303,8 @@ BACKGROUND_TASKS+=($!) ( while true; do if ! postfix_checks; then - log_to_redis "Postfix hit error limit" + log_msg "Postfix hit error limit" [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "postfix-mailcow" - echo -e "\e[31m$(date) - Postfix hit error limit\e[0m" echo postfix-mailcow > /tmp/com_pipe fi done @@ -313,9 +314,8 @@ BACKGROUND_TASKS+=($!) ( while true; do if ! dovecot_checks; then - log_to_redis "Dovecot hit error limit" + log_msg "Dovecot hit error limit" [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "dovecot-mailcow" - echo -e "\e[31m$(date) - Dovecot hit error limit\e[0m" echo dovecot-mailcow > /tmp/com_pipe fi done @@ -325,9 +325,8 @@ BACKGROUND_TASKS+=($!) ( while true; do if ! dns_checks; then - log_to_redis "Unbound hit error limit" + log_msg "Unbound hit error limit" [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "unbound-mailcow" - echo -e "\e[31m$(date) - Unbound hit error limit\e[0m" #echo unbound-mailcow > /tmp/com_pipe fi done @@ -337,9 +336,8 @@ BACKGROUND_TASKS+=($!) ( while true; do if ! rspamd_checks; then - log_to_redis "Rspamd hit error limit" + log_msg "Rspamd hit error limit" [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${WATCHDOG_NOTIFY_EMAIL}" "rspamd-mailcow" - echo -e "\e[31m$(date) - Rspamd hit error limit\e[0m" echo rspamd-mailcow > /tmp/com_pipe fi done @@ -351,8 +349,7 @@ BACKGROUND_TASKS+=($!) while true; do for bg_task in ${BACKGROUND_TASKS[*]}; do if ! kill -0 ${bg_task} 1>&2; then - echo "Worker ${bg_task} died, stopping watchdog and waiting for respawn..." - log_to_redis "Worker ${bg_task} died, stopping watchdog and waiting for respawn..." + log_msg "Worker ${bg_task} died, stopping watchdog and waiting for respawn..." kill -TERM 1 fi sleep 10 @@ -366,7 +363,7 @@ while true; do while nc -z dockerapi 8080; do sleep 3 done - echo "Cannot find dockerapi-mailcow, waiting to recover..." + log_msg "Cannot find dockerapi-mailcow, waiting to recover..." kill -STOP ${BACKGROUND_TASKS[*]} until nc -z dockerapi 8080; do sleep 3 @@ -385,11 +382,10 @@ while true; do sleep 3 CONTAINER_ID=$(curl --silent http://dockerapi:8080/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"${com_pipe_answer}\")) | .id") if [[ ! -z ${CONTAINER_ID} ]]; then - log_to_redis "Sending restart command to ${CONTAINER_ID}..." - echo "Sending restart command to ${CONTAINER_ID}..." + log_msg "Sending restart command to ${CONTAINER_ID}..." curl --silent -XPOST http://dockerapi:8080/containers/${CONTAINER_ID}/restart fi - echo "Wait for restarted container to settle and continue watching..." + log_msg "Wait for restarted container to settle and continue watching..." sleep 30s kill -CONT ${BACKGROUND_TASKS[*]} kill -USR1 ${BACKGROUND_TASKS[*]} diff --git a/docker-compose.yml b/docker-compose.yml index e4b6e858..478f8718 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -92,7 +92,7 @@ services: - rspamd php-fpm-mailcow: - image: mailcow/phpfpm:1.4 + image: mailcow/phpfpm:1.5 build: ./data/Dockerfiles/phpfpm command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" depends_on: @@ -224,6 +224,7 @@ services: envsubst < /etc/nginx/conf.d/templates/server_name.template > /etc/nginx/conf.d/server_name.active && nginx -qt && until ping phpfpm -c1 > /dev/null; do sleep 1; done && + until ping sogo -c1 > /dev/null; do sleep 1; done && until ping redis -c1 > /dev/null; do sleep 1; done && exec nginx -g 'daemon off;'" environment: @@ -251,7 +252,7 @@ services: depends_on: - nginx-mailcow - mysql-mailcow - image: mailcow/acme:1.22 + image: mailcow/acme:1.23 build: ./data/Dockerfiles/acme dns: - 172.22.1.254 @@ -274,7 +275,7 @@ services: - acme fail2ban-mailcow: - image: mailcow/fail2ban:1.7 + image: mailcow/fail2ban:1.8 build: ./data/Dockerfiles/fail2ban stop_grace_period: 30s depends_on: @@ -295,7 +296,7 @@ services: - /lib/modules:/lib/modules:ro watchdog-mailcow: - image: mailcow/watchdog:1.9 + image: mailcow/watchdog:1.10 build: ./data/Dockerfiles/watchdog volumes: - vmail-vol-1:/vmail:ro