commit
55586f4cb1
|
@ -6,20 +6,38 @@ LABEL maintainer "André Peters <andre.peters@servercow.de>"
|
|||
COPY dl_files.sh bootstrap.sh ./
|
||||
|
||||
# Installation
|
||||
RUN apk add --update \
|
||||
&& apk add --no-cache clamav clamav-libunrar curl bash tini \
|
||||
ENV CLAMAV 0.99.3
|
||||
|
||||
RUN apk add --no-cache --virtual build-dependencies alpine-sdk ncurses-dev zlib-dev bzip2-dev pcre-dev linux-headers fts-dev libxml2-dev libressl-dev \
|
||||
&& apk add --no-cache curl bash tini libxml2 libbz2 pcre fts libressl \
|
||||
&& wget -O - https://www.clamav.net/downloads/production/clamav-${CLAMAV}.tar.gz | tar xfvz - \
|
||||
&& cd clamav-${CLAMAV} \
|
||||
&& LIBS=-lfts ./configure \
|
||||
--prefix=/usr \
|
||||
--libdir=/usr/lib \
|
||||
--sysconfdir=/etc/clamav \
|
||||
--mandir=/usr/share/man \
|
||||
--infodir=/usr/share/info \
|
||||
--without-iconv \
|
||||
--disable-llvm \
|
||||
--with-user=clamav \
|
||||
--with-group=clamav \
|
||||
--with-dbdir=/var/lib/clamav \
|
||||
--enable-clamdtop \
|
||||
--enable-bigstack \
|
||||
--with-pcre \
|
||||
&& make -j4 \
|
||||
&& make install \
|
||||
&& make clean \
|
||||
&& cd .. && rm -rf clamav-${CLAMAV} \
|
||||
&& apk del build-dependencies \
|
||||
&& addgroup -S clamav \
|
||||
&& adduser -S -D -h /var/lib/clamav -s /sbin/nologin -G clamav -g clamav clamav \
|
||||
&& mkdir -p /run/clamav \
|
||||
&& chown clamav:clamav /run/clamav \
|
||||
&& chmod +x /dl_files.sh \
|
||||
&& set -ex; /bin/bash /dl_files.sh \
|
||||
&& mkdir /run/clamav \
|
||||
&& chown clamav:clamav /run/clamav \
|
||||
&& chmod 750 /run/clamav \
|
||||
&& sed -i '/Foreground yes/s/^#//g' /etc/clamav/clamd.conf \
|
||||
&& sed -i '/TCPSocket 3310/s/^#//g' /etc/clamav/clamd.conf \
|
||||
&& sed -i 's#LogFile /var/log/clamav/clamd.log#LogFile /tmp/logpipe_clamd#g' /etc/clamav/clamd.conf \
|
||||
&& sed -i 's/#PhishingSignatures yes/PhishingSignatures no/g' /etc/clamav/clamd.conf \
|
||||
&& sed -i 's/#PhishingScanURLs yes/PhishingScanURLs no/g' /etc/clamav/clamd.conf \
|
||||
&& sed -i 's#UpdateLogFile /var/log/clamav/freshclam.log#UpdateLogFile /tmp/logpipe_freshclam#g' /etc/clamav/freshclam.conf \
|
||||
&& sed -i '/Foreground yes/s/^#//g' /etc/clamav/freshclam.conf
|
||||
&& chmod 750 /run/clamav
|
||||
|
||||
# Port provision
|
||||
EXPOSE 3310
|
||||
|
|
|
@ -33,26 +33,29 @@ open my $file, '<', "/etc/sogo/sieve.creds";
|
|||
my $creds = <$file>;
|
||||
close $file;
|
||||
my ($master_user, $master_pass) = split /:/, $creds;
|
||||
my $sth = $dbh->prepare("SELECT id, user1, user2, host1, authmech1, password1, exclude, port1, enc1, delete2duplicates, maxage, subfolder2, delete1, delete2 FROM imapsync WHERE active = 1 AND (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(last_run) > mins_interval * 60 OR last_run IS NULL) ORDER BY last_run");
|
||||
my $sth = $dbh->prepare("SELECT id, user1, user2, host1, authmech1, password1, exclude, port1, enc1, delete2duplicates, maxage, subfolder2, delete1, delete2, automap, skipcrossduplicates, maxbytespersecond FROM imapsync WHERE active = 1 AND (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(last_run) > mins_interval * 60 OR last_run IS NULL) ORDER BY last_run");
|
||||
$sth->execute();
|
||||
my $row;
|
||||
|
||||
while ($row = $sth->fetchrow_arrayref()) {
|
||||
|
||||
$id = @$row[0];
|
||||
$user1 = @$row[1];
|
||||
$user2 = @$row[2];
|
||||
$host1 = @$row[3];
|
||||
$authmech1 = @$row[4];
|
||||
$password1 = @$row[5];
|
||||
$exclude = @$row[6];
|
||||
$port1 = @$row[7];
|
||||
$enc1 = @$row[8];
|
||||
$delete2duplicates = @$row[9];
|
||||
$maxage = @$row[10];
|
||||
$subfolder2 = @$row[11];
|
||||
$delete1 = @$row[12];
|
||||
$delete2 = @$row[13];
|
||||
$id = @$row[0];
|
||||
$user1 = @$row[1];
|
||||
$user2 = @$row[2];
|
||||
$host1 = @$row[3];
|
||||
$authmech1 = @$row[4];
|
||||
$password1 = @$row[5];
|
||||
$exclude = @$row[6];
|
||||
$port1 = @$row[7];
|
||||
$enc1 = @$row[8];
|
||||
$delete2duplicates = @$row[9];
|
||||
$maxage = @$row[10];
|
||||
$subfolder2 = @$row[11];
|
||||
$delete1 = @$row[12];
|
||||
$delete2 = @$row[13];
|
||||
$automap = @$row[14];
|
||||
$skipcrossduplicates = @$row[15];
|
||||
$maxbytespersecond = @$row[16];
|
||||
|
||||
$is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1 WHERE id = ?");
|
||||
$is_running->bind_param( 1, ${id} );
|
||||
|
@ -72,11 +75,14 @@ while ($row = $sth->fetchrow_arrayref()) {
|
|||
"--tmpdir", "/tmp",
|
||||
"--subscribeall",
|
||||
($exclude eq "" ? () : ("--exclude", $exclude)),
|
||||
($subfolder2 eq "" ? () : ('--subfolder2', $subfolder2)),
|
||||
($maxage eq "0" ? () : ('--maxage', $maxage)),
|
||||
($delete2duplicates ne "1" ? () : ('--delete2duplicates')),
|
||||
($delete1 ne "1" ? () : ('--delete')),
|
||||
($delete2 ne "1" ? () : ('--delete2')),
|
||||
($subfolder2 eq "" ? () : ('--subfolder2', $subfolder2)),
|
||||
($maxage eq "0" ? () : ('--maxage', $maxage)),
|
||||
($maxbytespersecond eq "0" ? () : ('--maxbytespersecond', $maxage)),
|
||||
($delete2duplicates ne "1" ? () : ('--delete2duplicates')),
|
||||
($delete1 ne "1" ? () : ('--delete')),
|
||||
($delete2 ne "1" ? () : ('--delete2')),
|
||||
($automap ne "1" ? () : ('--automap')),
|
||||
($skipcrossduplicates ne "1" ? () : ('--skipcrossduplicates')),
|
||||
(!defined($enc1) ? () : ($enc1)),
|
||||
"--host1", $host1,
|
||||
"--user1", $user1,
|
||||
|
|
|
@ -14,11 +14,11 @@ import json
|
|||
|
||||
yes_regex = re.compile(r'([yY][eE][sS]|[yY])+$')
|
||||
if re.search(yes_regex, os.getenv('SKIP_FAIL2BAN', 0)):
|
||||
print "SKIP_FAIL2BAN=y, Skipping Fail2ban container..."
|
||||
print 'SKIP_FAIL2BAN=y, Skipping Fail2ban container...'
|
||||
time.sleep(31536000)
|
||||
raise SystemExit
|
||||
|
||||
r = redis.StrictRedis(host='172.22.1.249', decode_responses=True, port=6379, db=0)
|
||||
r = redis.StrictRedis(host=os.getenv('IPV4_NETWORK', '172.22.1') + '.249', decode_responses=True, port=6379, db=0)
|
||||
pubsub = r.pubsub()
|
||||
|
||||
RULES = {}
|
||||
|
@ -29,19 +29,23 @@ RULES[4] = '-login: Aborted login \(tried to use disallowed .+\): user=.+, rip=(
|
|||
RULES[5] = 'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked'
|
||||
RULES[6] = 'mailcow UI: Invalid password for .+ by ([0-9a-f\.:]+)'
|
||||
|
||||
r.setnx("F2B_BAN_TIME", "1800")
|
||||
r.setnx("F2B_MAX_ATTEMPTS", "10")
|
||||
r.setnx("F2B_RETRY_WINDOW", "600")
|
||||
r.setnx('F2B_BAN_TIME', '1800')
|
||||
r.setnx('F2B_MAX_ATTEMPTS', '10')
|
||||
r.setnx('F2B_RETRY_WINDOW', '600')
|
||||
r.setnx('F2B_NETBAN_IPV6', '64')
|
||||
r.setnx('F2B_NETBAN_IPV4', '24')
|
||||
|
||||
bans = {}
|
||||
log = {}
|
||||
quit_now = False
|
||||
|
||||
def ban(address):
|
||||
BAN_TIME = int(r.get("F2B_BAN_TIME"))
|
||||
MAX_ATTEMPTS = int(r.get("F2B_MAX_ATTEMPTS"))
|
||||
RETRY_WINDOW = int(r.get("F2B_RETRY_WINDOW"))
|
||||
WHITELIST = r.hgetall("F2B_WHITELIST")
|
||||
BAN_TIME = int(r.get('F2B_BAN_TIME'))
|
||||
MAX_ATTEMPTS = int(r.get('F2B_MAX_ATTEMPTS'))
|
||||
RETRY_WINDOW = int(r.get('F2B_RETRY_WINDOW'))
|
||||
WHITELIST = r.hgetall('F2B_WHITELIST')
|
||||
NETBAN_IPV6 = '/' + str(r.get('F2B_NETBAN_IPV6'))
|
||||
NETBAN_IPV4 = '/' + str(r.get('F2B_NETBAN_IPV4'))
|
||||
|
||||
ip = ipaddress.ip_address(address.decode('ascii'))
|
||||
if type(ip) is ipaddress.IPv6Address and ip.ipv4_mapped:
|
||||
|
@ -56,13 +60,13 @@ def ban(address):
|
|||
wl_net = ipaddress.ip_network(wl_key.decode('ascii'), False)
|
||||
if wl_net.overlaps(self_network):
|
||||
log['time'] = int(round(time.time()))
|
||||
log['priority'] = "info"
|
||||
log['message'] = "Address %s is whitelisted by rule %s" % (self_network, wl_net)
|
||||
r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False))
|
||||
print "Address %s is whitelisted by rule %s" % (self_network, wl_net)
|
||||
log['priority'] = 'info'
|
||||
log['message'] = 'Address %s is whitelisted by rule %s' % (self_network, wl_net)
|
||||
r.lpush('F2B_LOG', json.dumps(log, ensure_ascii=False))
|
||||
print 'Address %s is whitelisted by rule %s' % (self_network, wl_net)
|
||||
return
|
||||
|
||||
net = ipaddress.ip_network((address + ('/24' if type(ip) is ipaddress.IPv4Address else '/64')).decode('ascii'), strict=False)
|
||||
net = ipaddress.ip_network((address + (NETBAN_IPV4 if type(ip) is ipaddress.IPv4Address else NETBAN_IPV6)).decode('ascii'), strict=False)
|
||||
net = str(net)
|
||||
|
||||
if not net in bans or time.time() - bans[net]['last_attempt'] > RETRY_WINDOW:
|
||||
|
@ -78,45 +82,45 @@ def ban(address):
|
|||
|
||||
if bans[net]['attempts'] >= MAX_ATTEMPTS:
|
||||
log['time'] = int(round(time.time()))
|
||||
log['priority'] = "crit"
|
||||
log['message'] = "Banning %s" % net
|
||||
r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False))
|
||||
print "Banning %s for %d minutes" % (net, BAN_TIME / 60)
|
||||
log['priority'] = 'crit'
|
||||
log['message'] = 'Banning %s' % net
|
||||
r.lpush('F2B_LOG', json.dumps(log, ensure_ascii=False))
|
||||
print 'Banning %s for %d minutes' % (net, BAN_TIME / 60)
|
||||
if type(ip) is ipaddress.IPv4Address:
|
||||
subprocess.call(["iptables", "-I", "INPUT", "-s", net, "-j", "REJECT"])
|
||||
subprocess.call(["iptables", "-I", "FORWARD", "-s", net, "-j", "REJECT"])
|
||||
subprocess.call(['iptables', '-I', 'INPUT', '-s', net, '-j', 'REJECT'])
|
||||
subprocess.call(['iptables', '-I', 'FORWARD', '-s', net, '-j', 'REJECT'])
|
||||
else:
|
||||
subprocess.call(["ip6tables", "-I", "INPUT", "-s", net, "-j", "REJECT"])
|
||||
subprocess.call(["ip6tables", "-I", "FORWARD", "-s", net, "-j", "REJECT"])
|
||||
r.hset("F2B_ACTIVE_BANS", "%s" % net, log['time'] + BAN_TIME)
|
||||
subprocess.call(['ip6tables', '-I', 'INPUT', '-s', net, '-j', 'REJECT'])
|
||||
subprocess.call(['ip6tables', '-I', 'FORWARD', '-s', net, '-j', 'REJECT'])
|
||||
r.hset('F2B_ACTIVE_BANS', '%s' % net, log['time'] + BAN_TIME)
|
||||
else:
|
||||
log['time'] = int(round(time.time()))
|
||||
log['priority'] = "warn"
|
||||
log['message'] = "%d more attempts in the next %d seconds until %s is banned" % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net)
|
||||
r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False))
|
||||
print "%d more attempts in the next %d seconds until %s is banned" % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net)
|
||||
log['priority'] = 'warn'
|
||||
log['message'] = '%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net)
|
||||
r.lpush('F2B_LOG', json.dumps(log, ensure_ascii=False))
|
||||
print '%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net)
|
||||
|
||||
def unban(net):
|
||||
log['time'] = int(round(time.time()))
|
||||
log['priority'] = "info"
|
||||
r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False))
|
||||
log['priority'] = 'info'
|
||||
r.lpush('F2B_LOG', json.dumps(log, ensure_ascii=False))
|
||||
if not net in bans:
|
||||
log['message'] = "%s is not banned, skipping unban and deleting from queue (if any)" % net
|
||||
r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False))
|
||||
print "%s is not banned, skipping unban and deleting from queue (if any)" % net
|
||||
r.hdel("F2B_QUEUE_UNBAN", "%s" % net)
|
||||
log['message'] = '%s is not banned, skipping unban and deleting from queue (if any)' % net
|
||||
r.lpush('F2B_LOG', json.dumps(log, ensure_ascii=False))
|
||||
print '%s is not banned, skipping unban and deleting from queue (if any)' % net
|
||||
r.hdel('F2B_QUEUE_UNBAN', '%s' % net)
|
||||
return
|
||||
log['message'] = "Unbanning %s" % net
|
||||
r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False))
|
||||
print "Unbanning %s" % net
|
||||
log['message'] = 'Unbanning %s' % net
|
||||
r.lpush('F2B_LOG', json.dumps(log, ensure_ascii=False))
|
||||
print 'Unbanning %s' % net
|
||||
if type(ipaddress.ip_network(net.decode('ascii'))) is ipaddress.IPv4Network:
|
||||
subprocess.call(["iptables", "-D", "INPUT", "-s", net, "-j", "REJECT"])
|
||||
subprocess.call(["iptables", "-D", "FORWARD", "-s", net, "-j", "REJECT"])
|
||||
subprocess.call(['iptables', '-D', 'INPUT', '-s', net, '-j', 'REJECT'])
|
||||
subprocess.call(['iptables', '-D', 'FORWARD', '-s', net, '-j', 'REJECT'])
|
||||
else:
|
||||
subprocess.call(["ip6tables", "-D", "INPUT", "-s", net, "-j", "REJECT"])
|
||||
subprocess.call(["ip6tables", "-D", "FORWARD", "-s", net, "-j", "REJECT"])
|
||||
r.hdel("F2B_ACTIVE_BANS", "%s" % net)
|
||||
r.hdel("F2B_QUEUE_UNBAN", "%s" % net)
|
||||
subprocess.call(['ip6tables', '-D', 'INPUT', '-s', net, '-j', 'REJECT'])
|
||||
subprocess.call(['ip6tables', '-D', 'FORWARD', '-s', net, '-j', 'REJECT'])
|
||||
r.hdel('F2B_ACTIVE_BANS', '%s' % net)
|
||||
r.hdel('F2B_QUEUE_UNBAN', '%s' % net)
|
||||
del bans[net]
|
||||
|
||||
def quit(signum, frame):
|
||||
|
@ -125,21 +129,21 @@ def quit(signum, frame):
|
|||
|
||||
def clear():
|
||||
log['time'] = int(round(time.time()))
|
||||
log['priority'] = "info"
|
||||
log['message'] = "Clearing all bans"
|
||||
r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False))
|
||||
print "Clearing all bans"
|
||||
log['priority'] = 'info'
|
||||
log['message'] = 'Clearing all bans'
|
||||
r.lpush('F2B_LOG', json.dumps(log, ensure_ascii=False))
|
||||
print 'Clearing all bans'
|
||||
for net in bans.copy():
|
||||
unban(net)
|
||||
pubsub.unsubscribe()
|
||||
|
||||
def watch():
|
||||
log['time'] = int(round(time.time()))
|
||||
log['priority'] = "info"
|
||||
log['message'] = "Watching Redis channel F2B_CHANNEL"
|
||||
r.lpush("F2B_LOG", json.dumps(log, ensure_ascii=False))
|
||||
pubsub.subscribe("F2B_CHANNEL")
|
||||
print "Subscribing to Redis channel F2B_CHANNEL"
|
||||
log['priority'] = 'info'
|
||||
log['message'] = 'Watching Redis channel F2B_CHANNEL'
|
||||
r.lpush('F2B_LOG', json.dumps(log, ensure_ascii=False))
|
||||
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():
|
||||
|
@ -150,18 +154,18 @@ def watch():
|
|||
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)
|
||||
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))
|
||||
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:
|
||||
BAN_TIME = int(r.get("F2B_BAN_TIME"))
|
||||
MAX_ATTEMPTS = int(r.get("F2B_MAX_ATTEMPTS"))
|
||||
QUEUE_UNBAN = r.hgetall("F2B_QUEUE_UNBAN")
|
||||
BAN_TIME = int(r.get('F2B_BAN_TIME'))
|
||||
MAX_ATTEMPTS = int(r.get('F2B_MAX_ATTEMPTS'))
|
||||
QUEUE_UNBAN = r.hgetall('F2B_QUEUE_UNBAN')
|
||||
if QUEUE_UNBAN:
|
||||
for net in QUEUE_UNBAN:
|
||||
unban(str(net))
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
FROM php:7.1-fpm-alpine
|
||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||
|
||||
ENV REDIS_PECL 3.1.4
|
||||
ENV MEMCACHED_PECL 3.0.3
|
||||
ENV APCU_PECL 5.1.8
|
||||
ENV REDIS_PECL 3.1.6
|
||||
ENV MEMCACHED_PECL 3.0.4
|
||||
ENV APCU_PECL 5.1.9
|
||||
ENV IMAGICK_PECL 3.4.3
|
||||
ENV MAILPARSE_PECL 3.0.2
|
||||
|
||||
RUN apk add -U --no-cache libxml2-dev \
|
||||
icu-dev \
|
||||
|
@ -41,27 +42,16 @@ RUN apk add -U --no-cache libxml2-dev \
|
|||
Net_Sieve \
|
||||
NET_SMTP \
|
||||
Mail_mime \
|
||||
&& pecl install redis-${REDIS_PECL} memcached-${MEMCACHED_PECL} APCu-${APCU_PECL} imagick-${IMAGICK_PECL} mailparse \
|
||||
&& pecl install redis-${REDIS_PECL} memcached-${MEMCACHED_PECL} APCu-${APCU_PECL} imagick-${IMAGICK_PECL} mailparse-${MAILPARSE_PECL} \
|
||||
&& docker-php-ext-enable redis apcu memcached imagick mailparse \
|
||||
&& pecl clear-cache \
|
||||
&& docker-php-ext-configure intl \
|
||||
&& 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 \
|
||||
&& { \
|
||||
echo 'opcache.enable=1'; \
|
||||
echo 'opcache.enable_cli=1'; \
|
||||
echo 'opcache.interned_strings_buffer=8'; \
|
||||
echo 'opcache.max_accelerated_files=10000'; \
|
||||
echo 'opcache.memory_consumption=128'; \
|
||||
echo 'opcache.save_comments=1'; \
|
||||
echo 'opcache.revalidate_freq=1'; \
|
||||
} > /usr/local/etc/php/conf.d/opcache-recommended.ini
|
||||
&& 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
|
||||
|
||||
COPY ./docker-entrypoint.sh /
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
CMD ["php-fpm"]
|
||||
|
|
|
@ -26,7 +26,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
syslog-ng-core \
|
||||
syslog-ng-mod-redis \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& touch /etc/default/locale
|
||||
&& touch /etc/default/locale \
|
||||
&& printf '#!/bin/bash\n/usr/sbin/postconf -c /opt/postfix/conf "$@"' > /usr/local/sbin/postconf \
|
||||
&& chmod +x /usr/local/sbin/postconf
|
||||
|
||||
RUN addgroup --system --gid 600 zeyple
|
||||
RUN adduser --system --home /var/lib/zeyple --no-create-home --uid 600 --gid 600 --disabled-login zeyple
|
||||
|
|
|
@ -6,7 +6,7 @@ while read QUERY; do
|
|||
echo "500 dunno"
|
||||
continue
|
||||
fi
|
||||
result=$(curl -s http://172.22.1.251:8081/forwardinghosts.php?host=${QUERY[1]})
|
||||
result=$(curl -s http://nginx:8081/forwardinghosts.php?host=${QUERY[1]})
|
||||
logger -t whitelist_forwardinghosts -p mail.info "Look up ${QUERY[1]} on whitelist, result $result"
|
||||
echo ${result}
|
||||
done
|
||||
|
|
|
@ -1 +1 @@
|
|||
settings = "http://172.22.1.251:8081/settings.php";
|
||||
settings = "http://nginx:8081/settings.php";
|
||||
|
|
|
@ -18,11 +18,13 @@ done
|
|||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view"
|
||||
|
||||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, home, kind, multiple_bookings) AS
|
||||
SELECT mailbox.username, mailbox.domain, mailbox.username, mailbox.password, mailbox.name, mailbox.username, IFNULL(ga.aliases, ''), IFNULL(gda.ad_alias, ''), CONCAT('/var/vmail/', maildir), mailbox.kind, mailbox.multiple_bookings FROM mailbox
|
||||
LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username = mailbox.username
|
||||
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, sa_aliases, ad_aliases, home, kind, multiple_bookings) AS
|
||||
SELECT mailbox.username, mailbox.domain, mailbox.username, mailbox.password, mailbox.name, mailbox.username, IFNULL(GROUP_CONCAT(ga.aliases SEPARATOR ' '), ''), IFNULL(gsa.send_as_acl, ''), IFNULL(gda.ad_alias, ''), CONCAT('/var/vmail/', maildir), mailbox.kind, mailbox.multiple_bookings FROM mailbox
|
||||
LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)')
|
||||
LEFT OUTER JOIN grouped_sender_acl gsa ON gsa.username = mailbox.username
|
||||
LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username
|
||||
WHERE mailbox.active = '1';
|
||||
WHERE mailbox.active = '1'
|
||||
GROUP BY mailbox.username;
|
||||
EOF
|
||||
|
||||
|
||||
|
@ -67,6 +69,7 @@ while read line
|
|||
<key>MailFieldNames</key>
|
||||
<array>
|
||||
<string>aliases</string>
|
||||
<string>sa_aliases</string>
|
||||
<string>ad_aliases</string>
|
||||
</array>
|
||||
<key>KindFieldName</key>
|
||||
|
|
|
@ -191,6 +191,7 @@ phpfpm_checks() {
|
|||
host_ip=$(get_container_ip php-fpm-mailcow)
|
||||
err_c_cur=${err_count}
|
||||
cgi-fcgi -bind -connect ${host_ip}:9000 | grep "Content-type" 1>&2; err_count=$(( ${err_count} + ($? * 2)))
|
||||
cgi-fcgi -bind -connect ${host_ip}:9001 | grep "Content-type" 1>&2; err_count=$(( ${err_count} + ($? * 2)))
|
||||
/usr/lib/nagios/plugins/check_ping -4 -H ${host_ip} -w 2000,10% -c 4000,100% -p2 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
[ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
|
||||
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
|
||||
|
|
|
@ -25,7 +25,7 @@ server {
|
|||
add_header X-Download-Options noopen;
|
||||
add_header X-Permitted-Cross-Domain-Policies none;
|
||||
|
||||
server_name NC_SERVER_SUB;
|
||||
server_name NC_SUBD;
|
||||
|
||||
root /web/nextcloud/;
|
||||
|
||||
|
@ -48,8 +48,10 @@ server {
|
|||
gzip_min_length 256;
|
||||
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
||||
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
|
||||
|
||||
set_real_ip_from 172.22.1.1;
|
||||
set_real_ip_from fd00::/8;
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
|
@ -112,7 +114,7 @@ server {
|
|||
add_header X-Download-Options noopen;
|
||||
add_header X-Permitted-Cross-Domain-Policies none;
|
||||
|
||||
server_name NC_SERVER_SUB;
|
||||
server_name NC_SUBD;
|
||||
|
||||
root /web/nextcloud/;
|
||||
|
||||
|
@ -135,8 +137,10 @@ server {
|
|||
gzip_min_length 256;
|
||||
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
||||
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
|
||||
|
||||
set_real_ip_from 172.22.1.1;
|
||||
set_real_ip_from fd00::/8;
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
LogFile /tmp/logpipe_clamd
|
||||
LogTime yes
|
||||
LogClean yes
|
||||
ExtendedDetectionInfo yes
|
||||
PidFile /run/clamav/clamd.pid
|
||||
OfficialDatabaseOnly no
|
||||
LocalSocket /run/clamav/clamd.sock
|
||||
TCPSocket 3310
|
||||
StreamMaxLength 25M
|
||||
MaxThreads 10
|
||||
ReadTimeout 10
|
||||
CommandReadTimeout 3
|
||||
SendBufTimeout 200
|
||||
MaxQueue 80
|
||||
IdleTimeout 20
|
||||
SelfCheck 3600
|
||||
User clamav
|
||||
AllowSupplementaryGroups yes
|
||||
Foreground yes
|
||||
DetectPUA yes
|
||||
# See https://github.com/vrtadmin/clamav-faq/blob/master/faq/faq-pua.md
|
||||
#ExcludePUA NetTool
|
||||
#ExcludePUA PWTool
|
||||
#IncludePUA Spy
|
||||
#IncludePUA Scanner
|
||||
#IncludePUA RAT
|
||||
AlgorithmicDetection yes
|
||||
ScanOLE2 yes
|
||||
OLE2BlockMacros yes
|
||||
ScanPDF yes
|
||||
ScanSWF yes
|
||||
ScanXMLDOCS yes
|
||||
ScanHWP3 yes
|
||||
ScanMail yes
|
||||
PhishingSignatures no
|
||||
PhishingScanURLs no
|
||||
HeuristicScanPrecedence yes
|
||||
ScanHTML yes
|
||||
ScanArchive yes
|
||||
MaxScanSize 50M
|
||||
MaxFileSize 25M
|
||||
MaxRecursion 5
|
||||
MaxFiles 200
|
||||
ScanOnAccess no
|
||||
Bytecode yes
|
||||
BytecodeSecurity TrustSigned
|
||||
BytecodeTimeout 1000
|
|
@ -0,0 +1,17 @@
|
|||
UpdateLogFile /tmp/logpipe_freshclam
|
||||
LogTime yes
|
||||
PidFile /run/clamav/freshclam.pid
|
||||
DatabaseOwner clamav
|
||||
AllowSupplementaryGroups yes
|
||||
DNSDatabaseInfo current.cvd.clamav.net
|
||||
DatabaseMirror database.clamav.net
|
||||
MaxAttempts 4
|
||||
ScriptedUpdates yes
|
||||
Checks 6
|
||||
NotifyClamd /etc/clamav/clamd.conf
|
||||
Foreground yes
|
||||
ConnectTimeout 20
|
||||
ReceiveTimeout 20
|
||||
TestDatabases yes
|
||||
Bytecode yes
|
||||
|
|
@ -10,7 +10,7 @@ server {
|
|||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9000;
|
||||
fastcgi_pass phpfpm:9001;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
|
|
@ -7,6 +7,13 @@ map $http_x_forwarded_proto $client_req_scheme {
|
|||
https https;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
include /etc/nginx/conf.d/server_name.active;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
include /etc/nginx/mime.types;
|
||||
charset utf-8;
|
||||
|
@ -17,6 +24,7 @@ server {
|
|||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Robots-Tag none;
|
||||
add_header X-Download-Options noopen;
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
add_header X-Permitted-Cross-Domain-Policies none;
|
||||
|
||||
index index.php index.html;
|
||||
|
@ -39,7 +47,10 @@ server {
|
|||
}
|
||||
|
||||
# If behind reverse proxy, forwards the correct IP
|
||||
set_real_ip_from 172.22.1.1;
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
set_real_ip_from fd00::/8;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
|
@ -65,7 +76,7 @@ server {
|
|||
}
|
||||
|
||||
location /rspamd/ {
|
||||
proxy_pass http://172.22.1.253:11334/;
|
||||
proxy_pass http://rspamd:11334/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
|
@ -97,7 +108,7 @@ server {
|
|||
}
|
||||
|
||||
location ^~ /Microsoft-Server-ActiveSync {
|
||||
proxy_pass http://172.22.1.252:20000/SOGo/Microsoft-Server-ActiveSync;
|
||||
proxy_pass http://sogo:20000/SOGo/Microsoft-Server-ActiveSync;
|
||||
proxy_connect_timeout 1000;
|
||||
proxy_next_upstream timeout error;
|
||||
proxy_send_timeout 1000;
|
||||
|
@ -119,7 +130,7 @@ server {
|
|||
}
|
||||
|
||||
location ^~ /SOGo {
|
||||
proxy_pass http://172.22.1.252:20000;
|
||||
proxy_pass http://sogo:20000;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
|
@ -134,7 +145,7 @@ server {
|
|||
}
|
||||
|
||||
location /SOGo.woa/WebServerResources/ {
|
||||
proxy_pass http://172.22.1.252:9192/WebServerResources/;
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -144,7 +155,7 @@ server {
|
|||
}
|
||||
|
||||
location /.woa/WebServerResources/ {
|
||||
proxy_pass http://172.22.1.252:9192/WebServerResources/;
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -154,7 +165,7 @@ server {
|
|||
}
|
||||
|
||||
location /SOGo/WebServerResources/ {
|
||||
proxy_pass http://172.22.1.252:9192/WebServerResources/;
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -164,7 +175,7 @@ server {
|
|||
}
|
||||
|
||||
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$ {
|
||||
proxy_pass http://172.22.1.252:9192/$1.SOGo/Resources/$2;
|
||||
proxy_pass http://sogo:9192/$1.SOGo/Resources/$2;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -195,6 +206,7 @@ server {
|
|||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Robots-Tag none;
|
||||
add_header X-Download-Options noopen;
|
||||
add_header X-Frame-Options "SAMEORIGIN";
|
||||
add_header X-Permitted-Cross-Domain-Policies none;
|
||||
|
||||
index index.php index.html;
|
||||
|
@ -217,7 +229,10 @@ server {
|
|||
}
|
||||
|
||||
# If behind reverse proxy, forwards the correct IP
|
||||
set_real_ip_from 172.22.1.1;
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
set_real_ip_from fd00::/8;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
|
@ -243,7 +258,7 @@ server {
|
|||
}
|
||||
|
||||
location /rspamd/ {
|
||||
proxy_pass http://172.22.1.253:11334/;
|
||||
proxy_pass http://rspamd:11334/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
|
@ -275,7 +290,7 @@ server {
|
|||
}
|
||||
|
||||
location ^~ /Microsoft-Server-ActiveSync {
|
||||
proxy_pass http://172.22.1.252:20000/SOGo/Microsoft-Server-ActiveSync;
|
||||
proxy_pass http://sogo:20000/SOGo/Microsoft-Server-ActiveSync;
|
||||
proxy_connect_timeout 1000;
|
||||
proxy_next_upstream timeout error;
|
||||
proxy_send_timeout 1000;
|
||||
|
@ -297,7 +312,7 @@ server {
|
|||
}
|
||||
|
||||
location ^~ /SOGo {
|
||||
proxy_pass http://172.22.1.252:20000;
|
||||
proxy_pass http://sogo:20000;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
|
@ -312,7 +327,7 @@ server {
|
|||
}
|
||||
|
||||
location /SOGo.woa/WebServerResources/ {
|
||||
proxy_pass http://172.22.1.252:9192/WebServerResources/;
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -322,7 +337,7 @@ server {
|
|||
}
|
||||
|
||||
location /.woa/WebServerResources/ {
|
||||
proxy_pass http://172.22.1.252:9192/WebServerResources/;
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -332,7 +347,7 @@ server {
|
|||
}
|
||||
|
||||
location /SOGo/WebServerResources/ {
|
||||
proxy_pass http://172.22.1.252:9192/WebServerResources/;
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
@ -342,7 +357,7 @@ server {
|
|||
}
|
||||
|
||||
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$ {
|
||||
proxy_pass http://172.22.1.252:9192/$1.SOGo/Resources/$2;
|
||||
proxy_pass http://sogo:9192/$1.SOGo/Resources/$2;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.interned_strings_buffer=8
|
||||
opcache.max_accelerated_files=10000
|
||||
opcache.memory_consumption=128
|
||||
opcache.save_comments=1
|
||||
opcache.revalidate_freq=1
|
|
@ -0,0 +1,12 @@
|
|||
[system]
|
||||
user = www-data
|
||||
group = www-data
|
||||
pm = dynamic
|
||||
pm.max_children = 10
|
||||
pm.start_servers = 2
|
||||
pm.min_spare_servers = 2
|
||||
pm.max_spare_servers = 4
|
||||
listen = [::]:9001
|
||||
access.log = /proc/self/fd/2
|
||||
clear_env = no
|
||||
catch_workers_output = yes
|
|
@ -0,0 +1,11 @@
|
|||
[www]
|
||||
user = www-data
|
||||
group = www-data
|
||||
pm = ondemand
|
||||
pm.max_children = 20
|
||||
pm.process_idle_timeout = 20s
|
||||
pm.max_requests = 800
|
||||
listen = [::]:9001
|
||||
access.log = /proc/self/fd/2
|
||||
clear_env = no
|
||||
catch_workers_output = yes
|
|
@ -9,7 +9,7 @@ smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_una
|
|||
alias_maps = hash:/etc/aliases
|
||||
alias_database = hash:/etc/aliases
|
||||
relayhost =
|
||||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 [fd4d:6169:6c63:6f77::]/64
|
||||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 [fd::]/8
|
||||
mailbox_size_limit = 0
|
||||
recipient_delimiter = +
|
||||
inet_interfaces = all
|
||||
|
|
|
@ -196,7 +196,7 @@ while ($row = array_shift($rows)) {
|
|||
}
|
||||
whitelist_header_<?=$username_sane;?> {
|
||||
<?php
|
||||
$stmt = $pdo->prepare("SELECT GROUP_CONCAT(REPLACE(CONCAT('^', `value`, '$'), '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf`
|
||||
$stmt = $pdo->prepare("SELECT GROUP_CONCAT(REPLACE(CONCAT('\<', `value`, '\>'), '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf`
|
||||
WHERE `object`= :object
|
||||
AND `option` = 'whitelist_from'");
|
||||
$stmt->execute(array(':object' => $row['object']));
|
||||
|
@ -288,7 +288,7 @@ while ($row = array_shift($rows)) {
|
|||
}
|
||||
blacklist_header_<?=$username_sane;?> {
|
||||
<?php
|
||||
$stmt = $pdo->prepare("SELECT GROUP_CONCAT(REPLACE(CONCAT('^', `value`, '$'), '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf`
|
||||
$stmt = $pdo->prepare("SELECT GROUP_CONCAT(REPLACE(CONCAT('\<', `value`, '\>'), '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf`
|
||||
WHERE `object`= :object
|
||||
AND `option` = 'blacklist_from'");
|
||||
$stmt->execute(array(':object' => $row['object']));
|
||||
|
|
|
@ -1 +1 @@
|
|||
whitelisted_ip = "http://172.22.1.251:8081/forwardinghosts.php";
|
||||
whitelisted_ip = "http://nginx:8081/forwardinghosts.php";
|
||||
|
|
|
@ -4,6 +4,6 @@ secure_ip = "172.16.0.0/12";
|
|||
secure_ip = "10.0.0.0/8";
|
||||
secure_ip = "127.0.0.1";
|
||||
secure_ip = "::1";
|
||||
secure_ip = "fd4d:6169:6c63:6f77::/64"
|
||||
secure_ip = "fd00::/8"
|
||||
.include(try=true; priority=10) "$CONFDIR/override.d/worker-controller-password.inc"
|
||||
.include(try=true; priority=20) "$CONFDIR/override.d/worker-controller.custom.inc"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
PrivateDAndTViewer
|
||||
);
|
||||
|
||||
WOWorkersCount = "20";
|
||||
WOWorkersCount = "7";
|
||||
SOGoACLsSendEMailNotifications = YES;
|
||||
SOGoAppointmentSendEMailNotifications = YES;
|
||||
SOGoDraftsFolderName = "Drafts";
|
||||
|
@ -36,7 +36,7 @@
|
|||
SOGoMailingMechanism = smtp;
|
||||
SOGoSMTPAuthenticationType = plain;
|
||||
|
||||
SxVMemLimit = 512;
|
||||
SxVMemLimit = 384;
|
||||
|
||||
SOGoMaximumPingInterval = 354;
|
||||
|
||||
|
|
|
@ -8,8 +8,11 @@ server:
|
|||
do-udp: yes
|
||||
do-tcp: yes
|
||||
do-daemonize: no
|
||||
access-control: 172.22.1.0/24 allow
|
||||
access-control: fd4d:6169:6c63:6f77::/64 allow
|
||||
access-control: 10.0.0.0/8 allow
|
||||
access-control: 172.16.0.0/12 allow
|
||||
access-control: 192.168.0.0/16 allow
|
||||
access-control: fd00::/8 allow
|
||||
access-control: fe80::/10 allow
|
||||
directory: "/etc/unbound"
|
||||
username: unbound
|
||||
auto-trust-anchor-file: trusted-key.key
|
||||
|
@ -19,7 +22,6 @@ server:
|
|||
private-address: 169.254.0.0/16
|
||||
private-address: fd00::/8
|
||||
private-address: fe80::/10
|
||||
private-address: fd4d:6169:6c63:6f77::/64
|
||||
root-hints: "/etc/unbound/root.hints"
|
||||
hide-identity: yes
|
||||
hide-version: yes
|
||||
|
|
|
@ -168,29 +168,31 @@ $tfa_data = get_tfa();
|
|||
if (!empty($dkim = dkim('details', $domain))) {
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" /></div>
|
||||
<div class="col-xs-2">
|
||||
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" /></div>
|
||||
<div class="col-md-3">
|
||||
<p>Domain: <strong><?=htmlspecialchars($domain);?></strong>
|
||||
<p><span class="label label-success"><?=$lang['admin']['dkim_key_valid'];?></span></p>
|
||||
<p><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
|
||||
<p><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
|
||||
<p class="dkim-label"><span class="label label-success"><?=$lang['admin']['dkim_key_valid'];?></span></p>
|
||||
<p class="dkim-label"><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
|
||||
<p class="dkim-label"><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-xs-9">
|
||||
<div class="col-md-8">
|
||||
<pre><?=$dkim['dkim_txt'];?></pre>
|
||||
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="<?=$dkim['privkey'];?>"><small>↪ Private key</small></p>
|
||||
</div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
else {
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" disabled /></div>
|
||||
<div class="col-xs-2">
|
||||
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" disabled /></div>
|
||||
<div class="col-md-3">
|
||||
<p>Domain: <strong><?=htmlspecialchars($domain);?></strong><br /><span class="label label-danger"><?=$lang['admin']['dkim_key_missing'];?></span></p>
|
||||
</div>
|
||||
<div class="col-xs-9"><pre>-</pre></div>
|
||||
<div class="col-md-8"><pre>-</pre></div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
@ -198,29 +200,31 @@ $tfa_data = get_tfa();
|
|||
if (!empty($dkim = dkim('details', $alias_domain))) {
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$alias_domain;?>" /></div>
|
||||
<div class="col-xs-1 col-xs-offset-1">
|
||||
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$alias_domain;?>" /></div>
|
||||
<div class="col-md-2 col-md-offset-1">
|
||||
<p><small>↳ Alias-Domain: <strong><?=htmlspecialchars($alias_domain);?></strong></small>
|
||||
<p><span class="label label-success"><?=$lang['admin']['dkim_key_valid'];?></span></p>
|
||||
<p><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
|
||||
<p><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
|
||||
<p class="dkim-label"><span class="label label-success"><?=$lang['admin']['dkim_key_valid'];?></span></p>
|
||||
<p class="dkim-label"><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
|
||||
<p class="dkim-label"><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-xs-9">
|
||||
<div class="col-md-8">
|
||||
<pre><?=$dkim['dkim_txt'];?></pre>
|
||||
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="<?=$dkim['privkey'];?>"><small>↪ Private key</small></p>
|
||||
</div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
else {
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" disabled /></div>
|
||||
<div class="col-xs-1 col-xs-offset-1">
|
||||
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$domain;?>" disabled /></div>
|
||||
<div class="col-md-2 col-md-offset-1">
|
||||
<p><small>↳ Alias-Domain: <strong><?=htmlspecialchars($alias_domain);?></strong><br /></small><span class="label label-danger"><?=$lang['admin']['dkim_key_missing'];?></span></p>
|
||||
</div>
|
||||
<div class="col-xs-9"><pre>-</pre></div>
|
||||
<div class="col-md-8"><pre>-</pre></div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
@ -230,18 +234,19 @@ $tfa_data = get_tfa();
|
|||
if (!empty($dkim = dkim('details', $blind))) {
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-xs-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$blind;?>" /></div>
|
||||
<div class="col-xs-2">
|
||||
<div class="col-md-1"><input type="checkbox" data-id="dkim" name="multi_select" value="<?=$blind;?>" /></div>
|
||||
<div class="col-md-3">
|
||||
<p>Domain: <strong><?=htmlspecialchars($blind);?></strong>
|
||||
<p><span class="label label-warning"><?=$lang['admin']['dkim_key_unused'];?></span></p>
|
||||
<p><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
|
||||
<p><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
|
||||
<p class="dkim-label"><span class="label label-warning"><?=$lang['admin']['dkim_key_unused'];?></span></p>
|
||||
<p class="dkim-label"><span class="label label-primary">Selector '<?=$dkim['dkim_selector'];?>'</span></p>
|
||||
<p class="dkim-label"><span class="label label-info"><?=$dkim['length'];?> bit</span></p>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-xs-9">
|
||||
<div class="col-md-8">
|
||||
<pre><?=$dkim['dkim_txt'];?></pre>
|
||||
<p data-toggle="modal" data-target="#showDKIMprivKey" id="dkim_priv" style="cursor:pointer;margin-top:-8pt" data-priv-key="<?=$dkim['privkey'];?>"><small>↪ Private key</small></p>
|
||||
</div>
|
||||
<hr class="visible-xs visible-sm">
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
@ -346,6 +351,20 @@ $tfa_data = get_tfa();
|
|||
<label for="retry_window"><?=$lang['admin']['f2b_retry_window'];?>:</label>
|
||||
<input type="number" class="form-control" id="retry_window" name="retry_window" value="<?=$f2b_data['retry_window'];?>" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="netban_ipv4"><?=$lang['admin']['f2b_netban_ipv4'];?>:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/</span>
|
||||
<input type="number" class="form-control" id="netban_ipv4" name="netban_ipv4" value="<?=$f2b_data['netban_ipv4'];?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="netban_ipv6"><?=$lang['admin']['f2b_netban_ipv6'];?>:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/</span>
|
||||
<input type="number" class="form-control" id="netban_ipv6" name="netban_ipv6" value="<?=$f2b_data['netban_ipv6'];?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="whitelist"><?=$lang['admin']['f2b_whitelist'];?>:</label>
|
||||
<textarea class="form-control" id="whitelist" name="whitelist" rows="5"><?=$f2b_data['whitelist'];?></textarea>
|
||||
|
@ -427,7 +446,7 @@ $tfa_data = get_tfa();
|
|||
?>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-success" id="edit_selected" data-item="self" data-id="quarantaine" data-api-url='edit/quarantaine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-default" id="edit_selected" data-item="self" data-id="quarantaine" data-api-url='edit/quarantaine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -441,7 +460,7 @@ $tfa_data = get_tfa();
|
|||
<form class="form-inline" role="form" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<input type="file" name="main_logo" class="filestyle" data-buttonName="btn-default" data-buttonText="Select" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml">
|
||||
<button name="submit_main_logo" type="submit" class="btn btn-success"><span class="glyphicon glyphicon-cloud-upload"></span> <?=$lang['admin']['upload'];?></button>
|
||||
<button name="submit_main_logo" type="submit" class="btn btn-default"><span class="glyphicon glyphicon-cloud-upload"></span> <?=$lang['admin']['upload'];?></button>
|
||||
</p>
|
||||
</form>
|
||||
<?php
|
||||
|
@ -501,7 +520,7 @@ $tfa_data = get_tfa();
|
|||
?>
|
||||
</table>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-success" id="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-sm btn-default" id="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-sm btn-default" type="button" id="add_app_link_row"><?=$lang['admin']['add_row'];?></button>
|
||||
</div></p>
|
||||
</form>
|
||||
|
@ -526,7 +545,7 @@ $tfa_data = get_tfa();
|
|||
<label for="help_text"><?=$lang['admin']['help_text'];?>:</label>
|
||||
<textarea class="form-control" id="help_text" name="help_text" rows="7"><?=$ui_texts['help_text'];?></textarea>
|
||||
</div>
|
||||
<button class="btn btn-success" id="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-default" id="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -117,3 +117,22 @@ legend {
|
|||
.lang-link-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.dkim-label {
|
||||
margin: 0 0 2px !important;
|
||||
}
|
||||
.overlay {
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
top: 0; right: 0; bottom: 0; left: 0;
|
||||
opacity: 0.7;
|
||||
}
|
||||
nav .glyphicon {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.logged-in-as {
|
||||
border-left: 1px solid #E7E7E7;
|
||||
}
|
||||
#top {
|
||||
padding-top: 70px;
|
||||
}
|
|
@ -661,12 +661,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
$id = $_GET["syncjob"];
|
||||
$result = mailbox('get', 'syncjob_details', $id);
|
||||
if (!empty($result)) {
|
||||
print_r($result);
|
||||
?>
|
||||
<h4><?=$lang['edit']['syncjob'];?></h4>
|
||||
<form class="form-horizontal" data-id="editsyncjob" role="form" method="post">
|
||||
<input type="hidden" value="0" name="delete2duplicates">
|
||||
<input type="hidden" value="0" name="delete1">
|
||||
<input type="hidden" value="0" name="delete2">
|
||||
<input type="hidden" value="0" name="automap">
|
||||
<input type="hidden" value="0" name="skipcrossduplicates">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="host1"><?=$lang['edit']['hostname'];?></label>
|
||||
|
@ -706,6 +709,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<label class="control-label col-sm-2" for="mins_interval"><?=$lang['edit']['mins_interval'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="mins_interval" min="1" max="3600" value="<?=htmlspecialchars($result['mins_interval'], ENT_QUOTES, 'UTF-8');?>" required>
|
||||
<small class="help-block">10-3600</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -717,7 +721,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxage" id="maxage" value="<?=htmlspecialchars($result['maxage'], ENT_QUOTES, 'UTF-8');?>">
|
||||
<input type="number" class="form-control" name="maxage" id="maxage" min="0" max="32000" value="<?=htmlspecialchars($result['maxage'], ENT_QUOTES, 'UTF-8');?>">
|
||||
<small class="help-block">0-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="<?=htmlspecialchars($result['maxbytespersecond'], ENT_QUOTES, 'UTF-8');?>">
|
||||
<small class="help-block">0-125000000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -747,6 +759,20 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="automap" <?=($result['automap']=="1") ? "checked" : "";?>> <?=$lang['edit']['automap'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="skipcrossduplicates" <?=($result['skipcrossduplicates']=="1") ? "checked" : "";?>> <?=$lang['edit']['skipcrossduplicates'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
|
|
|
@ -22,7 +22,9 @@ function setLang(sel) {
|
|||
$.post( "<?= $_SERVER['REQUEST_URI']; ?>", {lang: sel} );
|
||||
window.location.href = window.location.pathname + window.location.search;
|
||||
}
|
||||
|
||||
$(window).load(function() {
|
||||
$(".overlay").hide();
|
||||
});
|
||||
$(document).ready(function() {
|
||||
window.mailcow_alert_box = function(message, type) {
|
||||
msg = $('<span/>').html(message).text();
|
||||
|
|
|
@ -12,6 +12,8 @@ function fail2ban($_action, $_data = null) {
|
|||
$data['ban_time'] = $redis->Get('F2B_BAN_TIME');
|
||||
$data['max_attempts'] = $redis->Get('F2B_MAX_ATTEMPTS');
|
||||
$data['retry_window'] = $redis->Get('F2B_RETRY_WINDOW');
|
||||
$data['netban_ipv4'] = $redis->Get('F2B_NETBAN_IPV4');
|
||||
$data['netban_ipv6'] = $redis->Get('F2B_NETBAN_IPV6');
|
||||
$wl = $redis->hGetAll('F2B_WHITELIST');
|
||||
if (is_array($wl)) {
|
||||
foreach ($wl as $key => $value) {
|
||||
|
@ -50,6 +52,8 @@ function fail2ban($_action, $_data = null) {
|
|||
$ban_time = intval((isset($_data['ban_time'])) ? $_data['ban_time'] : $is_now['ban_time']);
|
||||
$max_attempts = intval((isset($_data['max_attempts'])) ? $_data['max_attempts'] : $is_now['active_int']);
|
||||
$retry_window = intval((isset($_data['retry_window'])) ? $_data['retry_window'] : $is_now['retry_window']);
|
||||
$netban_ipv4 = intval((isset($_data['netban_ipv4'])) ? $_data['netban_ipv4'] : $is_now['netban_ipv4']);
|
||||
$netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']);
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'] = array(
|
||||
|
@ -60,12 +64,20 @@ function fail2ban($_action, $_data = null) {
|
|||
}
|
||||
$wl = $_data['whitelist'];
|
||||
$ban_time = ($ban_time < 60) ? 60 : $ban_time;
|
||||
|
||||
$netban_ipv4 = ($netban_ipv4 < 8) ? 8 : $netban_ipv4;
|
||||
$netban_ipv6 = ($netban_ipv6 < 8) ? 8 : $netban_ipv6;
|
||||
$netban_ipv4 = ($netban_ipv4 > 32) ? 32 : $netban_ipv4;
|
||||
$netban_ipv6 = ($netban_ipv6 > 128) ? 128 : $netban_ipv6;
|
||||
|
||||
$max_attempts = ($max_attempts < 1) ? 1 : $max_attempts;
|
||||
$retry_window = ($retry_window < 1) ? 1 : $retry_window;
|
||||
try {
|
||||
$redis->Set('F2B_BAN_TIME', $ban_time);
|
||||
$redis->Set('F2B_MAX_ATTEMPTS', $max_attempts);
|
||||
$redis->Set('F2B_RETRY_WINDOW', $retry_window);
|
||||
$redis->Set('F2B_NETBAN_IPV4', $netban_ipv4);
|
||||
$redis->Set('F2B_NETBAN_IPV6', $netban_ipv6);
|
||||
$redis->Del('F2B_WHITELIST');
|
||||
if(!empty($wl)) {
|
||||
$wl_array = array_map('trim', preg_split( "/( |,|;|\n)/", $wl));
|
||||
|
|
|
@ -459,8 +459,9 @@ function user_get_alias_details($username) {
|
|||
while ($row = array_shift($run)) {
|
||||
$data['shared_aliases'] = $row['shared_aliases'];
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') AS `direct_aliases` FROM `alias`
|
||||
$stmt = $pdo->prepare("SELECT GROUP_CONCAT(`address` SEPARATOR ', ') AS `direct_aliases` FROM `alias`
|
||||
WHERE `goto` = :username_goto
|
||||
AND `address` NOT LIKE '@%'
|
||||
AND `address` != :username_address");
|
||||
$stmt->execute(
|
||||
array(
|
||||
|
@ -477,7 +478,13 @@ function user_get_alias_details($username) {
|
|||
$stmt->execute(array(':username' => $username));
|
||||
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($run)) {
|
||||
$data['ad_alias'] = $row['ad_alias'];
|
||||
if (empty($data['direct_aliases'])) {
|
||||
$data['direct_aliases'] = $row['ad_alias'];
|
||||
}
|
||||
else {
|
||||
// Probably faster than imploding
|
||||
$data['direct_aliases'] .= ', ' . $row['ad_alias'];
|
||||
}
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '✘') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` NOT LIKE '@%';");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
|
|
|
@ -213,24 +213,30 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
|||
return false;
|
||||
}
|
||||
$active = intval($_data['active']);
|
||||
$delete2duplicates = intval($_data['delete2duplicates']);
|
||||
$delete1 = intval($_data['delete1']);
|
||||
$delete2 = intval($_data['delete2']);
|
||||
$port1 = $_data['port1'];
|
||||
$host1 = strtolower($_data['host1']);
|
||||
$password1 = $_data['password1'];
|
||||
$exclude = $_data['exclude'];
|
||||
$maxage = $_data['maxage'];
|
||||
$subfolder2 = $_data['subfolder2'];
|
||||
$user1 = $_data['user1'];
|
||||
$mins_interval = $_data['mins_interval'];
|
||||
$enc1 = $_data['enc1'];
|
||||
$delete2duplicates = intval($_data['delete2duplicates']);
|
||||
$delete1 = intval($_data['delete1']);
|
||||
$delete2 = intval($_data['delete2']);
|
||||
$skipcrossduplicates = intval($_data['skipcrossduplicates']);
|
||||
$automap = intval($_data['automap']);
|
||||
$port1 = $_data['port1'];
|
||||
$host1 = strtolower($_data['host1']);
|
||||
$password1 = $_data['password1'];
|
||||
$exclude = $_data['exclude'];
|
||||
$maxage = $_data['maxage'];
|
||||
$maxbytespersecond = $_data['maxbytespersecond'];
|
||||
$subfolder2 = $_data['subfolder2'];
|
||||
$user1 = $_data['user1'];
|
||||
$mins_interval = $_data['mins_interval'];
|
||||
$enc1 = $_data['enc1'];
|
||||
if (empty($subfolder2)) {
|
||||
$subfolder2 = "";
|
||||
}
|
||||
if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32767)))) {
|
||||
$maxage = "0";
|
||||
}
|
||||
if (!isset($maxbytespersecond) || !filter_var($maxbytespersecond, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 125000000)))) {
|
||||
$maxbytespersecond = "0";
|
||||
}
|
||||
if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
|
@ -287,14 +293,17 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
|||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `active`)
|
||||
VALUES (:user2, :exclude, :delete1, :delete2, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :active)");
|
||||
$stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `active`)
|
||||
VALUES (:user2, :exclude, :delete1, :delete2, :automap, :skipcrossduplicates, :maxbytespersecond, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :active)");
|
||||
$stmt->execute(array(
|
||||
':user2' => $username,
|
||||
':exclude' => $exclude,
|
||||
':maxage' => $maxage,
|
||||
':delete1' => $delete1,
|
||||
':delete2' => $delete2,
|
||||
':automap' => $automap,
|
||||
':skipcrossduplicates' => $skipcrossduplicates,
|
||||
':maxbytespersecond' => $maxbytespersecond,
|
||||
':subfolder2' => $subfolder2,
|
||||
':host1' => $host1,
|
||||
':authmech1' => 'PLAIN',
|
||||
|
@ -1444,6 +1453,8 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
|||
$delete2duplicates = (isset($_data['delete2duplicates'])) ? intval($_data['delete2duplicates']) : $is_now['delete2duplicates'];
|
||||
$delete1 = (isset($_data['delete1'])) ? intval($_data['delete1']) : $is_now['delete1'];
|
||||
$delete2 = (isset($_data['delete2'])) ? intval($_data['delete2']) : $is_now['delete2'];
|
||||
$automap = (isset($_data['automap'])) ? intval($_data['automap']) : $is_now['automap'];
|
||||
$skipcrossduplicates = (isset($_data['skipcrossduplicates'])) ? intval($_data['skipcrossduplicates']) : $is_now['skipcrossduplicates'];
|
||||
$port1 = (!empty($_data['port1'])) ? $_data['port1'] : $is_now['port1'];
|
||||
$password1 = (!empty($_data['password1'])) ? $_data['password1'] : $is_now['password1'];
|
||||
$host1 = (!empty($_data['host1'])) ? $_data['host1'] : $is_now['host1'];
|
||||
|
@ -1452,6 +1463,7 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
|||
$mins_interval = (!empty($_data['mins_interval'])) ? $_data['mins_interval'] : $is_now['mins_interval'];
|
||||
$exclude = (!empty($_data['exclude'])) ? $_data['exclude'] : $is_now['exclude'];
|
||||
$maxage = (isset($_data['maxage']) && $_data['maxage'] != "") ? intval($_data['maxage']) : $is_now['maxage'];
|
||||
$maxbytespersecond = (isset($_data['maxbytespersecond']) && $_data['maxbytespersecond'] != "") ? intval($_data['maxbytespersecond']) : $is_now['maxbytespersecond'];
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'] = array(
|
||||
|
@ -1466,6 +1478,9 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
|||
if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32767)))) {
|
||||
$maxage = "0";
|
||||
}
|
||||
if (!isset($maxbytespersecond) || !filter_var($maxbytespersecond, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 125000000)))) {
|
||||
$maxbytespersecond = "0";
|
||||
}
|
||||
if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
|
@ -1502,14 +1517,33 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
|||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE `imapsync` SET `delete1` = :delete1, `delete2` = :delete2, `maxage` = :maxage, `subfolder2` = :subfolder2, `exclude` = :exclude, `host1` = :host1, `last_run` = :last_run, `user1` = :user1, `password1` = :password1, `mins_interval` = :mins_interval, `port1` = :port1, `enc1` = :enc1, `delete2duplicates` = :delete2duplicates, `active` = :active
|
||||
WHERE `id` = :id");
|
||||
$stmt = $pdo->prepare("UPDATE `imapsync` SET `delete1` = :delete1,
|
||||
`delete2` = :delete2,
|
||||
`automap` = :automap,
|
||||
`skipcrossduplicates` = :skipcrossduplicates,
|
||||
`maxage` = :maxage,
|
||||
`maxbytespersecond` = :maxbytespersecond,
|
||||
`subfolder2` = :subfolder2,
|
||||
`exclude` = :exclude,
|
||||
`host1` = :host1,
|
||||
`last_run` = :last_run,
|
||||
`user1` = :user1,
|
||||
`password1` = :password1,
|
||||
`mins_interval` = :mins_interval,
|
||||
`port1` = :port1,
|
||||
`enc1` = :enc1,
|
||||
`delete2duplicates` = :delete2duplicates,
|
||||
`active` = :active
|
||||
WHERE `id` = :id");
|
||||
$stmt->execute(array(
|
||||
':delete1' => $delete1,
|
||||
':delete2' => $delete2,
|
||||
':automap' => $automap,
|
||||
':skipcrossduplicates' => $skipcrossduplicates,
|
||||
':id' => $id,
|
||||
':exclude' => $exclude,
|
||||
':maxage' => $maxage,
|
||||
':maxbytespersecond' => $maxbytespersecond,
|
||||
':subfolder2' => $subfolder2,
|
||||
':host1' => $host1,
|
||||
':user1' => $user1,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Referrer-Policy" content="same-origin">
|
||||
<title><?=$UI_TEXTS['title_name'];?></title>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="/js/html5shiv.min.js"></script>
|
||||
|
@ -33,7 +34,8 @@
|
|||
<link rel="shortcut icon" href="/favicon.png" type="image/png">
|
||||
<link rel="icon" href="/favicon.png" type="image/png">
|
||||
</head>
|
||||
<body style="padding-top: 70px;" id="top">
|
||||
<body id="top">
|
||||
<div class="overlay"></div>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
|
@ -93,12 +95,12 @@
|
|||
<?php
|
||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
?>
|
||||
<li<?= (preg_match("/quarantaine/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/quarantaine.php"><span style="font-size: 12px;" class="glyphicon glyphicon-briefcase"></span> <?= $lang['header']['quarantaine']; ?></a></li>
|
||||
<li<?= (preg_match("/quarantaine/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/quarantaine.php"><span class="glyphicon glyphicon-briefcase"></span> <?= $lang['header']['quarantaine']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
if ($_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
?>
|
||||
<li><a href data-toggle="modal" data-container="sogo-mailcow" data-target="#RestartContainer"><span style="font-size: 12px;" class="glyphicon glyphicon-refresh"></span> <?= $lang['header']['restart_sogo']; ?></a></li>
|
||||
<li><a href data-toggle="modal" data-container="sogo-mailcow" data-target="#RestartContainer"><span class="glyphicon glyphicon-refresh"></span> <?= $lang['header']['restart_sogo']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
@ -126,11 +128,11 @@
|
|||
}
|
||||
if (!isset($_SESSION['dual-login']) && isset($_SESSION['mailcow_cc_username'])):
|
||||
?>
|
||||
<li><a href="#" style="border-left: 1px solid #E7E7E7;" onclick="logout.submit()"><?= sprintf($lang['header']['logged_in_as_logout'], $_SESSION['mailcow_cc_username']); ?></a></li>
|
||||
<li class="logged-in-as"><a href="#" onclick="logout.submit()"><b><?= $_SESSION['mailcow_cc_username']; ?></b> <span class="glyphicon glyphicon-log-out"></span></a></li>
|
||||
<?php
|
||||
elseif (isset($_SESSION['dual-login'])):
|
||||
?>
|
||||
<li><a href="#" style="border-left: 1px solid #E7E7E7;" onclick="logout.submit()"><?= sprintf($lang['header']['logged_in_as_logout_dual'], $_SESSION['mailcow_cc_username'], $_SESSION['dual-login']['username']); ?></a></li>
|
||||
<li class="logged-in-as"><a href="#" onclick="logout.submit()"><b><?= $_SESSION['mailcow_cc_username']; ?> <span class="text-info">(<?= $_SESSION['dual-login']['username']; ?>)</span> </b><span class="glyphicon glyphicon-log-out"></span></a></li>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
|
|
@ -3,7 +3,7 @@ function init_db_schema() {
|
|||
try {
|
||||
global $pdo;
|
||||
|
||||
$db_version = "02012018_1515";
|
||||
$db_version = "24012018_1219";
|
||||
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
|
@ -21,13 +21,14 @@ function init_db_schema() {
|
|||
AND active = '1'
|
||||
AND address NOT LIKE '@%'
|
||||
GROUP BY goto;",
|
||||
"grouped_sender_acl" => "CREATE VIEW grouped_sender_acl (username, send_as) AS
|
||||
SELECT logged_in_as, IFNULL(GROUP_CONCAT(send_as SEPARATOR ' '), '') AS send_as FROM sender_acl
|
||||
"grouped_sender_acl" => "CREATE VIEW grouped_sender_acl (username, send_as_acl) AS
|
||||
SELECT logged_in_as, IFNULL(GROUP_CONCAT(send_as SEPARATOR ' '), '') AS send_as_acl FROM sender_acl
|
||||
WHERE send_as NOT LIKE '@%'
|
||||
GROUP BY logged_in_as;",
|
||||
"grouped_domain_alias_address" => "CREATE VIEW grouped_domain_alias_address (username, ad_alias) AS
|
||||
SELECT username, IFNULL(GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ' '), '') AS ad_alias FROM mailbox
|
||||
LEFT OUTER JOIN alias_domain on target_domain=domain GROUP BY username;",
|
||||
LEFT OUTER JOIN alias_domain ON target_domain=domain
|
||||
GROUP BY username;",
|
||||
"sieve_before" => "CREATE VIEW sieve_before (id, username, script_name, script_data) AS
|
||||
SELECT md5(script_data), username, script_name, script_data FROM sieve_filters
|
||||
WHERE filter_type = 'prefilter';",
|
||||
|
@ -353,12 +354,15 @@ function init_db_schema() {
|
|||
"password1" => "VARCHAR(255) NOT NULL",
|
||||
"exclude" => "VARCHAR(500) NOT NULL DEFAULT ''",
|
||||
"maxage" => "SMALLINT NOT NULL DEFAULT '0'",
|
||||
"mins_interval" => "VARCHAR(50) NOT NULL",
|
||||
"mins_interval" => "VARCHAR(50) NOT NULL DEFAULT '0'",
|
||||
"maxbytespersecond" => "VARCHAR(50) NOT NULL DEFAULT '0'",
|
||||
"port1" => "SMALLINT NOT NULL",
|
||||
"enc1" => "ENUM('TLS','SSL','PLAIN') DEFAULT 'TLS'",
|
||||
"delete2duplicates" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"delete1" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||
"delete2" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||
"automap" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||
"skipcrossduplicates" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||
"is_running" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||
"returned_text" => "TEXT",
|
||||
"last_run" => "TIMESTAMP NULL DEFAULT NULL",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -101,6 +101,7 @@ $lang['danger']['spam_alias_max_exceeded'] = 'Maximale Anzahl an Spam-Alias-Adre
|
|||
$lang['danger']['validity_missing'] = 'Bitte geben Sie eine Gültigkeitsdauer an';
|
||||
$lang['user']['loading'] = "Lade...";
|
||||
$lang['user']['active_sieve'] = "Aktiver Filter";
|
||||
$lang['user']['show_sieve_filters'] = "Zeige aktiven Filter des Benutzers";
|
||||
$lang['user']['no_active_filter'] = "Kein aktiver Filter vorhanden";
|
||||
$lang['user']['on'] = 'Ein';
|
||||
$lang['user']['off'] = 'Aus';
|
||||
|
@ -122,7 +123,9 @@ $lang['user']['spam_aliases'] = 'Temporäre E-Mail Aliasse';
|
|||
$lang['user']['alias'] = 'Alias';
|
||||
$lang['user']['aliases'] = 'Aliasse';
|
||||
$lang['user']['shared_aliases'] = 'Geteilte Alias-Adressen';
|
||||
$lang['user']['shared_aliases_desc'] = 'Geteilte Alias-Adressen werden nicht bei benutzerdefinierten Einstellungen wie die des Spam-Filters oder der Verschlüsselungsrichtlinie berücksichtigt. Entsprechende Spam-Filter können lediglich von einem Administrator vorgenommen werden.';
|
||||
$lang['user']['direct_aliases'] = 'Direkte Alias-Adressen';
|
||||
$lang['user']['direct_aliases_desc'] = 'Nur direkte Alias-Adressen werden für benutzerdefinierte Einstellungen berücksichtigt.';
|
||||
$lang['user']['domain_aliases'] = 'Domain-Alias Adressen';
|
||||
$lang['user']['is_catch_all'] = 'Ist Catch-All Adresse für Domain(s)';
|
||||
$lang['user']['aliases_also_send_as'] = 'Darf außerdem versenden als Benutzer';
|
||||
|
@ -305,6 +308,12 @@ $lang['edit']['encryption'] = 'Verschlüsselung';
|
|||
$lang['edit']['maxage'] = 'Maximales Alter in Tagen einer Nachricht, die kopiert werden soll</br ><small>(0 = alle Nachrichten kopieren)</small>';
|
||||
$lang['edit']['subfolder2'] = 'Ziel-Ordner<br><small>(leer = kein Unterordner)</small>';
|
||||
$lang['edit']['mins_interval'] = 'Intervall (min)';
|
||||
$lang['edit']['maxbytespersecond'] = 'Max. Übertragungsrate in Bytes/s (0 für unlimitiert)';
|
||||
$lang['edit']['automap'] = 'Ordner automatisch mappen ("Sent items", "Sent" => "Sent" etc.)';
|
||||
$lang['edit']['skipcrossduplicates'] = 'Duplikate auch über Ordner hinweg überspringen ("first come, first serve")';
|
||||
$lang['add']['maxbytespersecond'] = 'Max. Übertragungsrate in Bytes/s (0 für unlimitiert)';
|
||||
$lang['add']['automap'] = 'Ordner automatisch mappen ("Sent items", "Sent" => "Sent" etc.)';
|
||||
$lang['add']['skipcrossduplicates'] = 'Duplikate auch über Ordner hinweg überspringen ("first come, first serve")';
|
||||
$lang['edit']['exclude'] = 'Elemente ausschließen (Regex)';
|
||||
$lang['edit']['archive'] = 'Archiv-Zugriff';
|
||||
$lang['edit']['max_mailboxes'] = 'Max. Mailboxanzahl:';
|
||||
|
@ -463,6 +472,8 @@ $lang['admin']['f2b_parameters'] = 'Fail2ban Parameter';
|
|||
$lang['admin']['f2b_ban_time'] = 'Banzeit (s)';
|
||||
$lang['admin']['f2b_max_attempts'] = 'Max. Versuche';
|
||||
$lang['admin']['f2b_retry_window'] = 'Wiederholungen im Zeitraum von (s)';
|
||||
$lang['admin']['f2b_netban_ipv4'] = 'Netzbereich für IPv4 Bans (8-32)';
|
||||
$lang['admin']['f2b_netban_ipv6'] = 'Netzbereich für IPv6 Bans (8-128)';
|
||||
$lang['admin']['f2b_whitelist'] = 'Whitelist für Netzwerke und Hosts';
|
||||
$lang['admin']['restrictions'] = 'Postfix Restriktionen';
|
||||
$lang['admin']['rr'] = 'Postfix Empfänger Restriktionen';
|
||||
|
|
|
@ -101,6 +101,7 @@ $lang['danger']['spam_alias_max_exceeded'] = "Max. allowed spam alias addresses
|
|||
$lang['danger']['validity_missing'] = 'Please assign a period of validity';
|
||||
$lang['user']['loading'] = "Loading...";
|
||||
$lang['user']['active_sieve'] = "Active filter";
|
||||
$lang['user']['show_sieve_filters'] = "Show active user sieve filter";
|
||||
$lang['user']['no_active_filter'] = "No active filter available";
|
||||
$lang['user']['on'] = "On";
|
||||
$lang['user']['off'] = "Off";
|
||||
|
@ -122,7 +123,9 @@ $lang['user']['spam_aliases'] = 'Temporary email aliases';
|
|||
$lang['user']['alias'] = 'Alias';
|
||||
$lang['user']['aliases'] = 'Aliases';
|
||||
$lang['user']['shared_aliases'] = 'Shared alias addresses';
|
||||
$lang['user']['shared_aliases_desc'] = 'A shared alias address is not affected by any user specific settings. A custom spam filter setting can be archived by a domain-wide policy set by an administrator..';
|
||||
$lang['user']['direct_aliases'] = 'Direct alias addresses';
|
||||
$lang['user']['direct_aliases_desc'] = 'Direct alias addresses are affected by spam filter and TLS policy settings.';
|
||||
$lang['user']['domain_aliases'] = 'Domain alias addresses';
|
||||
$lang['user']['is_catch_all'] = 'Catch-all for domain/s';
|
||||
$lang['user']['aliases_also_send_as'] = 'Also allowed to send as user';
|
||||
|
@ -303,6 +306,12 @@ $lang['edit']['username'] = 'Username';
|
|||
$lang['edit']['hostname'] = 'Hostname';
|
||||
$lang['edit']['encryption'] = 'Encryption';
|
||||
$lang['edit']['maxage'] = 'Maximum age of messages in days that will be polled from remote<br><small>(0 = ignore age)</small>';
|
||||
$lang['edit']['maxbytespersecond'] = 'Max. bytes per second (0 equals to unlimited)';
|
||||
$lang['edit']['automap'] = 'Try to automap folders ("Sent items", "Sent" => "Sent" etc.)';
|
||||
$lang['edit']['skipcrossduplicates'] = 'Skip duplicate messages across folders (first come, first serve)';
|
||||
$lang['add']['maxbytespersecond'] = 'Max. bytes per second (0 equals to unlimited)';
|
||||
$lang['add']['automap'] = 'Try to automap folders ("Sent items", "Sent" => "Sent" etc.)';
|
||||
$lang['add']['skipcrossduplicates'] = 'Skip duplicate messages across folders (first come, first serve)';
|
||||
$lang['edit']['subfolder2'] = 'Sync into subfolder on destination<br><small>(empty = do not use subfolder)</small>';
|
||||
$lang['edit']['mins_interval'] = 'Interval (min)';
|
||||
$lang['edit']['exclude'] = 'Exclude objects (regex)';
|
||||
|
@ -463,6 +472,8 @@ $lang['admin']['f2b_parameters'] = 'Fail2ban parameters';
|
|||
$lang['admin']['f2b_ban_time'] = 'Ban time (s)';
|
||||
$lang['admin']['f2b_max_attempts'] = 'Max. attempts';
|
||||
$lang['admin']['f2b_retry_window'] = 'Retry window (s) for max. attempts';
|
||||
$lang['admin']['f2b_netban_ipv4'] = 'IPv4 subnet size to apply ban on (8-32)';
|
||||
$lang['admin']['f2b_netban_ipv6'] = 'IPv6 subnet size to apply ban on (8-128)';
|
||||
$lang['admin']['f2b_whitelist'] = 'Whitelisted networks/hosts';
|
||||
$lang['admin']['search_domain_da'] = 'Search domains';
|
||||
$lang['admin']['restrictions'] = 'Postfix Restrictions';
|
||||
|
|
|
@ -391,6 +391,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<small class="help-block">0-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="0">
|
||||
<small class="help-block">0-125000000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
|
||||
<div class="col-sm-10">
|
||||
|
@ -418,6 +425,20 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="automap"> <?=$lang['add']['automap'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="skipcrossduplicates"> <?=$lang['add']['skipcrossduplicates'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
|
|
|
@ -70,6 +70,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<small class="help-block">0-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="0">
|
||||
<small class="help-block">0-125000000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
|
||||
<div class="col-sm-10">
|
||||
|
@ -97,6 +104,20 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="automap"> <?=$lang['add']['automap'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="skipcrossduplicates"> <?=$lang['add']['skipcrossduplicates'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
|
|
|
@ -97,7 +97,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"> <span class="glyphicon glyphicon-filter"></span></div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<p><a href="#userFilterModal" data-toggle="modal">[Show active user sieve filter]</a></p>
|
||||
<p><a href="#userFilterModal" data-toggle="modal">[<?=$lang['user']['show_sieve_filters'];?>]</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
@ -105,24 +105,22 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
$user_get_alias_details = user_get_alias_details($username);
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['direct_aliases'];?>:</div>
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['direct_aliases'];?>:
|
||||
<p class="small"><?=$lang['user']['direct_aliases_desc'];?></p>
|
||||
</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<p><?=$user_get_alias_details['direct_aliases'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['shared_aliases'];?>:</div>
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['shared_aliases'];?>:
|
||||
<p class="small"><?=$lang['user']['shared_aliases_desc'];?></p>
|
||||
</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<p><?=$user_get_alias_details['shared_aliases'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['domain_aliases'];?>:</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<p><?=$user_get_alias_details['ad_alias'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['aliases_also_send_as'];?>:</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
|
|
|
@ -12,7 +12,7 @@ services:
|
|||
restart: always
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.254
|
||||
ipv4_address: ${IPV4_NETWORK}.254
|
||||
aliases:
|
||||
- unbound
|
||||
|
||||
|
@ -29,10 +29,9 @@ services:
|
|||
- MYSQL_PASSWORD=${DBPASS}
|
||||
restart: always
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.250
|
||||
aliases:
|
||||
- mysql
|
||||
|
||||
|
@ -44,29 +43,31 @@ services:
|
|||
environment:
|
||||
- TZ=${TZ}
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.249
|
||||
ipv4_address: ${IPV4_NETWORK}.249
|
||||
aliases:
|
||||
- redis
|
||||
|
||||
clamd-mailcow:
|
||||
image: mailcow/clamd:1.6
|
||||
image: mailcow/clamd:1.8
|
||||
build: ./data/Dockerfiles/clamd
|
||||
restart: always
|
||||
environment:
|
||||
- SKIP_CLAMD=${SKIP_CLAMD:-n}
|
||||
- TZ=${TZ}
|
||||
- SKIP_CLAMD=${SKIP_CLAMD:-n}
|
||||
volumes:
|
||||
- ./data/conf/clamav/:/etc/clamav/
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
networks:
|
||||
mailcow-network:
|
||||
aliases:
|
||||
- clamd
|
||||
|
||||
rspamd-mailcow:
|
||||
image: mailcow/rspamd:1.15
|
||||
image: mailcow/rspamd:1.16
|
||||
build: ./data/Dockerfiles/rspamd
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
|
@ -82,16 +83,15 @@ services:
|
|||
- rspamd-vol-1:/var/lib/rspamd
|
||||
restart: always
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
hostname: rspamd
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.253
|
||||
aliases:
|
||||
- rspamd
|
||||
|
||||
php-fpm-mailcow:
|
||||
image: mailcow/phpfpm:1.8
|
||||
image: mailcow/phpfpm:1.9
|
||||
build: ./data/Dockerfiles/phpfpm
|
||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||
depends_on:
|
||||
|
@ -101,6 +101,9 @@ services:
|
|||
- ./data/conf/rspamd/dynmaps:/dynmaps:ro
|
||||
- dkim-vol-1:/data/dkim
|
||||
- ./data/conf/rspamd/meta_exporter:/meta_exporter:ro
|
||||
- ./data/conf/phpfpm/php-fpm.d/www.conf:/usr/local/etc/php-fpm.d/www.conf
|
||||
- ./data/conf/phpfpm/php-fpm.d/system.conf:/usr/local/etc/php-fpm.d/system.conf
|
||||
- ./data/conf/phpfpm/php-conf.d/opcache-recommended.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini
|
||||
environment:
|
||||
- LOG_LINES=${LOG_LINES}
|
||||
- TZ=${TZ}
|
||||
|
@ -118,14 +121,14 @@ services:
|
|||
- SMTP_PORT=${SMTP_PORT:-25}
|
||||
restart: always
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
networks:
|
||||
mailcow-network:
|
||||
aliases:
|
||||
- phpfpm
|
||||
|
||||
sogo-mailcow:
|
||||
image: mailcow/sogo:1.13
|
||||
image: mailcow/sogo:1.14
|
||||
build: ./data/Dockerfiles/sogo
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
|
@ -138,15 +141,14 @@ services:
|
|||
- ./data/conf/sogo/:/etc/sogo/
|
||||
restart: always
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.252
|
||||
aliases:
|
||||
- sogo
|
||||
|
||||
dovecot-mailcow:
|
||||
image: mailcow/dovecot:1.17
|
||||
image: mailcow/dovecot:1.18
|
||||
build: ./data/Dockerfiles/dovecot
|
||||
cap_add:
|
||||
- NET_BIND_SERVICE
|
||||
|
@ -176,7 +178,7 @@ services:
|
|||
soft: 20000
|
||||
hard: 40000
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
hostname: ${MAILCOW_HOSTNAME}
|
||||
networks:
|
||||
mailcow-network:
|
||||
|
@ -184,7 +186,7 @@ services:
|
|||
- dovecot
|
||||
|
||||
postfix-mailcow:
|
||||
image: mailcow/postfix:1.11
|
||||
image: mailcow/postfix:1.13
|
||||
build: ./data/Dockerfiles/postfix
|
||||
volumes:
|
||||
- ./data/conf/postfix:/opt/postfix/conf
|
||||
|
@ -197,13 +199,15 @@ services:
|
|||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
- DBPASS=${DBPASS}
|
||||
cap_add:
|
||||
- NET_BIND_SERVICE
|
||||
ports:
|
||||
- "${SMTP_PORT:-25}:25"
|
||||
- "${SMTPS_PORT:-465}:465"
|
||||
- "${SUBMISSION_PORT:-587}:587"
|
||||
restart: always
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
hostname: ${MAILCOW_HOSTNAME}
|
||||
networks:
|
||||
mailcow-network:
|
||||
|
@ -214,7 +218,7 @@ services:
|
|||
image: memcached:alpine
|
||||
restart: always
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
networks:
|
||||
mailcow-network:
|
||||
aliases:
|
||||
|
@ -249,10 +253,9 @@ services:
|
|||
- "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}"
|
||||
restart: always
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.251
|
||||
aliases:
|
||||
- nginx
|
||||
|
||||
|
@ -263,7 +266,7 @@ services:
|
|||
image: mailcow/acme:1.28
|
||||
build: ./data/Dockerfiles/acme
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
environment:
|
||||
- LOG_LINES=${LOG_LINES}
|
||||
- ADDITIONAL_SAN=${ADDITIONAL_SAN}
|
||||
|
@ -284,7 +287,7 @@ services:
|
|||
- acme
|
||||
|
||||
fail2ban-mailcow:
|
||||
image: mailcow/fail2ban:1.10
|
||||
image: mailcow/fail2ban:1.11
|
||||
build: ./data/Dockerfiles/fail2ban
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
|
@ -298,16 +301,17 @@ services:
|
|||
environment:
|
||||
- TZ=${TZ}
|
||||
- SKIP_FAIL2BAN=${SKIP_FAIL2BAN:-n}
|
||||
- IPV4_NETWORK=${IPV4_NETWORK}
|
||||
network_mode: "host"
|
||||
dns:
|
||||
- 172.22.1.254
|
||||
- ${IPV4_NETWORK}.254
|
||||
volumes:
|
||||
- /lib/modules:/lib/modules:ro
|
||||
|
||||
watchdog-mailcow:
|
||||
image: mailcow/watchdog:1.12
|
||||
image: mailcow/watchdog:1.13
|
||||
# Debug
|
||||
#command: /watchdog.sh
|
||||
command: /watchdog.sh
|
||||
build: ./data/Dockerfiles/watchdog
|
||||
volumes:
|
||||
- vmail-vol-1:/vmail:ro
|
||||
|
@ -323,7 +327,6 @@ services:
|
|||
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: 172.22.1.248
|
||||
aliases:
|
||||
- watchdog
|
||||
|
||||
|
@ -358,8 +361,8 @@ networks:
|
|||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: 172.22.1.0/24
|
||||
- subnet: fd4d:6169:6c63:6f77::/64
|
||||
- subnet: ${IPV4_NETWORK}.0/24
|
||||
- subnet: ${IPV6_NETWORK}
|
||||
|
||||
volumes:
|
||||
vmail-vol-1:
|
||||
|
|
|
@ -79,10 +79,12 @@ elif [[ ${NC_INSTALL} == "y" ]]; then
|
|||
/web/nextcloud/occ config:system:set redis port --value=6379 --type=integer; \
|
||||
/web/nextcloud/occ config:system:set memcache.locking --value='\OC\Memcache\Redis' --type=string; \
|
||||
/web/nextcloud/occ config:system:set memcache.local --value='\OC\Memcache\Redis' --type=string; \
|
||||
/web/nextcloud/occ config:system:set trusted_proxies 0 --value=fd4d:6169:6c63:6f77::1; \
|
||||
/web/nextcloud/occ config:system:set trusted_proxies 1 --value=172.22.1.0/24; \
|
||||
/web/nextcloud/occ config:system:set trusted_domains 1 --value=${MAILCOW_HOSTNAME}; \
|
||||
/web/nextcloud/occ config:system:set trusted_proxies 0 --value=${IPV6_NETWORK}; \
|
||||
/web/nextcloud/occ config:system:set trusted_proxies 1 --value=${IPV4_NETWORK}.0/24; \
|
||||
/web/nextcloud/occ config:system:set overwritewebroot --value=/nextcloud; \
|
||||
/web/nextcloud/occ config:system:set overwritehost --value=${MAILCOW_HOSTNAME}; \
|
||||
/web/nextcloud/occ config:system:set overwriteprotocol --value=https; \
|
||||
/web/nextcloud/occ config:system:set mail_smtpmode --value=smtp; \
|
||||
/web/nextcloud/occ config:system:set mail_smtpauthtype --value=LOGIN; \
|
||||
/web/nextcloud/occ config:system:set mail_from_address --value=nextcloud; \
|
||||
|
@ -94,10 +96,11 @@ elif [[ ${NC_INSTALL} == "y" ]]; then
|
|||
/web/nextcloud/occ config:system:set user_backends 0 class --value=OC_User_IMAP"
|
||||
|
||||
if [[ ${NC_TYPE} == "subdomain" ]]; then
|
||||
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) /web/nextcloud/occ config:system:set trusted_domains 1 --value=${NC_SUBD}
|
||||
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) /web/nextcloud/occ config:system:set overwritewebroot --value=/
|
||||
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) /web/nextcloud/occ config:system:set overwritehost --value=${NC_SUBD}
|
||||
cp ./data/assets/nextcloud/nextcloud.conf ./data/conf/nginx/
|
||||
sed -i 's/NC_SUBD/${NC_SUBD}/g' ./data/conf/nginx/nextcloud.conf
|
||||
sed -i "s/NC_SUBD/${NC_SUBD}/g" ./data/conf/nginx/nextcloud.conf
|
||||
elif [[ ${NC_TYPE} == "subfolder" ]]; then
|
||||
cp ./data/assets/nextcloud/site.nextcloud.custom ./data/conf/nginx/
|
||||
fi
|
||||
|
|
224
update.sh
224
update.sh
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
for bin in curl docker-compose docker git awk sha1sum; do
|
||||
if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi
|
||||
if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi
|
||||
done
|
||||
|
||||
[[ ! -f mailcow.conf ]] && { echo "mailcow.conf is missing"; exit 1;}
|
||||
|
@ -9,64 +9,83 @@ done
|
|||
CONFIG_ARRAY=("SKIP_LETS_ENCRYPT" "USE_WATCHDOG" "WATCHDOG_NOTIFY_EMAIL" "SKIP_CLAMD" "SKIP_IP_CHECK" "SKIP_FAIL2BAN" "ADDITIONAL_SAN" "DOVEADM_PORT")
|
||||
sed -i '$a\' 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 [[ ${option} == "DOVEADM_PORT" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo "DOVEADM_PORT=127.0.0.1:19991" >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "WATCHDOG_NOTIFY_EMAIL" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo "WATCHDOG_NOTIFY_EMAIL=" >> mailcow.conf
|
||||
fi
|
||||
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 [[ ${option} == "DOVEADM_PORT" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo "DOVEADM_PORT=127.0.0.1:19991" >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "WATCHDOG_NOTIFY_EMAIL" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo "WATCHDOG_NOTIFY_EMAIL=" >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "LOG_LINES" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo '# Max log lines per service to keep in Redis logs' >> mailcow.conf
|
||||
echo "LOG_LINES=9999" >> mailcow.conf
|
||||
fi
|
||||
elif ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo "${option}=n" >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "IPV4_NETWORK" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo '# Internal IPv4 /24 subnet, format n.n.n. (expands to n.n.n.0/24)' >> mailcow.conf
|
||||
echo "IPV4_NETWORK=172.22.1" >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "IPV6_NETWORK" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo '# Internal IPv6 subnet in fd00::/8' >> mailcow.conf
|
||||
echo "IPV6_NETWORK=fd4d:6169:6c63:6f77::/64" >> 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
|
||||
echo -e "\e[31mfailed\e[0m"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\e[32mOK\e[0m"
|
||||
echo -e "\e[31mfailed\e[0m"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\e[32mOK\e[0m"
|
||||
fi
|
||||
|
||||
set -o pipefail
|
||||
export LC_ALL=C
|
||||
DATE=$(date +%Y-%m-%d_%H_%M_%S)
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
declare -a DC_PARAMS
|
||||
|
||||
case "${1}" in
|
||||
--check|-c)
|
||||
echo "Checking remote code for updates..."
|
||||
git fetch origin ${BRANCH}
|
||||
if ! git diff origin/${BRANCH} --quiet; then
|
||||
echo "Updated code is available."
|
||||
exit 0
|
||||
else
|
||||
echo "No updates available."
|
||||
exit 3
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
while (($#)); do
|
||||
case "${1}" in
|
||||
--check|-c)
|
||||
echo "Checking remote code for updates..."
|
||||
git fetch origin ${BRANCH}
|
||||
if [[ $(git branch ${BRANCH} --contains $(git rev-parse origin/${BRANCH}) > /dev/null 2> /dev/null; echo $?) != 0 ]]; then
|
||||
echo "Updated code is available."
|
||||
exit 0
|
||||
else
|
||||
echo "No updates available."
|
||||
exit 3
|
||||
fi
|
||||
;;
|
||||
--no-start)
|
||||
DC_PARAMS=(${DC_PARAMS[@]} "--no-start")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo -e "\e[32mChecking for newer update script...\e[0m"
|
||||
SHA1_1=$(sha1sum update.sh)
|
||||
|
@ -74,22 +93,22 @@ git fetch origin ${BRANCH}
|
|||
git checkout origin/${BRANCH} update.sh
|
||||
SHA1_2=$(sha1sum update.sh)
|
||||
if [[ ${SHA1_1} != ${SHA1_2} ]]; then
|
||||
echo "update.sh changed, please run this script again, exiting."
|
||||
chmod +x update.sh
|
||||
exit 0
|
||||
echo "update.sh changed, please run this script again, exiting."
|
||||
chmod +x update.sh
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -f mailcow.conf ]]; then
|
||||
source mailcow.conf
|
||||
else
|
||||
echo -e "\e[31mNo mailcow.conf - is mailcow installed?\e[0m"
|
||||
exit 1
|
||||
source mailcow.conf
|
||||
else
|
||||
echo -e "\e[31mNo mailcow.conf - is mailcow installed?\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
read -r -p "Are you sure you want to update mailcow: dockerized? All containers will be stopped. [y/N] " response
|
||||
if [[ ! "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
echo "OK, exiting."
|
||||
exit 0
|
||||
echo "OK, exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo -e "Stopping mailcow... "
|
||||
|
@ -109,31 +128,31 @@ git merge -Xtheirs -Xpatience -m "After update on ${DATE}"
|
|||
# Need to use a variable to not pass return codes of if checks
|
||||
MERGE_RETURN=$?
|
||||
if [[ ${MERGE_RETURN} == 128 ]]; then
|
||||
echo -e "\e[31m\nOh no, what happened?\n=> You most likely added files to your local mailcow instance that were now added to the official mailcow repository. Please move them to another location before updating mailcow.\e[0m"
|
||||
exit 1
|
||||
echo -e "\e[31m\nOh no, what happened?\n=> You most likely added files to your local mailcow instance that were now added to the official mailcow repository. Please move them to another location before updating mailcow.\e[0m"
|
||||
exit 1
|
||||
elif [[ ${MERGE_RETURN} == 1 ]]; then
|
||||
echo -e "\e[93mPotenial conflict, trying to fix...\e[0m"
|
||||
git status --porcelain | grep -E "UD|DU" | awk '{print $2}' | xargs rm -v
|
||||
git add -A
|
||||
git commit -m "After update on ${DATE}" > /dev/null
|
||||
git checkout .
|
||||
echo -e "\e[32mRemoved and recreated files if necessary.\e[0m"
|
||||
echo -e "\e[93mPotenial conflict, trying to fix...\e[0m"
|
||||
git status --porcelain | grep -E "UD|DU" | awk '{print $2}' | xargs rm -v
|
||||
git add -A
|
||||
git commit -m "After update on ${DATE}" > /dev/null
|
||||
git checkout .
|
||||
echo -e "\e[32mRemoved and recreated files if necessary.\e[0m"
|
||||
elif [[ ${MERGE_RETURN} != 0 ]]; then
|
||||
echo -e "\e[31m\nOh no, something went wrong. Please check the error message above.\e[0m"
|
||||
echo
|
||||
echo "Run docker-compose up -d to restart your stack without updates or try again after fixing the mentioned errors."
|
||||
exit 1
|
||||
echo -e "\e[31m\nOh no, something went wrong. Please check the error message above.\e[0m"
|
||||
echo
|
||||
echo "Run docker-compose up -d to restart your stack without updates or try again after fixing the mentioned errors."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo -e "\e[32mFetching new docker-compose version...\e[0m"
|
||||
sleep 2
|
||||
if [[ $(curl -sL -w "%{http_code}" https://www.servercow.de/docker-compose/latest.php -o /dev/null) == "200" ]]; then
|
||||
LATEST_COMPOSE=$(curl -#L https://www.servercow.de/docker-compose/latest.php)
|
||||
curl -#L https://github.com/docker/compose/releases/download/${LATEST_COMPOSE}/docker-compose-$(uname -s)-$(uname -m) > $(which docker-compose)
|
||||
chmod +x $(which docker-compose)
|
||||
else
|
||||
echo -e "\e[33mCannot determine latest docker-compose version, skipping...\e[0m"
|
||||
LATEST_COMPOSE=$(curl -#L https://www.servercow.de/docker-compose/latest.php)
|
||||
curl -#L https://github.com/docker/compose/releases/download/${LATEST_COMPOSE}/docker-compose-$(uname -s)-$(uname -m) > $(which docker-compose)
|
||||
chmod +x $(which docker-compose)
|
||||
else
|
||||
echo -e "\e[33mCannot determine latest docker-compose version, skipping...\e[0m"
|
||||
fi
|
||||
|
||||
echo -e "\e[32mFetching new images, if any...\e[0m"
|
||||
|
@ -146,48 +165,47 @@ cp -n data/assets/ssl-example/*.pem data/assets/ssl/
|
|||
|
||||
echo -e "\e[32mStarting mailcow...\e[0m"
|
||||
sleep 2
|
||||
docker-compose up -d --remove-orphans
|
||||
docker-compose up -d --remove-orphans ${DC_PARAMS[@]}
|
||||
|
||||
echo -e "\e[32mCollecting garbage...\e[0m"
|
||||
IMGS_TO_DELETE=()
|
||||
for container in $(grep -oP "image: \Kmailcow.+" docker-compose.yml); do
|
||||
REPOSITORY=${container/:*}
|
||||
TAG=${container/*:}
|
||||
V_MAIN=${container/*.}
|
||||
V_SUB=${container/*.}
|
||||
REPOSITORY=${container/:*}
|
||||
TAG=${container/*:}
|
||||
V_MAIN=${container/*.}
|
||||
V_SUB=${container/*.}
|
||||
EXISTING_TAGS=$(docker images | grep ${REPOSITORY} | awk '{ print $2 }')
|
||||
for existing_tag in ${EXISTING_TAGS[@]}; do
|
||||
V_MAIN_EXISTING=${existing_tag/*.}
|
||||
V_SUB_EXISTING=${existing_tag/*.}
|
||||
# Not an integer
|
||||
[[ ! $V_MAIN_EXISTING =~ ^[0-9]+$ ]] && continue
|
||||
[[ ! $V_SUB_EXISTING =~ ^[0-9]+$ ]] && continue
|
||||
|
||||
EXISTING_TAGS=$(docker images | grep ${REPOSITORY} | awk '{ print $2 }')
|
||||
for existing_tag in ${EXISTING_TAGS[@]}; do
|
||||
V_MAIN_EXISTING=${existing_tag/*.}
|
||||
V_SUB_EXISTING=${existing_tag/*.}
|
||||
|
||||
# Not an integer
|
||||
[[ ! $V_MAIN_EXISTING =~ ^[0-9]+$ ]] && continue
|
||||
[[ ! $V_SUB_EXISTING =~ ^[0-9]+$ ]] && continue
|
||||
|
||||
if [[ $V_MAIN_EXISTING == "latest" ]]; then
|
||||
echo "Found deprecated label \"latest\" for repository $REPOSITORY, it should be deleted."
|
||||
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
|
||||
elif [[ $V_MAIN_EXISTING -lt $V_MAIN ]]; then
|
||||
echo "Found tag $existing_tag for $REPOSITORY, which is older than the current tag $TAG and should be deleted."
|
||||
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
|
||||
elif [[ $V_SUB_EXISTING -lt $V_SUB ]]; then
|
||||
echo "Found tag $existing_tag for $REPOSITORY, which is older than the current tag $TAG and should be deleted."
|
||||
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
|
||||
fi
|
||||
done
|
||||
if [[ $V_MAIN_EXISTING == "latest" ]]; then
|
||||
echo "Found deprecated label \"latest\" for repository $REPOSITORY, it should be deleted."
|
||||
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
|
||||
elif [[ $V_MAIN_EXISTING -lt $V_MAIN ]]; then
|
||||
echo "Found tag $existing_tag for $REPOSITORY, which is older than the current tag $TAG and should be deleted."
|
||||
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
|
||||
elif [[ $V_SUB_EXISTING -lt $V_SUB ]]; then
|
||||
echo "Found tag $existing_tag for $REPOSITORY, which is older than the current tag $TAG and should be deleted."
|
||||
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [[ ! -z ${IMGS_TO_DELETE[*]} ]]; then
|
||||
echo "Run the following command to delete unused image tags:"
|
||||
echo
|
||||
echo " docker rmi ${IMGS_TO_DELETE[*]}"
|
||||
echo
|
||||
read -r -p "Do you want to delete old image tags right now? [y/N] " response
|
||||
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
docker rmi ${IMGS_TO_DELETE[*]}
|
||||
else
|
||||
echo "OK, skipped."
|
||||
fi
|
||||
echo "Run the following command to delete unused image tags:"
|
||||
echo
|
||||
echo " docker rmi ${IMGS_TO_DELETE[*]}"
|
||||
echo
|
||||
read -r -p "Do you want to delete old image tags right now? [y/N] " response
|
||||
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
docker rmi ${IMGS_TO_DELETE[*]}
|
||||
else
|
||||
echo "OK, skipped."
|
||||
fi
|
||||
fi
|
||||
echo -e "\e[32mFurther cleanup...\e[0m"
|
||||
echo "If you want to cleanup further garbage collected by Docker, please make sure all containers are up and running before cleaning your system by executing \"docker system prune\""
|
||||
|
|
Loading…
Reference in New Issue