diff --git a/data/Dockerfiles/acme/docker-entrypoint.sh b/data/Dockerfiles/acme/docker-entrypoint.sh index 716c3768..b8098a14 100755 --- a/data/Dockerfiles/acme/docker-entrypoint.sh +++ b/data/Dockerfiles/acme/docker-entrypoint.sh @@ -137,10 +137,11 @@ while true; do fi done - ALL_VALIDATED="$(echo ${VALIDATED_CONFIG_DOMAINS[*]} ${ADDITIONAL_VALIDATED_SAN[*]} ${VALIDATED_MAILCOW_HOSTNAME})" + # Unique elements + ALL_VALIDATED=($(echo ${VALIDATED_CONFIG_DOMAINS[*]} ${ADDITIONAL_VALIDATED_SAN[*]} ${VALIDATED_MAILCOW_HOSTNAME} | xargs -n1 | sort -u | xargs)) if [[ -z ${ALL_VALIDATED[*]} ]]; then echo "Cannot validate hostnames, skipping Let's Encrypt..." - echo 0 + exit 0 fi ORPHANED_SAN=($(echo ${SAN_ARRAY_NOW[*]} ${VALIDATED_CONFIG_DOMAINS[*]} ${ADDITIONAL_VALIDATED_SAN[*]} ${MAILCOW_HOSTNAME} | tr ' ' '\n' | sort | uniq -u )) @@ -159,7 +160,7 @@ while true; do -f ${ACME_BASE}/acme/private/account.key \ -k ${ACME_BASE}/acme/private/privkey.pem \ -c ${ACME_BASE}/acme \ - ${VALIDATED_MAILCOW_HOSTNAME} ${VALIDATED_CONFIG_DOMAINS[*]} ${ADDITIONAL_VALIDATED_SAN[*]} + ${ALL_VALIDATED[*]} case "$?" in 0) # new certs diff --git a/data/Dockerfiles/clamd/bootstrap.sh b/data/Dockerfiles/clamd/bootstrap.sh index 96c35667..6b4acb4d 100755 --- a/data/Dockerfiles/clamd/bootstrap.sh +++ b/data/Dockerfiles/clamd/bootstrap.sh @@ -4,6 +4,11 @@ trap "kill 0" SIGINT touch /var/log/clamav/clamd.log /var/log/clamav/freshclam.log chown -R clamav:clamav /var/log/clamav/ +if [[ "${SKIP_CLAMD}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + echo "SKIP_CLAMD=y, skipping ClamAV..." + exit 0 +fi + freshclam -d & clamd & diff --git a/data/Dockerfiles/dovecot/syslog-ng.conf b/data/Dockerfiles/dovecot/syslog-ng.conf index ead195a5..b8cc44fd 100644 --- a/data/Dockerfiles/dovecot/syslog-ng.conf +++ b/data/Dockerfiles/dovecot/syslog-ng.conf @@ -15,17 +15,27 @@ source s_src { }; destination d_combined { file("/var/log/combined.log"); }; -destination d_redis { +destination d_redis_persistent_log { redis( host("redis-mailcow") + persist-name("redis1") port(6379) command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") ); }; -filter f_mail { facility(mail) and not filter(f_debug); }; +destination d_redis_f2b_channel { + redis( + host("redis-mailcow") + persist-name("redis2") + port(6379) + command("PUBLISH" "F2B_CHANNEL" "$MESSAGE") + ); +}; +filter f_mail { facility(mail); }; log { source(s_src); destination(d_combined); filter(f_mail); - destination(d_redis); + destination(d_redis_persistent_log); + destination(d_redis_f2b_channel); }; diff --git a/data/Dockerfiles/fail2ban/Dockerfile b/data/Dockerfiles/fail2ban/Dockerfile index 9f81f14e..26fe9414 100644 --- a/data/Dockerfiles/fail2ban/Dockerfile +++ b/data/Dockerfiles/fail2ban/Dockerfile @@ -2,7 +2,7 @@ FROM python:2-alpine LABEL maintainer "Andre Peters " RUN apk add -U --no-cache iptables ip6tables -RUN pip install docker redis +RUN pip install redis ipaddress COPY logwatch.py / CMD ["python2", "-u", "/logwatch.py"] diff --git a/data/Dockerfiles/fail2ban/logwatch.py b/data/Dockerfiles/fail2ban/logwatch.py index 74bc26b5..d431a072 100644 --- a/data/Dockerfiles/fail2ban/logwatch.py +++ b/data/Dockerfiles/fail2ban/logwatch.py @@ -8,7 +8,6 @@ import signal import ipaddress import subprocess from threading import Thread -import docker import redis import time import json @@ -19,33 +18,16 @@ if re.search(yes_regex, os.getenv('SKIP_FAIL2BAN', 0)): raise SystemExit r = redis.StrictRedis(host='172.22.1.249', decode_responses=True, port=6379, db=0) -client = docker.from_env() - -for container in client.containers.list(): - if "postfix-mailcow" in container.name: - postfix_container = container.name - elif "dovecot-mailcow" in container.name: - dovecot_container = container.name - elif "sogo-mailcow" in container.name: - sogo_container = container.name - elif "php-fpm-mailcow" in container.name: - php_fpm_container = container.name +pubsub = r.pubsub() RULES = {} - -RULES[postfix_container] = {} -RULES[dovecot_container] = {} -RULES[sogo_container] = {} -RULES[php_fpm_container] = {} - -RULES[postfix_container][1] = 'warning: .*\[([0-9a-f\.:]+)\]: SASL .* authentication failed' -RULES[dovecot_container][1] = '-login: Disconnected \(auth failed, .*\): user=.*, method=.*, rip=([0-9a-f\.:]+),' -RULES[dovecot_container][2] = '-login: Disconnected \(no auth .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' -RULES[dovecot_container][3] = '-login: Aborted login \(no auth .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' -RULES[dovecot_container][4] = '-login: Aborted login \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' -RULES[sogo_container][1] = 'SOGo.* Login from \'([0-9a-f\.:]+)\' for user .* might not have worked' -RULES[php_fpm_container][1] = 'mailcow UI: Invalid password for .* by ([0-9a-f\.:]+)' - +RULES[1] = 'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed' +RULES[2] = '-login: Disconnected \(auth failed, .+\): user=.*, method=.+, rip=([0-9a-f\.:]+),' +RULES[3] = '-login: Disconnected \(no auth .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' +RULES[4] = '-login: Aborted login \(no auth .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' +RULES[5] = '-login: Aborted login \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' +RULES[6] = 'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked' +RULES[7] = 'mailcow UI: Invalid password for .+ by ([0-9a-f\.:]+)' r.setnx("F2B_BAN_TIME", "1800") r.setnx("F2B_MAX_ATTEMPTS", "10") @@ -149,24 +131,28 @@ def clear(): print "Clearing all bans" for net in bans.copy(): unban(net) + pubsub.unsubscribe() -def watch(container): +def watch(): log['time'] = int(round(time.time())) log['priority'] = "info" - log['message'] = "Watching %s" % container + log['message'] = "Watching Redis channel F2B_CHANNEL" r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False)) - print "Watching", container - for msg in client.containers.get(container).attach(stream=True, logs=False): - for rule_id, rule_regex in RULES[container].iteritems(): - result = re.search(rule_regex, msg) - if result: - addr = result.group(1) - print "%s matched rule id %d in %s" % (addr, rule_id, container) - log['time'] = int(round(time.time())) - log['priority'] = "warn" - log['message'] = "%s matched rule id %d in %s" % (addr, rule_id, container) - r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False)) - ban(addr) + pubsub.subscribe("F2B_CHANNEL") + print "Subscribing to Redis channel F2B_CHANNEL" + while True: + for item in pubsub.listen(): + for rule_id, rule_regex in RULES.iteritems(): + if item['data'] and item['type'] == 'message': + result = re.search(rule_regex, item['data']) + if result: + addr = result.group(1) + print "%s matched rule id %d" % (addr, rule_id) + log['time'] = int(round(time.time())) + log['priority'] = "warn" + log['message'] = "%s matched rule id %d" % (addr, rule_id) + r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False)) + ban(addr) def autopurge(): while not quit_now: @@ -180,14 +166,13 @@ def autopurge(): if bans[net]['attempts'] >= MAX_ATTEMPTS: if time.time() - bans[net]['last_attempt'] > BAN_TIME: unban(net) - time.sleep(30) + time.sleep(10) if __name__ == '__main__': - threads = [] - for container in RULES: - threads.append(Thread(target=watch, args=(container,))) - threads[-1].daemon = True - threads[-1].start() + + watch_thread = Thread(target=watch) + watch_thread.daemon = True + watch_thread.start() autopurge_thread = Thread(target=autopurge) autopurge_thread.daemon = True @@ -197,9 +182,4 @@ if __name__ == '__main__': atexit.register(clear) while not quit_now: - for thread in threads: - if not thread.isAlive(): - break - time.sleep(0.1) - - clear() + time.sleep(0.5) diff --git a/data/Dockerfiles/postfix/syslog-ng.conf b/data/Dockerfiles/postfix/syslog-ng.conf index 2c1fce88..48783b2a 100644 --- a/data/Dockerfiles/postfix/syslog-ng.conf +++ b/data/Dockerfiles/postfix/syslog-ng.conf @@ -15,17 +15,27 @@ source s_src { }; destination d_combined { file("/var/log/combined.log"); }; -destination d_redis { +destination d_redis_persistent_log { redis( host("redis-mailcow") + persist-name("redis1") port(6379) - command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") + command("LPUSH" "POSTFIX_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") ); }; -filter f_mail { facility(mail) and not filter(f_debug); }; +destination d_redis_f2b_channel { + redis( + host("redis-mailcow") + persist-name("redis2") + port(6379) + command("PUBLISH" "F2B_CHANNEL" "$MESSAGE") + ); +}; +filter f_mail { facility(mail); }; log { source(s_src); destination(d_combined); filter(f_mail); - destination(d_redis); + destination(d_redis_persistent_log); + destination(d_redis_f2b_channel); }; diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index a3a1308d..0fc4675f 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:jessie-slim +FROM debian:stretch-slim LABEL maintainer "Andre Peters " ARG DEBIAN_FRONTEND=noninteractive @@ -11,30 +11,23 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ cron \ gnupg \ - make \ mysql-client \ supervisor \ syslog-ng \ syslog-ng-core \ syslog-ng-mod-redis \ - tar \ + dirmngr \ wget \ - zip \ && rm -rf /var/lib/apt/lists/* \ && dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \ - && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc" \ - && export GNUPGHOME="$(mktemp -d)" \ - && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ - && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \ - && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \ && chmod +x /usr/local/bin/gosu \ && gosu nobody true RUN mkdir /usr/share/doc/sogo \ && touch /usr/share/doc/sogo/empty.sh \ - && apt-key adv --keyserver keys.gnupg.net --recv-key 0x810273C4 \ - && echo "deb http://packages.inverse.ca/SOGo/nightly/3/debian/ jessie jessie" > /etc/apt/sources.list.d/sogo.list \ + && apt-key adv --keyserver sks.labs.nic.cz --recv-key A04BE668 \ + && echo "deb http://www.axis.cz/linux/debian stretch sogo-v3" > /etc/apt/sources.list.d/sogo.list \ && apt-get update && apt-get install -y --force-yes \ sogo \ sogo-activesync \ diff --git a/data/Dockerfiles/sogo/reconf-domains.sh b/data/Dockerfiles/sogo/reconf-domains.sh index a0a0b64d..ec0d4c93 100755 --- a/data/Dockerfiles/sogo/reconf-domains.sh +++ b/data/Dockerfiles/sogo/reconf-domains.sh @@ -93,9 +93,6 @@ echo ' chown sogo:sogo -R /var/lib/sogo/ chmod 600 /var/lib/sogo/GNUstep/Defaults/sogod.plist -# Regenerate the SOGo Integrator plugin -/thunderbird/build-plugins.sh ${MAILCOW_HOSTNAME} < <(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain;" -B -N) - supervisorctl restart sogo sleep 99999 diff --git a/data/Dockerfiles/sogo/syslog-ng.conf b/data/Dockerfiles/sogo/syslog-ng.conf index 6e9ba2a2..4d17d9b1 100644 --- a/data/Dockerfiles/sogo/syslog-ng.conf +++ b/data/Dockerfiles/sogo/syslog-ng.conf @@ -19,13 +19,22 @@ source s_sogo { destination d_combined { file("/var/log/combined.log"); }; -destination d_redis { +destination d_redis_persistent_log { redis( host("redis-mailcow") + persist-name("redis1") port(6379) command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") ); }; +destination d_redis_f2b_channel { + redis( + host("redis-mailcow") + persist-name("redis2") + port(6379) + command("PUBLISH" "F2B_CHANNEL" "$MESSAGE") + ); +}; log { source(s_sogo); source(s_src); @@ -33,5 +42,6 @@ log { }; log { source(s_sogo); - destination(d_redis); + destination(d_redis_persistent_log); + destination(d_redis_f2b_channel); }; diff --git a/data/web/admin.php b/data/web/admin.php index f402fd61..0e0003a8 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -231,7 +231,7 @@ $tfa_data = get_tfa(); - +
diff --git a/data/web/css/admin.css b/data/web/css/admin.css index d2bb2489..7f8897a0 100644 --- a/data/web/css/admin.css +++ b/data/web/css/admin.css @@ -31,3 +31,14 @@ body.modal-open { .inputMissingAttr { border-color: #FF4136; } +.rotate { + -moz-transition: all 0.3s linear; + -webkit-transition: all 0.3s linear; + transition: all 0.3s linear; +} +.rotate.animation { + -ms-transform:rotateX(180deg); + -moz-transform:rotateX(180deg); + -webkit-transform:rotateX(180deg); + transform:rotateX(180deg); +} \ No newline at end of file diff --git a/data/web/css/mailcow.css b/data/web/css/mailcow.css index 09ece249..eeade3c7 100644 --- a/data/web/css/mailcow.css +++ b/data/web/css/mailcow.css @@ -91,4 +91,11 @@ body.modal-open { max-width: 550px; z-index: 2000; } -.input-group-sm .btn { margin-top: 0px !important } \ No newline at end of file +.input-group-sm .btn { margin-top: 0px !important } +legend { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none + -o-user-select: none; + user-select: none; +} \ No newline at end of file diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 8e7b7cfd..b3420530 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -168,6 +168,7 @@ function doveadm_authenticate($hash, $algorithm, $password) { } function check_login($user, $pass) { global $pdo; + global $redis; if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) { return false; } @@ -229,10 +230,12 @@ function check_login($user, $pass) { } if (!isset($_SESSION['ldelay'])) { $_SESSION['ldelay'] = "0"; + $redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']); error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']); } elseif (!isset($_SESSION['mailcow_cc_username'])) { $_SESSION['ldelay'] = $_SESSION['ldelay']+0.5; + $redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']); error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']); } sleep($_SESSION['ldelay']); diff --git a/data/web/js/admin.js b/data/web/js/admin.js index 55ffcc0a..371b287f 100644 --- a/data/web/js/admin.js +++ b/data/web/js/admin.js @@ -47,6 +47,10 @@ jQuery(function($){ e.preventDefault(); draw_rspamd_history(); }); + $("#import_dkim_legend").on('click', function(e) { + e.preventDefault(); + $('#import_dkim_arrow').toggleClass("animation"); + }); function draw_postfix_logs() { ft_postfix_logs = FooTable.init('#postfix_log', { "columns": [ diff --git a/data/web/thunderbird-plugins.php b/data/web/thunderbird-plugins.php deleted file mode 100644 index 8a1a7e9b..00000000 --- a/data/web/thunderbird-plugins.php +++ /dev/null @@ -1,96 +0,0 @@ - 'thunderbird', - 'version' => $row[1], - 'filename' => str_replace('__DOMAIN__', $_GET["domain"], $row[2]), - ); - } - fclose($fh); - } -} - -$applications -= array( "thunderbird" => "{3550f703-e582-4d05-9a08-453d09bdfdc6} - 31.0 - 31.*" ); - -$pluginname = $_GET["plugin"]; -$plugin =& $plugins[$pluginname]; -$application =& $applications[$plugin["application"]]; - -if ( $plugin ) { - $platform = $_GET["platform"]; - if ( $platform - && file_exists( $platform . "/" . $plugin["filename"] ) ) { - $plugin["filename"] = $platform . "/" . $plugin["filename"]; - } - elseif ( !file_exists( $plugin["filename"] ) ) { - $plugin = false; - } -} - -if ( $plugin ) { - header("Content-type: text/xml; charset=utf-8"); - echo ('' . "\n"); -?> - - - - - -
  • - - - - - - - - - - -
  • -
    -
    -
    -
    - diff --git a/data/web/thunderbird-plugins/.gitignore b/data/web/thunderbird-plugins/.gitignore deleted file mode 100644 index 2744d736..00000000 --- a/data/web/thunderbird-plugins/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.zip -sogo-*-master -version.csv -*.xpi -*.tar.gz diff --git a/data/web/thunderbird-plugins/build-plugins.sh b/data/web/thunderbird-plugins/build-plugins.sh deleted file mode 100755 index 03986b78..00000000 --- a/data/web/thunderbird-plugins/build-plugins.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -set -e - -MAILHOST=$1 - -cd $(dirname $0) - -wget -O integrator.tar.gz https://github.com/inverse-inc/sogo-integrator.tb31/archive/master.tar.gz -wget -O connector.tar.gz https://github.com/inverse-inc/sogo-connector.tb31/archive/master.tar.gz - -mkdir -p integrator connector -tar --strip-components=1 -C integrator -xf integrator.tar.gz -tar --strip-components=1 -C connector -xf connector.tar.gz - -# build custom integrator -while read DOMAIN; do - echo "Building SOGo Integrator for $DOMAIN hosted on $MAILHOST" - cd integrator - echo > defaults/preferences/site.js - mkdir -p custom/${DOMAIN} - cp -r custom/sogo-demo/* custom/${DOMAIN}/ - sed -i "s/http:\/\/sogo-demo\.inverse\.ca/https:\/\/${MAILHOST}/g" custom/${DOMAIN}/chrome/content/extensions.rdf - sed -i "s/plugins\/updates\.php[?]/thunderbird-plugins.php?domain=${DOMAIN}\&/g" custom/${DOMAIN}/chrome/content/extensions.rdf - echo 'pref("sogo-integrator.autocomplete.server.urlid", "'${DOMAIN}'");' > custom/${DOMAIN}/defaults/preferences/site.js - echo 'pref("mail.collect_email_address_outgoing", false);' >> custom/${DOMAIN}/defaults/preferences/site.js - sed -i 's/<\/Seq>/
  • <\/li>
  • <\/li><\/Seq>/g' custom/${DOMAIN}/chrome/content/extensions.rdf - make build=${DOMAIN} - INTEGRATOR_VER=$(grep em:version install.rdf | awk -F '"' '{print $2}') - cp sogo-integrator-*-${DOMAIN}.xpi ../sogo-integrator-${INTEGRATOR_VER}-${DOMAIN}.xpi - cd .. -done - -# build connector -cd connector -make -CONNECTOR_VER=$(grep em:version install.rdf | awk -F '"' '{print $2}') -cp sogo-connector-*.xpi ../sogo-connector-${CONNECTOR_VER}.xpi -cd .. - -# download Sieve plugin -SIEVE_RELEASES=$(wget --header="Accept: application/vnd.github.v3+json" -qO - https://api.github.com/repos/thsmi/sieve/releases) -SIEVE_VER=$(echo "$SIEVE_RELEASES" | grep -o '"tag_name": *"[^"]*"' | head -n 1 | awk -F '"' '{print $4}') -SIEVE_URL=$(echo "$SIEVE_RELEASES" | grep -o '"browser_download_url": *"[^"]*"' | head -n 1 | awk -F '"' '{print $4}') -wget -O sieve-${SIEVE_VER}.xpi ${SIEVE_URL} -unset SIEVE_RELEASES - -# download ACL plugin -IMAP_ACL_RELEASES=$(wget -qO - 'https://addons.mozilla.org/api/v3/addons/addon/176736') -IMAP_ACL_VER=$(echo "$IMAP_ACL_RELEASES" | grep -o '"version": *"[^"]*"' | head -n 1 | awk -F '"' '{print $4}') -IMAP_ACL_URL=$(echo "$IMAP_ACL_RELEASES" | grep -o '"url": *"[^"]*\.xpi' | head -n 1 | awk -F '"' '{print $4}') -wget -O imap_acl_extension-${IMAP_ACL_VER}-tb.xpi ${IMAP_ACL_URL} -unset IMAP_ACL_RELEASES - -# update version file -echo "sogo-connector@inverse.ca;${CONNECTOR_VER};sogo-connector-${CONNECTOR_VER}.xpi" > version.csv -echo "sogo-integrator@inverse.ca;${INTEGRATOR_VER};sogo-integrator-${INTEGRATOR_VER}-__DOMAIN__.xpi" >> version.csv -echo "sieve@mozdev.org;${SIEVE_VER};sieve-${SIEVE_VER}.xpi" >> version.csv -echo "imap-acl@sirphreak.com;${IMAP_ACL_VER};imap_acl_extension-${IMAP_ACL_VER}-tb.xpi" >> version.csv - -rm -rf connector integrator *.tar.gz diff --git a/docker-compose.yml b/docker-compose.yml index 12003749..f809c671 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -66,9 +66,11 @@ services: - redis clamd-mailcow: - image: mailcow/clamd:1.0 + image: mailcow/clamd:1.1 build: ./data/Dockerfiles/clamd restart: always + environment: + - SKIP_CLAMD=${SKIP_CLAMD:-n} dns: - 172.22.1.254 dns_search: mailcow-network @@ -143,7 +145,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.0 + image: mailcow/sogo:1.1 build: ./data/Dockerfiles/sogo depends_on: unbound-mailcow: @@ -156,7 +158,6 @@ services: - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} volumes: - ./data/conf/sogo/:/etc/sogo/ - - ./data/web/thunderbird-plugins:/thunderbird restart: always logging: options: @@ -171,7 +172,7 @@ services: - sogo dovecot-mailcow: - image: mailcow/dovecot:1.1 + image: mailcow/dovecot:1.2 build: ./data/Dockerfiles/dovecot depends_on: unbound-mailcow: @@ -206,7 +207,7 @@ services: - dovecot postfix-mailcow: - image: mailcow/postfix:1.0 + image: mailcow/postfix:1.1 build: ./data/Dockerfiles/postfix depends_on: unbound-mailcow: @@ -293,7 +294,7 @@ services: acme-mailcow: depends_on: - nginx-mailcow - image: mailcow/acme:1.11 + image: mailcow/acme:1.12 build: ./data/Dockerfiles/acme dns: - 172.22.1.254 @@ -319,7 +320,7 @@ services: - acme fail2ban-mailcow: - image: mailcow/fail2ban:1.4 + image: mailcow/fail2ban:1.5 build: ./data/Dockerfiles/fail2ban depends_on: - dovecot-mailcow @@ -337,8 +338,8 @@ services: - 172.22.1.254 dns_search: mailcow-network volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - /lib/modules:/lib/modules:ro + ipv6nat: image: robbertkl/ipv6nat restart: always diff --git a/generate_config.sh b/generate_config.sh index 433b9001..62a5ecaf 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -58,7 +58,7 @@ HTTPS_BIND=0.0.0.0 # ------------------------------ # You should leave that alone # Format: 11.22.33.44:25 or 0.0.0.0:465 etc. -# Do _not_ use IP:PORT in HTTPS_BIND or HTTPS_PORT +# Do _not_ use IP:PORT in HTTP(S)_BIND or HTTP(S)_PORT SMTP_PORT=25 SMTPS_PORT=465 @@ -87,6 +87,9 @@ SKIP_IP_CHECK=n # To never run fail2ban-mailcow SKIP_FAIL2BAN=n +# To never run clamd-mailcow +SKIP_CLAMD=n + EOF mkdir -p data/assets/ssl diff --git a/update.sh b/update.sh index d5645144..399382d4 100755 --- a/update.sh +++ b/update.sh @@ -7,6 +7,25 @@ if [[ -z $(which git) ]]; then echo "Cannot find git, exiting."; exit 1; fi if [[ -z $(which awk) ]]; then echo "Cannot find awk, exiting."; exit 1; fi if [[ -z $(which sha1sum) ]]; then echo "Cannot find sha1sum, exiting."; exit 1; fi +CONFIG_ARRAY=("SKIP_LETS_ENCRYPT" "SKIP_CLAMD" "SKIP_IP_CHECK" "SKIP_FAIL2BAN" "ADDITIONAL_SAN") +echo >> mailcow.conf +for option in ${CONFIG_ARRAY[@]}; do + if [[ ${option} == "ADDITIONAL_SAN" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "${option}=" >> mailcow.conf + fi + elif [[ ${option} == "COMPOSE_PROJECT_NAME" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "${COMPOSE_PROJECT_NAME}=mailcow-dockerized" >> mailcow.conf + fi + elif ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "${option}=n" >> mailcow.conf + fi +done + echo -en "Checking internet connection... " curl -o /dev/null google.com -sm3 if [[ $? != 0 ]]; then @@ -106,14 +125,16 @@ chmod +x $(which docker-compose) echo -e "\e[32mStarting mailcow...\e[0m" sleep 2 docker-compose up -d --remove-orphans -#echo -e "\e[32mCleaning up Docker objects...\e[0m" -if docker images -f "dangling=true" | grep ago --quiet; then - docker rmi -f $(docker images -f "dangling=true" -q) +#echo -e "\e[32mCleaning up dangling Docker objects...\e[0m" +if [[ ! -z $(docker images -qf "dangling=true") ]]; then + docker rmi -f $(docker images -qf "dangling=true" -q) +fi +if [[ ! -z $(docker volume ls -qf dangling=true) ]]; then docker volume rm $(docker volume ls -qf dangling=true) fi -echo "In case you encounter any problem, hard-reset to a state before updating mailcow:" -echo -git reflog --color=always | grep "Before update on " -echo -echo "Use \"git reset --hard hash-on-the-left\" and run docker-compose up -d afterwards." +#echo "In case you encounter any problem, hard-reset to a state before updating mailcow:" +#echo +#git reflog --color=always | grep "Before update on " +#echo +#echo "Use \"git reset --hard hash-on-the-left\" and run docker-compose up -d afterwards."