Pārlūkot izejas kodu

Merge branch 'dev'

andryyy 8 gadi atpakaļ
vecāks
revīzija
c30f54d368

+ 4 - 3
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

+ 5 - 0
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 &
 

+ 13 - 3
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);
 };

+ 1 - 1
data/Dockerfiles/fail2ban/Dockerfile

@@ -2,7 +2,7 @@ FROM python:2-alpine
 LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
 
 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"]

+ 32 - 52
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)

+ 14 - 4
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);
 };

+ 4 - 11
data/Dockerfiles/sogo/Dockerfile

@@ -1,4 +1,4 @@
-FROM debian:jessie-slim
+FROM debian:stretch-slim
 LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
 
 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 \

+ 0 - 3
data/Dockerfiles/sogo/reconf-domains.sh

@@ -93,9 +93,6 @@ echo '    </dict>
 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

+ 12 - 2
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);
 };

+ 1 - 1
data/web/admin.php

@@ -231,7 +231,7 @@ $tfa_data = get_tfa();
           <button class="btn btn-default" id="add_item" data-id="dkim" data-api-url='add/dkim' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
         </form>
 
-        <legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" data-toggle="collapse">↳ <?=$lang['admin']['import_private_key'];?></legend>
+        <legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" id="import_dkim_legend" unselectable="on" data-toggle="collapse"><span id="import_dkim_arrow" class="rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['import_private_key'];?></legend>
         <div id="import_dkim" class="collapse">
         <form class="form" data-id="dkim_import" role="form" method="post">
           <div class="form-group">

+ 11 - 0
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);
+}

+ 8 - 1
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 }
+.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;
+}

+ 3 - 0
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']);

+ 4 - 0
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": [

+ 0 - 96
data/web/thunderbird-plugins.php

@@ -1,96 +0,0 @@
-<?php
-/* updates.php - this file is part of SOGo
- *
- *  Copyright (C) 2006-2014 Inverse inc.
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* This script handles the automatic propagation of extensions pertaining to a
-   SOGo site. It requires PHP 4.1.0 or later. */
-$plugin_dir = 'thunderbird-plugins';
-chdir($plugin_dir);
-$plugins = array();
-
-if (file_exists('version.csv'))
-{
-  $fh = fopen('version.csv', 'r');
-  if ($fh)
-  {
-    while (($row = fgetcsv($fh, 1000, ';')) !== FALSE)
-    {
-      $plugins[$row[0]] = array(
-        'application' => 'thunderbird',
-        'version' => $row[1],
-        'filename' => str_replace('__DOMAIN__', $_GET["domain"], $row[2]),
-      );
-    }
-    fclose($fh);
-  }
-}
-
-$applications
-= array( "thunderbird" => "<em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
-                <em:minVersion>31.0</em:minVersion>
-                <em:maxVersion>31.*</em:maxVersion>" );
-
-$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 ('<?xml version="1.0"?>' . "\n");
-?>
-<!DOCTYPE RDF>
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-  xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-  <Description about="urn:mozilla:extension:<?php echo $pluginname ?>">
-    <em:updates>
-      <Seq>
-        <li>
-          <Description>
-            <em:version><?php echo $plugin["version"] ?></em:version>
-            <em:targetApplication>
-              <Description>
-                <?php echo $applications[$plugin["application"]] ?>
-                
-                <em:updateLink><?php echo 'https://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/' .  $plugin_dir . '/' . $plugin["filename"] ?></em:updateLink>
-              </Description>
-            </em:targetApplication>
-          </Description>
-        </li>
-      </Seq>
-    </em:updates>
-  </Description>
-</RDF>
-<?php
-} else {
-  header("Content-type: text/plain; charset=utf-8", true, 404);
-  echo( 'Plugin not found' );
-}
-?>

+ 0 - 5
data/web/thunderbird-plugins/.gitignore

@@ -1,5 +0,0 @@
-*.zip
-sogo-*-master
-version.csv
-*.xpi
-*.tar.gz

+ 0 - 61
data/web/thunderbird-plugins/build-plugins.sh

@@ -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}\&amp;/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><Description em:id="sieve@mozdev.org" em:name="Sieve"\/><\/li><li><Description em:id="imap-acl@sirphreak.com" em:name="Imap-ACL-Extension"\/><\/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

+ 9 - 8
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

+ 4 - 1
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

+ 29 - 8
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."