diff --git a/data/Dockerfiles/acme/Dockerfile b/data/Dockerfiles/acme/Dockerfile index 27f65e651b..08271bddbe 100644 --- a/data/Dockerfiles/acme/Dockerfile +++ b/data/Dockerfiles/acme/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.19 -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer "The Infrastructure Company GmbH GmbH " ARG PIP_BREAK_SYSTEM_PACKAGES=1 RUN apk upgrade --no-cache \ diff --git a/data/Dockerfiles/clamd/Dockerfile b/data/Dockerfiles/clamd/Dockerfile index 31a332d7ae..8e107516b6 100644 --- a/data/Dockerfiles/clamd/Dockerfile +++ b/data/Dockerfiles/clamd/Dockerfile @@ -1,12 +1,14 @@ -FROM clamav/clamav:1.0.3_base +FROM alpine:3.19 -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer "The Infrastructure Company GmbH GmbH " RUN apk upgrade --no-cache \ && apk add --update --no-cache \ rsync \ + clamav \ bind-tools \ - bash + bash \ + tini # init COPY clamd.sh /clamd.sh @@ -14,7 +16,9 @@ RUN chmod +x /sbin/tini # healthcheck COPY healthcheck.sh /healthcheck.sh +COPY clamdcheck.sh /usr/local/bin RUN chmod +x /healthcheck.sh +RUN chmod +x /usr/local/bin/clamdcheck.sh HEALTHCHECK --start-period=6m CMD "/healthcheck.sh" ENTRYPOINT [] diff --git a/data/Dockerfiles/clamd/clamdcheck.sh b/data/Dockerfiles/clamd/clamdcheck.sh new file mode 100644 index 0000000000..7884d48a95 --- /dev/null +++ b/data/Dockerfiles/clamd/clamdcheck.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -eu + +if [ "${CLAMAV_NO_CLAMD:-}" != "false" ]; then + if [ "$(echo "PING" | nc localhost 3310)" != "PONG" ]; then + echo "ERROR: Unable to contact server" + exit 1 + fi + + echo "Clamd is up" +fi + +exit 0 \ No newline at end of file diff --git a/data/Dockerfiles/dockerapi/Dockerfile b/data/Dockerfiles/dockerapi/Dockerfile index d11f5dda64..3dd1d232eb 100644 --- a/data/Dockerfiles/dockerapi/Dockerfile +++ b/data/Dockerfiles/dockerapi/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.19 -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer "The Infrastructure Company GmbH GmbH " ARG PIP_BREAK_SYSTEM_PACKAGES=1 WORKDIR /app diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index d1413b2aec..9433dd2ea1 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -1,119 +1,115 @@ -FROM debian:bullseye-slim -LABEL maintainer "The Infrastructure Company GmbH " +FROM alpine:3.19 +LABEL maintainer "The Infrastructure Company GmbH GmbH " -ARG DEBIAN_FRONTEND=noninteractive -# renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced extractVersion=(?.*)$ -ARG DOVECOT=2.3.21 -# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=(?.*)$ -ARG GOSU_VERSION=1.17 -ENV LC_ALL C +# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?.*)$ +ARG GOSU_VERSION=1.16 +ENV LANG C.UTF-8 +ENV LC_ALL C.UTF-8 # Add groups and users before installing Dovecot to not break compatibility -RUN groupadd -g 5000 vmail \ - && groupadd -g 401 dovecot \ - && groupadd -g 402 dovenull \ - && groupadd -g 999 sogo \ - && usermod -a -G sogo nobody \ - && useradd -g vmail -u 5000 vmail -d /var/vmail \ - && useradd -c "Dovecot unprivileged user" -d /dev/null -u 401 -g dovecot -s /bin/false dovecot \ - && useradd -c "Dovecot login user" -d /dev/null -u 402 -g dovenull -s /bin/false dovenull \ - && touch /etc/default/locale \ - && apt-get update \ - && apt-get -y --no-install-recommends install \ - build-essential \ - apt-transport-https \ +RUN addgroup -g 5000 vmail \ + && addgroup -g 401 dovecot \ + && addgroup -g 402 dovenull \ + && sed -i "s/999/99/" /etc/group \ + && addgroup -g 999 sogo \ + && addgroup nobody sogo \ + && adduser -D -u 5000 -G vmail -h /var/vmail vmail \ + && adduser -D -G dovecot -u 401 -h /dev/null -s /sbin/nologin dovecot \ + && adduser -D -G dovenull -u 402 -h /dev/null -s /sbin/nologin dovenull \ + && apk add --no-cache --update \ + bash \ + bind-tools \ + findutils \ + envsubst \ ca-certificates \ - cpanminus \ curl \ - dnsutils \ - dirmngr \ - gettext \ - gnupg2 \ jq \ - libauthen-ntlm-perl \ - libcgi-pm-perl \ - libcrypt-openssl-rsa-perl \ - libcrypt-ssleay-perl \ - libdata-uniqid-perl \ - libdbd-mysql-perl \ - libdbi-perl \ - libdigest-hmac-perl \ - libdist-checkconflicts-perl \ - libencode-imaputf7-perl \ - libfile-copy-recursive-perl \ - libfile-tail-perl \ - libhtml-parser-perl \ - libio-compress-perl \ - libio-socket-inet6-perl \ - libio-socket-ssl-perl \ - libio-tee-perl \ - libipc-run-perl \ - libjson-webtoken-perl \ - liblockfile-simple-perl \ - libmail-imapclient-perl \ - libmodule-implementation-perl \ - libmodule-scandeps-perl \ - libnet-ssleay-perl \ - libpackage-stash-perl \ - libpackage-stash-xs-perl \ - libpar-packer-perl \ - libparse-recdescent-perl \ - libproc-processtable-perl \ - libreadonly-perl \ - libregexp-common-perl \ - libssl-dev \ - libsys-meminfo-perl \ - libterm-readkey-perl \ - libtest-deep-perl \ - libtest-fatal-perl \ - libtest-mock-guard-perl \ - libtest-mockobject-perl \ - libtest-nowarnings-perl \ - libtest-pod-perl \ - libtest-requires-perl \ - libtest-simple-perl \ - libtest-warn-perl \ - libtry-tiny-perl \ - libunicode-string-perl \ - liburi-perl \ - libwww-perl \ - lua-sql-mysql \ + lua \ + lua-cjson \ lua-socket \ + lua-sql-mysql \ + lua5.3-sql-mysql \ + icu-data-full \ + mariadb-connector-c \ + gcompat \ mariadb-client \ + perl \ + perl-ntlm \ + perl-cgi \ + perl-crypt-openssl-rsa \ + perl-utils \ + perl-crypt-ssleay \ + perl-data-uniqid \ + perl-dbd-mysql \ + perl-dbi \ + perl-digest-hmac \ + perl-dist-checkconflicts \ + perl-encode-imaputf7 \ + perl-file-copy-recursive \ + perl-file-tail \ + perl-io-socket-inet6 \ + perl-io-gzip \ + perl-io-socket-ssl \ + perl-io-tee \ + perl-ipc-run \ + perl-json-webtoken \ + perl-mail-imapclient \ + perl-module-implementation \ + perl-module-scandeps \ + perl-net-ssleay \ + perl-package-stash \ + perl-package-stash-xs \ + perl-par-packer \ + perl-parse-recdescent \ + perl-lockfile-simple --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community/ \ + libproc \ + perl-readonly \ + perl-regexp-common \ + perl-sys-meminfo \ + perl-term-readkey \ + perl-test-deep \ + perl-test-fatal \ + perl-test-mockobject \ + perl-test-mock-guard \ + perl-test-pod \ + perl-test-requires \ + perl-test-simple \ + perl-test-warn \ + perl-try-tiny \ + perl-unicode-string \ + perl-proc-processtable \ + perl-app-cpanminus \ procps \ - python3-pip \ - redis-server \ - supervisor \ + python3 \ + py3-mysqlclient \ + py3-html2text \ + py3-jinja2 \ + py3-redis \ + redis \ syslog-ng \ - syslog-ng-core \ - syslog-ng-mod-redis \ + syslog-ng-redis \ + syslog-ng-json \ + supervisor \ + tzdata \ wget \ - && dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \ - && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \ - && chmod +x /usr/local/bin/gosu \ - && gosu nobody true \ - && apt-key adv --fetch-keys https://repo.dovecot.org/DOVECOT-REPO-GPG \ - && echo "deb https://repo.dovecot.org/ce-${DOVECOT}/debian/bullseye bullseye main" > /etc/apt/sources.list.d/dovecot.list \ - && apt-get update \ - && apt-get -y --no-install-recommends install \ - dovecot-lua \ - dovecot-managesieved \ - dovecot-sieve \ + dovecot \ + dovecot-dev \ dovecot-lmtpd \ + dovecot-lua \ dovecot-ldap \ dovecot-mysql \ - dovecot-core \ + dovecot-sql \ + dovecot-submissiond \ + dovecot-pigeonhole-plugin \ dovecot-pop3d \ - dovecot-imapd \ - dovecot-solr \ - && pip3 install mysql-connector-python html2text jinja2 redis \ - && apt-get autoremove --purge -y \ - && apt-get autoclean \ - && rm -rf /var/lib/apt/lists/* \ - && rm -rf /tmp/* /var/tmp/* /root/.cache/ -# imapsync dependencies -RUN cpan Crypt::OpenSSL::PKCS12 + dovecot-fts-solr \ + && arch=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) \ + && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$arch" \ + && chmod +x /usr/local/bin/gosu \ + && gosu nobody true + +# RUN cpan LockFile::Simple COPY trim_logs.sh /usr/local/bin/trim_logs.sh COPY clean_q_aged.sh /usr/local/bin/clean_q_aged.sh diff --git a/data/Dockerfiles/dovecot/docker-entrypoint.sh b/data/Dockerfiles/dovecot/docker-entrypoint.sh index b2633c2763..f1e2e9668d 100755 --- a/data/Dockerfiles/dovecot/docker-entrypoint.sh +++ b/data/Dockerfiles/dovecot/docker-entrypoint.sh @@ -432,4 +432,8 @@ done # May be related to something inside Docker, I seriously don't know touch /etc/dovecot/lua/passwd-verify.lua +if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then + cp /etc/syslog-ng/syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng.conf +fi + exec "$@" diff --git a/data/Dockerfiles/dovecot/quarantine_notify.py b/data/Dockerfiles/dovecot/quarantine_notify.py index 65f2a0e60f..e8d743b317 100755 --- a/data/Dockerfiles/dovecot/quarantine_notify.py +++ b/data/Dockerfiles/dovecot/quarantine_notify.py @@ -3,11 +3,10 @@ import smtplib import os import sys -import mysql.connector +import MySQLdb from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.utils import COMMASPACE, formatdate -import cgi import jinja2 from jinja2 import Template import json @@ -50,7 +49,7 @@ def query_mysql(query, headers = True, update = False): while True: try: - cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user=os.environ.get('DBUSER'), passwd=os.environ.get('DBPASS'), database=os.environ.get('DBNAME'), charset="utf8mb4", collation="utf8mb4_general_ci") + cnx = MySQLdb.connect(user=os.environ.get('DBUSER'), password=os.environ.get('DBPASS'), database=os.environ.get('DBNAME'), charset="utf8mb4", collation="utf8mb4_general_ci") except Exception as ex: print('%s - trying again...' % (ex)) time.sleep(3) diff --git a/data/Dockerfiles/dovecot/quota_notify.py b/data/Dockerfiles/dovecot/quota_notify.py index 2d7361b81d..34b3e0ed90 100755 --- a/data/Dockerfiles/dovecot/quota_notify.py +++ b/data/Dockerfiles/dovecot/quota_notify.py @@ -55,7 +55,7 @@ msg.attach(text_part) msg.attach(html_part) msg['To'] = username - p = Popen(['/usr/lib/dovecot/dovecot-lda', '-d', username, '-o', '"plugin/quota=maildir:User quota:noenforcing"'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) + p = Popen(['/usr/libexec/dovecot/dovecot-lda', '-d', username, '-o', '"plugin/quota=maildir:User quota:noenforcing"'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) p.communicate(input=bytes(msg.as_string(), 'utf-8')) domain = username.split("@")[-1] diff --git a/data/Dockerfiles/dovecot/supervisord.conf b/data/Dockerfiles/dovecot/supervisord.conf index a769864091..5b00500024 100644 --- a/data/Dockerfiles/dovecot/supervisord.conf +++ b/data/Dockerfiles/dovecot/supervisord.conf @@ -13,6 +13,10 @@ autostart=true [program:dovecot] command=/usr/sbin/dovecot -F +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 autorestart=true [eventlistener:processes] diff --git a/data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf b/data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf index ea2bcfbfae..f7fc20b7e0 100644 --- a/data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf +++ b/data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf @@ -1,4 +1,4 @@ -@version: 3.28 +@version: 4.5 @include "scl.conf" options { chain_hostnames(off); @@ -6,11 +6,11 @@ options { use_dns(no); use_fqdn(no); owner("root"); group("adm"); perm(0640); - stats_freq(0); + stats(freq(0)); bad_hostname("^gconfd$"); }; -source s_src { - unix-stream("/dev/log"); +source s_dgram { + unix-dgram("/dev/log"); internal(); }; destination d_stdout { pipe("/dev/stdout"); }; @@ -36,7 +36,7 @@ filter f_replica { not match("Error: sync: Unknown user in remote" value("MESSAGE")); }; log { - source(s_src); + source(s_dgram); filter(f_replica); destination(d_stdout); filter(f_mail); diff --git a/data/Dockerfiles/dovecot/syslog-ng.conf b/data/Dockerfiles/dovecot/syslog-ng.conf index 2ee4f6241f..fcc13587d7 100644 --- a/data/Dockerfiles/dovecot/syslog-ng.conf +++ b/data/Dockerfiles/dovecot/syslog-ng.conf @@ -1,4 +1,4 @@ -@version: 3.28 +@version: 4.5 @include "scl.conf" options { chain_hostnames(off); @@ -6,11 +6,11 @@ options { use_dns(no); use_fqdn(no); owner("root"); group("adm"); perm(0640); - stats_freq(0); + stats(freq(0)); bad_hostname("^gconfd$"); }; -source s_src { - unix-stream("/dev/log"); +source s_dgram { + unix-dgram("/dev/log"); internal(); }; destination d_stdout { pipe("/dev/stdout"); }; @@ -36,7 +36,7 @@ filter f_replica { not match("Error: sync: Unknown user in remote" value("MESSAGE")); }; log { - source(s_src); + source(s_dgram); filter(f_replica); destination(d_stdout); filter(f_mail); diff --git a/data/Dockerfiles/postfix/Dockerfile b/data/Dockerfiles/postfix/Dockerfile index bda6e07f2d..236062d782 100644 --- a/data/Dockerfiles/postfix/Dockerfile +++ b/data/Dockerfiles/postfix/Dockerfile @@ -1,5 +1,5 @@ FROM debian:bullseye-slim -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer "The Infrastructure Company GmbH GmbH " ARG DEBIAN_FRONTEND=noninteractive ENV LC_ALL C diff --git a/data/Dockerfiles/rspamd/Dockerfile b/data/Dockerfiles/rspamd/Dockerfile index 9d022f8265..2511a6f2fe 100644 --- a/data/Dockerfiles/rspamd/Dockerfile +++ b/data/Dockerfiles/rspamd/Dockerfile @@ -1,5 +1,5 @@ FROM debian:bullseye-slim -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer "The Infrastructure Company GmbH GmbH " ARG DEBIAN_FRONTEND=noninteractive ARG CODENAME=bullseye @@ -13,7 +13,7 @@ RUN apt-get update && apt-get install -y \ dnsutils \ netcat \ && apt-key adv --fetch-keys https://rspamd.com/apt-stable/gpg.key \ - && echo "deb [arch=amd64] https://rspamd.com/apt-stable/ $CODENAME main" > /etc/apt/sources.list.d/rspamd.list \ + && echo "deb https://rspamd.com/apt-stable/ $CODENAME main" > /etc/apt/sources.list.d/rspamd.list \ && apt-get update \ && apt-get --no-install-recommends -y install rspamd redis-tools procps nano \ && rm -rf /var/lib/apt/lists/* \ diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index cbc5c93a9e..54d676b9a1 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -1,8 +1,8 @@ FROM debian:bullseye-slim -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer "The Infrastructure Company GmbH GmbH " ARG DEBIAN_FRONTEND=noninteractive -ARG SOGO_DEBIAN_REPOSITORY=http://packages.sogo.nu/nightly/5/debian/ +ARG SOGO_DEBIAN_REPOSITORY=http://www.axis.cz/linux/debian # renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?.*)$ ARG GOSU_VERSION=1.17 ENV LC_ALL C @@ -32,7 +32,7 @@ RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \ && mkdir /usr/share/doc/sogo \ && touch /usr/share/doc/sogo/empty.sh \ && apt-key adv --keyserver keys.openpgp.org --recv-key 74FFC6D72B925A34B5D356BDF8A27B36A6E2EAE9 \ - && echo "deb ${SOGO_DEBIAN_REPOSITORY} bullseye bullseye" > /etc/apt/sources.list.d/sogo.list \ + && echo "deb [trusted=yes] ${SOGO_DEBIAN_REPOSITORY} bullseye sogo-v5" > /etc/apt/sources.list.d/sogo.list \ && apt-get update && apt-get install -y --no-install-recommends \ sogo \ sogo-activesync \ diff --git a/data/Dockerfiles/unbound/Dockerfile b/data/Dockerfiles/unbound/Dockerfile index 1e0192f876..cd4dfde8e5 100644 --- a/data/Dockerfiles/unbound/Dockerfile +++ b/data/Dockerfiles/unbound/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.19 -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer "The Infrastructure Company GmbH GmbH " RUN apk add --update --no-cache \ curl \ diff --git a/data/Dockerfiles/watchdog/watchdog.sh b/data/Dockerfiles/watchdog/watchdog.sh index b95bf84b57..d43cb38ac1 100755 --- a/data/Dockerfiles/watchdog/watchdog.sh +++ b/data/Dockerfiles/watchdog/watchdog.sh @@ -716,8 +716,8 @@ rspamd_checks() { From: watchdog@localhost Empty -' | usr/bin/curl --max-time 10 -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/scan | jq -rc .default.required_score) - if [[ ${SCORE} != "9999" ]]; then +' | usr/bin/curl --max-time 10 -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/scan | jq -rc .default.required_score | sed 's/\..*//' ) + if [[ ${SCORE} -ne 9999 ]]; then echo "Rspamd settings check failed, score returned: ${SCORE}" 2>> /tmp/rspamd-mailcow 1>&2 err_count=$(( ${err_count} + 1)) else diff --git a/docker-compose.yml b/docker-compose.yml index 267d1f133b..26a0cfe137 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,7 +58,7 @@ services: - redis clamd-mailcow: - image: mailcow/clamd:1.63 + image: mailcow/clamd:1.64 restart: always depends_on: unbound-mailcow: @@ -77,7 +77,7 @@ services: - clamd rspamd-mailcow: - image: mailcow/rspamd:1.94 + image: mailcow/rspamd:1.95 stop_grace_period: 30s depends_on: - dovecot-mailcow @@ -171,7 +171,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.120 + image: mailcow/sogo:1.121 environment: - DBNAME=${DBNAME} - DBUSER=${DBUSER} @@ -203,7 +203,7 @@ services: labels: ofelia.enabled: "true" ofelia.job-exec.sogo_sessions.schedule: "@every 1m" - ofelia.job-exec.sogo_sessions.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool expire-sessions $${SOGO_EXPIRE_SESSION} || exit 0\"" + ofelia.job-exec.sogo_sessions.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool -v expire-sessions $${SOGO_EXPIRE_SESSION} || exit 0\"" ofelia.job-exec.sogo_ealarms.schedule: "@every 1m" ofelia.job-exec.sogo_ealarms.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-ealarms-notify -p /etc/sogo/sieve.creds || exit 0\"" ofelia.job-exec.sogo_eautoreply.schedule: "@every 5m" @@ -218,7 +218,7 @@ services: - sogo dovecot-mailcow: - image: mailcow/dovecot:1.26 + image: mailcow/dovecot:1.27 depends_on: - mysql-mailcow dns: @@ -298,7 +298,7 @@ services: - dovecot postfix-mailcow: - image: mailcow/postfix:1.73 + image: mailcow/postfix:1.74 depends_on: mysql-mailcow: condition: service_started @@ -547,8 +547,10 @@ services: aliases: - dockerapi + + ##### Will be removed soon ##### solr-mailcow: - image: mailcow/solr:1.8.1 + image: mailcow/solr:1.8.2 restart: always volumes: - solr-vol-1:/opt/solr/server/solr/dovecot-fts/data @@ -562,6 +564,7 @@ services: mailcow-network: aliases: - solr + ################################ olefy-mailcow: image: mailcow/olefy:1.12 diff --git a/generate_config.sh b/generate_config.sh index 3b2928937d..2986f16897 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -34,7 +34,7 @@ if docker compose > /dev/null 2>&1; then echo -e "\e[33mNotice: You´ll have to update this Compose Version via your Package Manager manually!\e[0m" else echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" exit 1 fi elif docker-compose > /dev/null 2>&1; then @@ -47,14 +47,14 @@ elif docker-compose > /dev/null 2>&1; then echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" else echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" exit 1 fi fi else echo -e "\e[31mCannot find Docker Compose.\e[0m" - echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m" exit 1 fi diff --git a/helper-scripts/_cold-standby.sh b/helper-scripts/_cold-standby.sh index 0e8885a3ec..ff0512e073 100755 --- a/helper-scripts/_cold-standby.sh +++ b/helper-scripts/_cold-standby.sh @@ -2,6 +2,7 @@ PATH=${PATH}:/opt/bin DATE=$(date +%Y-%m-%d_%H_%M_%S) +LOCAL_ARCH=$(uname -m) export LC_ALL=C echo @@ -148,6 +149,9 @@ else echo -e "\e[31mCannot find any Docker Compose on remote, exiting...\e[0m" exit 1 fi + + REMOTE_ARCH=$(ssh -o StrictHostKeyChecking=no -i "${REMOTE_SSH_KEY}" ${REMOTE_SSH_HOST} -p ${REMOTE_SSH_PORT} "uname -m") + } SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) @@ -164,6 +168,17 @@ echo -e "\033[1mFound compose project name ${CMPS_PRJ} for ${MAILCOW_HOSTNAME}\0 echo -e "\033[1mFound SQL ${SQLIMAGE}\033[0m" echo +# Print Message if Local Arch and Remote Arch is not the same +if [[ $LOCAL_ARCH != $REMOTE_ARCH ]]; then + echo + echo -e "\e[1;33m!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!\e[0m" + echo -e "\e[3;33mDetected Architecture missmatch from source to destination...\e[0m" + echo -e "\e[3;33mYour backup is transferred but some volumes might be skipped!\e[0m" + echo -e "\e[1;33m!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!\e[0m" + echo + sleep 2 +fi + # Make sure destination exists, rsync can fail under some circumstances echo -e "\033[1mPreparing remote...\033[0m" if ! ssh -o StrictHostKeyChecking=no \ @@ -248,8 +263,21 @@ for vol in $(docker volume ls -qf name="${CMPS_PRJ}"); do # Cleanup rm -rf "${SCRIPT_DIR}/../_tmp_mariabackup/" - else + elif [[ "${vol}" =~ "rspamd-vol-1" ]]; then + # Exclude rspamd-vol-1 if the Architectures are not the same on source and destination due to compatibility issues. + if [[ $LOCAL_ARCH == $REMOTE_ARCH ]]; then + echo -e "\033[1mSynchronizing ${vol} from local ${mountpoint}...\033[0m" + rsync --delete --info=progress2 -aH -e "ssh -o StrictHostKeyChecking=no \ + -i \"${REMOTE_SSH_KEY}\" \ + -p ${REMOTE_SSH_PORT}" \ + "${mountpoint}/" root@${REMOTE_SSH_HOST}:"${mountpoint}" + else + echo -e "\e[1;31mSkipping ${vol} from local maschine due to incompatiblity between different architecture...\e[0m" + sleep 2 + continue + fi + else echo -e "\033[1mSynchronizing ${vol} from local ${mountpoint}...\033[0m" rsync --delete --info=progress2 -aH -e "ssh -o StrictHostKeyChecking=no \ -i \"${REMOTE_SSH_KEY}\" \ diff --git a/helper-scripts/backup_and_restore.sh b/helper-scripts/backup_and_restore.sh index ee9f0202d5..03390927bd 100755 --- a/helper-scripts/backup_and_restore.sh +++ b/helper-scripts/backup_and_restore.sh @@ -53,6 +53,7 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" COMPOSE_FILE=${SCRIPT_DIR}/../docker-compose.yml ENV_FILE=${SCRIPT_DIR}/../.env THREADS=$(echo ${THREADS:-1}) +ARCH=$(uname -m) if ! [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then echo "Thread input is not a number!" @@ -96,6 +97,7 @@ function backup() { mkdir -p "${BACKUP_LOCATION}/mailcow-${DATE}" chmod 755 "${BACKUP_LOCATION}/mailcow-${DATE}" cp "${SCRIPT_DIR}/../mailcow.conf" "${BACKUP_LOCATION}/mailcow-${DATE}" + touch "${BACKUP_LOCATION}/mailcow-${DATE}/.$ARCH" for bin in docker; do if [[ -z $(which ${bin}) ]]; then >&2 echo -e "\e[31mCannot find ${bin} in local PATH, exiting...\e[0m" @@ -231,12 +233,29 @@ function restore() { docker start $(docker ps -aqf name=dovecot-mailcow) ;; rspamd) - docker stop $(docker ps -qf name=rspamd-mailcow) - docker run -it --name mailcow-backup --rm \ - -v ${RESTORE_LOCATION}:/backup:z \ - -v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_rspamd.tar.gz - docker start $(docker ps -aqf name=rspamd-mailcow) + if [[ $(find "${RESTORE_LOCATION}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') == "" ]]; then + echo -e "\e[33mCould not find a architecture signature of the loaded backup... Maybe the backup was done before the multiarch update?" + sleep 2 + echo -e "Continuing anyhow. If rspamd is crashing opon boot try remove the rspamd volume with docker volume rm ${CMPS_PRJ}_rspamd-vol-1 after you've stopped the stack.\e[0m" + sleep 2 + docker stop $(docker ps -qf name=rspamd-mailcow) + docker run -it --name mailcow-backup --rm \ + -v ${RESTORE_LOCATION}:/backup:z \ + -v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:z \ + ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_rspamd.tar.gz + docker start $(docker ps -aqf name=rspamd-mailcow) + elif [[ $ARCH != $(find "${RESTORE_LOCATION}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') ]]; then + echo -e "\e[31mThe Architecture of the backed up mailcow OS is different then your restoring mailcow OS..." + sleep 2 + echo -e "Skipping rspamd due to compatibility issues!\e[0m" + else + docker stop $(docker ps -qf name=rspamd-mailcow) + docker run -it --name mailcow-backup --rm \ + -v ${RESTORE_LOCATION}:/backup:z \ + -v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:z \ + ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_rspamd.tar.gz + docker start $(docker ps -aqf name=rspamd-mailcow) + fi ;; postfix) docker stop $(docker ps -qf name=postfix-mailcow) @@ -360,9 +379,17 @@ elif [[ ${1} == "restore" ]]; then FILE_SELECTION[${i}]="redis" ((i++)) elif [[ ${file} =~ rspamd ]]; then - echo "[ ${i} ] - Rspamd data" - FILE_SELECTION[${i}]="rspamd" - ((i++)) + if [[ $(find "${FOLDER_SELECTION[${input_sel}]}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') == "" ]]; then + echo "[ ${i} ] - Rspamd data (unkown Arch detected, restore with caution!)" + FILE_SELECTION[${i}]="rspamd" + ((i++)) + elif [[ $ARCH != $(find "${FOLDER_SELECTION[${input_sel}]}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') ]]; then + echo -e "\e[31m[ NaN ] - Rspamd data (incompatible Arch, cannot restore it)\e[0m" + else + echo "[ ${i} ] - Rspamd data" + FILE_SELECTION[${i}]="rspamd" + ((i++)) + fi elif [[ ${file} =~ postfix ]]; then echo "[ ${i} ] - Postfix data" FILE_SELECTION[${i}]="postfix" diff --git a/update.sh b/update.sh index 47ae1f8ba3..623242d5b9 100755 --- a/update.sh +++ b/update.sh @@ -181,7 +181,7 @@ if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m" else echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" exit 1 fi elif docker-compose > /dev/null 2>&1; then @@ -196,14 +196,14 @@ if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" else echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease update/install regarding to this doc site: https://docs.mailcow.email/install/\e[0m" exit 1 fi fi else echo -e "\e[31mCannot find Docker Compose.\e[0m" - echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m" exit 1 fi @@ -216,7 +216,7 @@ elif [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then if ! $COMPOSE_COMMAND > /dev/null 2>&1 || ! $COMPOSE_COMMAND --version | grep "^2." > /dev/null 2>&1; then # IF it cannot find Standalone in > 2.X, then script stops echo -e "\e[31mCannot find Docker Compose or the Version is lower then 2.X.X.\e[0m" - echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m" exit 1 fi # If it finds the standalone Plugin it will use this instead and change the mailcow.conf Variable accordingly @@ -236,7 +236,7 @@ elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then if ! $COMPOSE_COMMAND > /dev/null 2>&1; then # IF it cannot find Native in > 2.X, then script stops echo -e "\e[31mCannot find Docker Compose.\e[0m" - echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m" exit 1 fi # If it finds the native Plugin it will use this instead and change the mailcow.conf Variable accordingly