Browse Source

Updated mailcow Components to be ARM64 compatible

DerLinkman 2 years ago
parent
commit
accedf0280

+ 1 - 1
data/Dockerfiles/acme/Dockerfile

@@ -1,6 +1,6 @@
 FROM alpine:3.19
 
-LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
+LABEL maintainer "The Infrastructure Company GmbH GmbH <info@servercow.de>"
 
 ARG PIP_BREAK_SYSTEM_PACKAGES=1
 RUN apk upgrade --no-cache \

+ 7 - 3
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 <info@servercow.de>"
+LABEL maintainer "The Infrastructure Company GmbH GmbH <info@servercow.de>"
 
 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 []

+ 14 - 0
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

+ 1 - 1
data/Dockerfiles/dockerapi/Dockerfile

@@ -1,6 +1,6 @@
 FROM alpine:3.19
 
-LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
+LABEL maintainer "The Infrastructure Company GmbH GmbH <info@servercow.de>"
 
 ARG PIP_BREAK_SYSTEM_PACKAGES=1
 WORKDIR /app

+ 96 - 100
data/Dockerfiles/dovecot/Dockerfile

@@ -1,119 +1,115 @@
-FROM debian:bullseye-slim
-LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
+FROM alpine:3.19
+LABEL maintainer "The Infrastructure Company GmbH GmbH <info@servercow.de>"
 
-ARG DEBIAN_FRONTEND=noninteractive
-# renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced extractVersion=(?<version>.*)$
-ARG DOVECOT=2.3.21
-# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=(?<version>.*)$
-ARG GOSU_VERSION=1.17
-ENV LC_ALL C
+# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
+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

+ 4 - 0
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 "$@"

+ 2 - 3
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 @@ try:
   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)

+ 1 - 1
data/Dockerfiles/dovecot/quota_notify.py

@@ -55,7 +55,7 @@ try:
   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]

+ 4 - 0
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]

+ 5 - 5
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);

+ 5 - 5
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);

+ 1 - 1
data/Dockerfiles/postfix/Dockerfile

@@ -1,5 +1,5 @@
 FROM debian:bullseye-slim
-LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
+LABEL maintainer "The Infrastructure Company GmbH GmbH <info@servercow.de>"
 
 ARG DEBIAN_FRONTEND=noninteractive
 ENV LC_ALL C

+ 2 - 2
data/Dockerfiles/rspamd/Dockerfile

@@ -1,5 +1,5 @@
 FROM debian:bullseye-slim
-LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
+LABEL maintainer "The Infrastructure Company GmbH GmbH <info@servercow.de>"
 
 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/* \

+ 3 - 3
data/Dockerfiles/sogo/Dockerfile

@@ -1,8 +1,8 @@
 FROM debian:bullseye-slim
-LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
+LABEL maintainer "The Infrastructure Company GmbH GmbH <info@servercow.de>"
 
 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=^(?<version>.*)$
 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 \

+ 1 - 1
data/Dockerfiles/unbound/Dockerfile

@@ -1,6 +1,6 @@
 FROM alpine:3.19
 
-LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
+LABEL maintainer "The Infrastructure Company GmbH GmbH <info@servercow.de>"
 
 RUN apk add --update --no-cache \
 	curl \

+ 2 - 2
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

+ 10 - 7
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

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

+ 29 - 1
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}\" \

+ 36 - 9
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"

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