diff --git a/data/Dockerfiles/acme/Dockerfile b/data/Dockerfiles/acme/Dockerfile index 8688e4400..8aa16ad58 100644 --- a/data/Dockerfiles/acme/Dockerfile +++ b/data/Dockerfiles/acme/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.20 -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer = "The Infrastructure Company GmbH " RUN apk upgrade --no-cache \ diff --git a/data/Dockerfiles/acme/acme.sh b/data/Dockerfiles/acme/acme.sh index 9d04d10ce..9682684e4 100755 --- a/data/Dockerfiles/acme/acme.sh +++ b/data/Dockerfiles/acme/acme.sh @@ -123,7 +123,7 @@ done log_f "Database OK" log_f "Waiting for Nginx..." -until $(curl --output /dev/null --silent --head --fail http://nginx:8081); do +until $(curl --output /dev/null --silent --head --fail http://nginx.${COMPOSE_PROJECT_NAME}_mailcow-network:8081); do sleep 2 done log_f "Nginx OK" @@ -137,7 +137,7 @@ log_f "Resolver OK" # Waiting for domain table log_f "Waiting for domain table..." while [[ -z ${DOMAIN_TABLE} ]]; do - curl --silent http://nginx/ >/dev/null 2>&1 + curl --silent http://nginx.${COMPOSE_PROJECT_NAME}_mailcow-network/ >/dev/null 2>&1 DOMAIN_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'domain'" -Bs) [[ -z ${DOMAIN_TABLE} ]] && sleep 10 done diff --git a/data/Dockerfiles/acme/reload-configurations.sh b/data/Dockerfiles/acme/reload-configurations.sh index d5461a4db..8d194b68b 100644 --- a/data/Dockerfiles/acme/reload-configurations.sh +++ b/data/Dockerfiles/acme/reload-configurations.sh @@ -2,32 +2,32 @@ # Reading container IDs # Wrapping as array to ensure trimmed content when calling $NGINX etc. -NGINX=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"nginx-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " ")) -DOVECOT=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"dovecot-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " ")) -POSTFIX=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"postfix-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " ")) +NGINX=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"nginx-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " ")) +DOVECOT=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"dovecot-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " ")) +POSTFIX=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"postfix-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" | tr "\n" " ")) reload_nginx(){ echo "Reloading Nginx..." - NGINX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${NGINX}/exec -d '{"cmd":"reload", "task":"nginx"}' --silent -H 'Content-type: application/json' | jq -r .type) + NGINX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${NGINX}/exec -d '{"cmd":"reload", "task":"nginx"}' --silent -H 'Content-type: application/json' | jq -r .type) [[ ${NGINX_RELOAD_RET} != 'success' ]] && { echo "Could not reload Nginx, restarting container..."; restart_container ${NGINX} ; } } reload_dovecot(){ echo "Reloading Dovecot..." - DOVECOT_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${DOVECOT}/exec -d '{"cmd":"reload", "task":"dovecot"}' --silent -H 'Content-type: application/json' | jq -r .type) + DOVECOT_RELOAD_RET=$(curl -X POST --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${DOVECOT}/exec -d '{"cmd":"reload", "task":"dovecot"}' --silent -H 'Content-type: application/json' | jq -r .type) [[ ${DOVECOT_RELOAD_RET} != 'success' ]] && { echo "Could not reload Dovecot, restarting container..."; restart_container ${DOVECOT} ; } } reload_postfix(){ echo "Reloading Postfix..." - POSTFIX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi/containers/${POSTFIX}/exec -d '{"cmd":"reload", "task":"postfix"}' --silent -H 'Content-type: application/json' | jq -r .type) + POSTFIX_RELOAD_RET=$(curl -X POST --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${POSTFIX}/exec -d '{"cmd":"reload", "task":"postfix"}' --silent -H 'Content-type: application/json' | jq -r .type) [[ ${POSTFIX_RELOAD_RET} != 'success' ]] && { echo "Could not reload Postfix, restarting container..."; restart_container ${POSTFIX} ; } } restart_container(){ for container in $*; do echo "Restarting ${container}..." - C_REST_OUT=$(curl -X POST --insecure https://dockerapi/containers/${container}/restart --silent | jq -r '.msg') + C_REST_OUT=$(curl -X POST --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${container}/restart --silent | jq -r '.msg') echo "${C_REST_OUT}" done } diff --git a/data/Dockerfiles/clamd/Dockerfile b/data/Dockerfiles/clamd/Dockerfile index ab1e2550f..1850d4bed 100644 --- a/data/Dockerfiles/clamd/Dockerfile +++ b/data/Dockerfiles/clamd/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.20 -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer = "The Infrastructure Company GmbH " RUN apk upgrade --no-cache \ && apk add --update --no-cache \ diff --git a/data/Dockerfiles/dockerapi/Dockerfile b/data/Dockerfiles/dockerapi/Dockerfile index 511c46234..92c19dcc1 100644 --- a/data/Dockerfiles/dockerapi/Dockerfile +++ b/data/Dockerfiles/dockerapi/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.20 -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer = "The Infrastructure Company GmbH " ARG PIP_BREAK_SYSTEM_PACKAGES=1 WORKDIR /app diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index b09b06c98..b8b827932 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -1,5 +1,6 @@ FROM alpine:3.20 -LABEL maintainer "The Infrastructure Company GmbH " + +LABEL maintainer = "The Infrastructure Company GmbH " # renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?.*)$ ARG GOSU_VERSION=1.16 diff --git a/data/Dockerfiles/dovecot/docker-entrypoint.sh b/data/Dockerfiles/dovecot/docker-entrypoint.sh index 944f055e4..1d0a78304 100755 --- a/data/Dockerfiles/dovecot/docker-entrypoint.sh +++ b/data/Dockerfiles/dovecot/docker-entrypoint.sh @@ -283,14 +283,6 @@ sievec /var/vmail/sieve/global_sieve_after.sieve sievec /usr/lib/dovecot/sieve/report-spam.sieve sievec /usr/lib/dovecot/sieve/report-ham.sieve -for file in /var/vmail/*/*/sieve/*.sieve ; do - if [[ "$file" == "/var/vmail/*/*/sieve/*.sieve" ]]; then - continue - fi - sievec "$file" "$(dirname "$file")/../.dovecot.svbin" - chown vmail:vmail "$(dirname "$file")/../.dovecot.svbin" -done - # Fix permissions chown root:root /etc/dovecot/sql/*.conf chown root:dovecot /etc/dovecot/sql/dovecot-dict-sql-sieve* /etc/dovecot/sql/dovecot-dict-sql-quota* /etc/dovecot/auth/passwd-verify.lua diff --git a/data/Dockerfiles/dovecot/rspamd-pipe-ham b/data/Dockerfiles/dovecot/rspamd-pipe-ham index 732af8585..b9a84f1bf 100755 --- a/data/Dockerfiles/dovecot/rspamd-pipe-ham +++ b/data/Dockerfiles/dovecot/rspamd-pipe-ham @@ -3,8 +3,8 @@ FILE=/tmp/mail$$ cat > $FILE trap "/bin/rm -f $FILE" 0 1 2 3 13 15 -cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzydel -cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnham -cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd +cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/fuzzydel +cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/learnham +cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/fuzzyadd exit 0 diff --git a/data/Dockerfiles/dovecot/rspamd-pipe-spam b/data/Dockerfiles/dovecot/rspamd-pipe-spam index a4b91a01f..3f02c4872 100755 --- a/data/Dockerfiles/dovecot/rspamd-pipe-spam +++ b/data/Dockerfiles/dovecot/rspamd-pipe-spam @@ -3,8 +3,8 @@ FILE=/tmp/mail$$ cat > $FILE trap "/bin/rm -f $FILE" 0 1 2 3 13 15 -cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzydel -cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnspam -cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd +cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/fuzzydel +cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/learnspam +cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/fuzzyadd exit 0 diff --git a/data/Dockerfiles/dovecot/sa-rules.sh b/data/Dockerfiles/dovecot/sa-rules.sh index cbfeb5af2..107ea7172 100755 --- a/data/Dockerfiles/dovecot/sa-rules.sh +++ b/data/Dockerfiles/dovecot/sa-rules.sh @@ -21,11 +21,11 @@ sed -i -e 's/\([^\\]\)\$\([^\/]\)/\1\\$\2/g' /etc/rspamd/custom/sa-rules if [[ "$(cat /etc/rspamd/custom/sa-rules | md5sum | cut -d' ' -f1)" != "${HASH_SA_RULES}" ]]; then CONTAINER_NAME=rspamd-mailcow - CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | \ + CONTAINER_ID=$(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | \ jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | \ jq -rc "select( .name | tostring | contains(\"${CONTAINER_NAME}\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id") if [[ ! -z ${CONTAINER_ID} ]]; then - curl --silent --insecure -XPOST --connect-timeout 15 --max-time 120 https://dockerapi/containers/${CONTAINER_ID}/restart + curl --silent --insecure -XPOST --connect-timeout 15 --max-time 120 https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/restart fi fi diff --git a/data/Dockerfiles/netfilter/Dockerfile b/data/Dockerfiles/netfilter/Dockerfile index 4f65f8e08..86f9e3f69 100644 --- a/data/Dockerfiles/netfilter/Dockerfile +++ b/data/Dockerfiles/netfilter/Dockerfile @@ -1,5 +1,6 @@ FROM alpine:3.20 -LABEL maintainer "The Infrastructure Company GmbH " + +LABEL maintainer = "The Infrastructure Company GmbH " WORKDIR /app diff --git a/data/Dockerfiles/olefy/Dockerfile b/data/Dockerfiles/olefy/Dockerfile index e71ea9ff2..3b2729134 100644 --- a/data/Dockerfiles/olefy/Dockerfile +++ b/data/Dockerfiles/olefy/Dockerfile @@ -1,5 +1,6 @@ FROM alpine:3.20 -LABEL maintainer "The Infrastructure Company GmbH " + +LABEL maintainer = "The Infrastructure Company GmbH " ARG PIP_BREAK_SYSTEM_PACKAGES=1 WORKDIR /app diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index 22036b9b3..0ac722b22 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -1,5 +1,6 @@ FROM php:8.2-fpm-alpine3.18 -LABEL maintainer "The Infrastructure Company GmbH " + +LABEL maintainer = "The Infrastructure Company GmbH " # renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?.*)$ ARG APCU_PECL_VERSION=5.1.23 diff --git a/data/Dockerfiles/phpfpm/docker-entrypoint.sh b/data/Dockerfiles/phpfpm/docker-entrypoint.sh index e6c26fd19..87b4e298d 100755 --- a/data/Dockerfiles/phpfpm/docker-entrypoint.sh +++ b/data/Dockerfiles/phpfpm/docker-entrypoint.sh @@ -23,7 +23,7 @@ done # Check mysql_upgrade (master and slave) CONTAINER_ID= until [[ ! -z "${CONTAINER_ID}" ]] && [[ "${CONTAINER_ID}" =~ ^[[:alnum:]]*$ ]]; do - CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"mysql-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" 2> /dev/null) + CONTAINER_ID=$(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"mysql-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" 2> /dev/null) echo "Could not get mysql-mailcow container id... trying again" sleep 2 done @@ -35,7 +35,7 @@ until [[ ${SQL_UPGRADE_STATUS} == 'success' ]]; do echo "Tried to upgrade MySQL and failed, giving up after ${SQL_LOOP_C} retries and starting container (oops, not good)" break fi - SQL_FULL_UPGRADE_RETURN=$(curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_upgrade"}' --silent -H 'Content-type: application/json') + SQL_FULL_UPGRADE_RETURN=$(curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_upgrade"}' --silent -H 'Content-type: application/json') SQL_UPGRADE_STATUS=$(echo ${SQL_FULL_UPGRADE_RETURN} | jq -r .type) SQL_LOOP_C=$((SQL_LOOP_C+1)) echo "SQL upgrade iteration #${SQL_LOOP_C}" @@ -60,12 +60,12 @@ done # doing post-installation stuff, if SQL was upgraded (master and slave) if [ ${SQL_CHANGED} -eq 1 ]; then - POSTFIX=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"postfix-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" 2> /dev/null) + POSTFIX=$(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" 2> /dev/null | jq -rc "select( .name | tostring | contains(\"postfix-mailcow\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id" 2> /dev/null) if [[ -z "${POSTFIX}" ]] || ! [[ "${POSTFIX}" =~ ^[[:alnum:]]*$ ]]; then echo "Could not determine Postfix container ID, skipping Postfix restart." else echo "Restarting Postfix" - curl -X POST --silent --insecure https://dockerapi/containers/${POSTFIX}/restart | jq -r '.msg' + curl -X POST --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${POSTFIX}/restart | jq -r '.msg' echo "Sleeping 5 seconds..." sleep 5 fi @@ -74,7 +74,7 @@ fi # Check mysql tz import (master and slave) TZ_CHECK=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT CONVERT_TZ('2019-11-02 23:33:00','Europe/Berlin','UTC') AS time;" -BN 2> /dev/null) if [[ -z ${TZ_CHECK} ]] || [[ "${TZ_CHECK}" == "NULL" ]]; then - SQL_FULL_TZINFO_IMPORT_RETURN=$(curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_tzinfo_to_sql"}' --silent -H 'Content-type: application/json') + SQL_FULL_TZINFO_IMPORT_RETURN=$(curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_tzinfo_to_sql"}' --silent -H 'Content-type: application/json') echo "MySQL mysql_tzinfo_to_sql - debug output:" echo ${SQL_FULL_TZINFO_IMPORT_RETURN} fi diff --git a/data/Dockerfiles/postfix/Dockerfile b/data/Dockerfiles/postfix/Dockerfile index a45ce12b2..0f1911c62 100644 --- a/data/Dockerfiles/postfix/Dockerfile +++ b/data/Dockerfiles/postfix/Dockerfile @@ -1,5 +1,6 @@ FROM debian:bookworm-slim -LABEL maintainer "The Infrastructure Company GmbH " + +LABEL maintainer = "The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive ENV LC_ALL C diff --git a/data/Dockerfiles/rspamd/Dockerfile b/data/Dockerfiles/rspamd/Dockerfile index 57dea270c..06c8f5ebc 100644 --- a/data/Dockerfiles/rspamd/Dockerfile +++ b/data/Dockerfiles/rspamd/Dockerfile @@ -1,10 +1,10 @@ -FROM debian:bullseye-slim -LABEL maintainer "The Infrastructure Company GmbH " +FROM debian:bookworm-slim +LABEL maintainer = "The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive -ARG RSPAMD_VER=rspamd_3.7.5-2~8c86c1676 -ARG CODENAME=bullseye -ENV LC_ALL C +ARG RSPAMD_VER=rspamd_3.9.1-1~82f43560f +ARG CODENAME=bookworm +ENV LC_ALL=C RUN apt-get update && apt-get install -y --no-install-recommends \ tzdata \ @@ -12,11 +12,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gnupg2 \ apt-transport-https \ dnsutils \ - netcat \ + netcat-traditional \ wget \ redis-tools \ procps \ nano \ + lua-cjson \ && arch=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) \ && wget -P /tmp https://rspamd.com/apt-stable/pool/main/r/rspamd/${RSPAMD_VER}~${CODENAME}_${arch}.deb\ && apt install -y /tmp/${RSPAMD_VER}~${CODENAME}_${arch}.deb \ diff --git a/data/Dockerfiles/rspamd/docker-entrypoint.sh b/data/Dockerfiles/rspamd/docker-entrypoint.sh index 8af7619c2..cf09ee48f 100755 --- a/data/Dockerfiles/rspamd/docker-entrypoint.sh +++ b/data/Dockerfiles/rspamd/docker-entrypoint.sh @@ -124,4 +124,190 @@ for file in /hooks/*; do fi done +# If DQS KEY is set in mailcow.conf add Spamhaus DQS RBLs +if [[ ! -z ${SPAMHAUS_DQS_KEY} ]]; then + cat < /etc/rspamd/custom/dqs-rbl.conf + # Autogenerated by mailcow. DO NOT TOUCH! + spamhaus { + rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net"; + from = false; + } + spamhaus_from { + from = true; + received = false; + rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net"; + returncodes { + SPAMHAUS_ZEN = [ "127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.0.9", "127.0.0.10", "127.0.0.11" ]; + } + } + spamhaus_authbl_received { + # Check if the sender client is listed in AuthBL (AuthBL is *not* part of ZEN) + rbl = "${SPAMHAUS_DQS_KEY}.authbl.dq.spamhaus.net"; + from = false; + received = true; + ipv6 = true; + returncodes { + SH_AUTHBL_RECEIVED = "127.0.0.20" + } + } + spamhaus_dbl { + # Add checks on the HELO string + rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net"; + helo = true; + rdns = true; + dkim = true; + disable_monitoring = true; + returncodes { + RBL_DBL_SPAM = "127.0.1.2"; + RBL_DBL_PHISH = "127.0.1.4"; + RBL_DBL_MALWARE = "127.0.1.5"; + RBL_DBL_BOTNET = "127.0.1.6"; + RBL_DBL_ABUSED_SPAM = "127.0.1.102"; + RBL_DBL_ABUSED_PHISH = "127.0.1.104"; + RBL_DBL_ABUSED_MALWARE = "127.0.1.105"; + RBL_DBL_ABUSED_BOTNET = "127.0.1.106"; + RBL_DBL_DONT_QUERY_IPS = "127.0.1.255"; + } + } + spamhaus_dbl_fullurls { + ignore_defaults = true; + no_ip = true; + rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net"; + selector = 'urls:get_host' + disable_monitoring = true; + returncodes { + DBLABUSED_SPAM_FULLURLS = "127.0.1.102"; + DBLABUSED_PHISH_FULLURLS = "127.0.1.104"; + DBLABUSED_MALWARE_FULLURLS = "127.0.1.105"; + DBLABUSED_BOTNET_FULLURLS = "127.0.1.106"; + } + } + spamhaus_zrd { + # Add checks on the HELO string also for DQS + rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net"; + helo = true; + rdns = true; + dkim = true; + disable_monitoring = true; + returncodes { + RBL_ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"]; + RBL_ZRD_FRESH_DOMAIN = [ + "127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24" + ]; + RBL_ZRD_DONT_QUERY_IPS = "127.0.2.255"; + } + } + "SPAMHAUS_ZEN_URIBL" { + enabled = true; + rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net"; + resolve_ip = true; + checks = ['urls']; + replyto = true; + emails = true; + ipv4 = true; + ipv6 = true; + emails_domainonly = true; + returncodes { + URIBL_SBL = "127.0.0.2"; + URIBL_SBL_CSS = "127.0.0.3"; + URIBL_XBL = ["127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7"]; + URIBL_PBL = ["127.0.0.10", "127.0.0.11"]; + URIBL_DROP = "127.0.0.9"; + } + } + SH_EMAIL_DBL { + ignore_defaults = true; + replyto = true; + emails_domainonly = true; + disable_monitoring = true; + rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net"; + returncodes = { + SH_EMAIL_DBL = [ + "127.0.1.2", + "127.0.1.4", + "127.0.1.5", + "127.0.1.6" + ]; + SH_EMAIL_DBL_ABUSED = [ + "127.0.1.102", + "127.0.1.104", + "127.0.1.105", + "127.0.1.106" + ]; + SH_EMAIL_DBL_DONT_QUERY_IPS = [ "127.0.1.255" ]; + } + } + SH_EMAIL_ZRD { + ignore_defaults = true; + replyto = true; + emails_domainonly = true; + disable_monitoring = true; + rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net"; + returncodes = { + SH_EMAIL_ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"]; + SH_EMAIL_ZRD_FRESH_DOMAIN = [ + "127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24" + ]; + SH_EMAIL_ZRD_DONT_QUERY_IPS = [ "127.0.2.255" ]; + } + } + "DBL" { + # override the defaults for DBL defined in modules.d/rbl.conf + rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net"; + disable_monitoring = true; + } + "ZRD" { + ignore_defaults = true; + rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net"; + no_ip = true; + dkim = true; + emails = true; + emails_domainonly = true; + urls = true; + returncodes = { + ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"]; + ZRD_FRESH_DOMAIN = ["127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24"]; + } + } + spamhaus_sbl_url { + ignore_defaults = true + rbl = "${SPAMHAUS_DQS_KEY}.sbl.dq.spamhaus.net"; + checks = ['urls']; + disable_monitoring = true; + returncodes { + SPAMHAUS_SBL_URL = "127.0.0.2"; + } + } + + SH_HBL_EMAIL { + ignore_defaults = true; + rbl = "_email.${SPAMHAUS_DQS_KEY}.hbl.dq.spamhaus.net"; + emails_domainonly = false; + selector = "from('smtp').lower;from('mime').lower"; + ignore_whitelist = true; + checks = ['emails', 'replyto']; + hash = "sha1"; + returncodes = { + SH_HBL_EMAIL = [ + "127.0.3.2" + ]; + } + } + + spamhaus_dqs_hbl { + symbol = "HBL_FILE_UNKNOWN"; + rbl = "_file.${SPAMHAUS_DQS_KEY}.hbl.dq.spamhaus.net."; + selector = "attachments('rbase32', 'sha256')"; + ignore_whitelist = true; + ignore_defaults = true; + returncodes { + SH_HBL_FILE_MALICIOUS = "127.0.3.10"; + SH_HBL_FILE_SUSPICIOUS = "127.0.3.15"; + } + } +EOF +else + rm -rf /etc/rspamd/custom/dqs-rbl.conf +fi + exec "$@" diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index 760c95014..6366c12ff 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -1,5 +1,6 @@ FROM debian:bullseye-slim -LABEL maintainer "The Infrastructure Company GmbH " + +LABEL maintainer = "The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_VERSION=bullseye diff --git a/data/Dockerfiles/unbound/Dockerfile b/data/Dockerfiles/unbound/Dockerfile index 0ad5a05f0..958d24e5f 100644 --- a/data/Dockerfiles/unbound/Dockerfile +++ b/data/Dockerfiles/unbound/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.20 -LABEL maintainer "The Infrastructure Company GmbH " +LABEL maintainer = "The Infrastructure Company GmbH " RUN apk add --update --no-cache \ curl \ diff --git a/data/Dockerfiles/watchdog/Dockerfile b/data/Dockerfiles/watchdog/Dockerfile index a844d73bc..0f3e7dfb9 100644 --- a/data/Dockerfiles/watchdog/Dockerfile +++ b/data/Dockerfiles/watchdog/Dockerfile @@ -1,5 +1,6 @@ FROM alpine:3.20 -LABEL maintainer "The Infrastructure Company GmbH " + +LABEL maintainer = "The Infrastructure Company GmbH " # Installation RUN apk add --update \ diff --git a/data/Dockerfiles/watchdog/watchdog.sh b/data/Dockerfiles/watchdog/watchdog.sh index cb342c138..d4de6d8db 100755 --- a/data/Dockerfiles/watchdog/watchdog.sh +++ b/data/Dockerfiles/watchdog/watchdog.sh @@ -191,12 +191,12 @@ get_container_ip() { else sleep 0.5 # get long container id for exact match - CONTAINER_ID=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring == \"${1}\") | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id")) + CONTAINER_ID=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring == \"${1}\") | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id")) # returned id can have multiple elements (if scaled), shuffle for random test CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf)) if [[ ! -z ${CONTAINER_ID} ]]; then for matched_container in "${CONTAINER_ID[@]}"; do - CONTAINER_IPS=($(curl --silent --insecure https://dockerapi/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress')) + CONTAINER_IPS=($(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress')) for ip_match in "${CONTAINER_IPS[@]}"; do # grep will do nothing if one of these vars is empty [[ -z ${ip_match} ]] && continue @@ -716,7 +716,7 @@ 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 | sed 's/\..*//' ) +' | usr/bin/curl --max-time 10 -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd.${COMPOSE_PROJECT_NAME}_mailcow-network/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)) @@ -1095,12 +1095,12 @@ while true; do elif [[ ${com_pipe_answer} =~ .+-mailcow ]]; then kill -STOP ${BACKGROUND_TASKS[*]} sleep 10 - CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"${com_pipe_answer}\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id") + CONTAINER_ID=$(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], project: .Config.Labels[\"com.docker.compose.project\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"${com_pipe_answer}\")) | select( .project | tostring | contains(\"${COMPOSE_PROJECT_NAME,,}\")) | .id") if [[ ! -z ${CONTAINER_ID} ]]; then if [[ "${com_pipe_answer}" == "php-fpm-mailcow" ]]; then - HAS_INITDB=$(curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/top | jq '.msg.Processes[] | contains(["php -c /usr/local/etc/php -f /web/inc/init_db.inc.php"])' | grep true) + HAS_INITDB=$(curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/top | jq '.msg.Processes[] | contains(["php -c /usr/local/etc/php -f /web/inc/init_db.inc.php"])' | grep true) fi - S_RUNNING=$(($(date +%s) - $(curl --silent --insecure https://dockerapi/containers/${CONTAINER_ID}/json | jq .State.StartedAt | xargs -n1 date +%s -d))) + S_RUNNING=$(($(date +%s) - $(curl --silent --insecure https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/json | jq .State.StartedAt | xargs -n1 date +%s -d))) if [ ${S_RUNNING} -lt 360 ]; then log_msg "Container is running for less than 360 seconds, skipping action..." elif [[ ! -z ${HAS_INITDB} ]]; then @@ -1108,7 +1108,7 @@ while true; do sleep 60 else log_msg "Sending restart command to ${CONTAINER_ID}..." - curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/restart + curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/restart notify_error "${com_pipe_answer}" log_msg "Wait for restarted container to settle and continue watching..." sleep 35 diff --git a/data/conf/dovecot/dovecot.folders.conf b/data/conf/dovecot/dovecot.folders.conf index 99c9670fa..fa6872679 100644 --- a/data/conf/dovecot/dovecot.folders.conf +++ b/data/conf/dovecot/dovecot.folders.conf @@ -289,5 +289,20 @@ namespace inbox { mailbox "Kladde" { special_use = \Drafts } + mailbox "Πρόχειρα" { + special_use = \Drafts + } + mailbox "Απεσταλμένα" { + special_use = \Sent + } + mailbox "Κάδος απορριμάτων" { + special_use = \Trash + } + mailbox "Ανεπιθύμητα" { + special_use = \Junk + } + mailbox "Αρχειοθετημένα" { + special_use = \Archive + } prefix = -} \ No newline at end of file +} diff --git a/data/conf/rspamd/local.d/rbl.conf b/data/conf/rspamd/local.d/rbl.conf index d49dae034..7f2976a08 100644 --- a/data/conf/rspamd/local.d/rbl.conf +++ b/data/conf/rspamd/local.d/rbl.conf @@ -2,6 +2,7 @@ rbls { interserver_ip { symbol = "RBL_INTERSERVER_IP"; rbl = "rbl.interserver.net"; + from = true; ipv6 = false; returncodes { RBL_INTERSERVER_BAD_IP = "127.0.0.2"; @@ -19,4 +20,7 @@ rbls { RBL_INTERSERVER_BAD_URI = "127.0.0.2"; } } -} + +.include(try=true,override=true,priority=5) "$LOCAL_CONFDIR/custom/dqs-rbl.conf" + +} \ No newline at end of file diff --git a/data/conf/rspamd/local.d/rbl_group.conf b/data/conf/rspamd/local.d/rbl_group.conf index 4d346f158..916de4ef0 100644 --- a/data/conf/rspamd/local.d/rbl_group.conf +++ b/data/conf/rspamd/local.d/rbl_group.conf @@ -17,4 +17,261 @@ symbols = { score = 4.0; description = "Listed on Interserver RBL"; } + + "SPAMHAUS_ZEN" { + weight = 7.0; + } + "SH_AUTHBL_RECEIVED" { + weight = 4.0; + } + "RBL_DBL_SPAM" { + weight = 7.0; + } + "RBL_DBL_PHISH" { + weight = 7.0; + } + "RBL_DBL_MALWARE" { + weight = 7.0; + } + "RBL_DBL_BOTNET" { + weight = 7.0; + } + "RBL_DBL_ABUSED_SPAM" { + weight = 3.0; + } + "RBL_DBL_ABUSED_PHISH" { + weight = 3.0; + } + "RBL_DBL_ABUSED_MALWARE" { + weight = 3.0; + } + "RBL_DBL_ABUSED_BOTNET" { + weight = 3.0; + } + "RBL_ZRD_VERY_FRESH_DOMAIN" { + weight = 7.0; + } + "RBL_ZRD_FRESH_DOMAIN" { + weight = 4.0; + } + "ZRD_VERY_FRESH_DOMAIN" { + weight = 7.0; + } + "ZRD_FRESH_DOMAIN" { + weight = 4.0; + } + "SH_EMAIL_DBL" { + weight = 7.0; + } + "SH_EMAIL_DBL_ABUSED" { + weight = 7.0; + } + "SH_EMAIL_ZRD_VERY_FRESH_DOMAIN" { + weight = 7.0; + } + "SH_EMAIL_ZRD_FRESH_DOMAIN" { + weight = 4.0; + } + "RBL_DBL_DONT_QUERY_IPS" { + weight = 0.0; + } + "RBL_ZRD_DONT_QUERY_IPS" { + weight = 0.0; + } + "SH_EMAIL_ZRD_DONT_QUERY_IPS" { + weight = 0.0; + } + "SH_EMAIL_DBL_DONT_QUERY_IPS" { + weight = 0.0; + } + "DBL" { + weight = 0.0; + description = "DBL unknown result"; + groups = ["spamhaus"]; + } + "DBL_SPAM" { + weight = 7; + description = "DBL uribl spam"; + groups = ["spamhaus"]; + } + "DBL_PHISH" { + weight = 7; + description = "DBL uribl phishing"; + groups = ["spamhaus"]; + } + "DBL_MALWARE" { + weight = 7; + description = "DBL uribl malware"; + groups = ["spamhaus"]; + } + "DBL_BOTNET" { + weight = 7; + description = "DBL uribl botnet C&C domain"; + groups = ["spamhaus"]; + } + + + "DBLABUSED_SPAM_FULLURLS" { + weight = 5.5; + description = "DBL uribl abused legit spam"; + groups = ["spamhaus"]; + } + "DBLABUSED_PHISH_FULLURLS" { + weight = 5.5; + description = "DBL uribl abused legit phish"; + groups = ["spamhaus"]; + } + "DBLABUSED_MALWARE_FULLURLS" { + weight = 5.5; + description = "DBL uribl abused legit malware"; + groups = ["spamhaus"]; + } + "DBLABUSED_BOTNET_FULLURLS" { + weight = 5.5; + description = "DBL uribl abused legit botnet"; + groups = ["spamhaus"]; + } + + "DBL_ABUSE" { + weight = 5.5; + description = "DBL uribl abused legit spam"; + groups = ["spamhaus"]; + } + "DBL_ABUSE_REDIR" { + weight = 1.5; + description = "DBL uribl abused spammed redirector domain"; + groups = ["spamhaus"]; + } + "DBL_ABUSE_PHISH" { + weight = 5.5; + description = "DBL uribl abused legit phish"; + groups = ["spamhaus"]; + } + "DBL_ABUSE_MALWARE" { + weight = 5.5; + description = "DBL uribl abused legit malware"; + groups = ["spamhaus"]; + } + "DBL_ABUSE_BOTNET" { + weight = 5.5; + description = "DBL uribl abused legit botnet C&C"; + groups = ["spamhaus"]; + } + "DBL_PROHIBIT" { + weight = 0.0; + description = "DBL uribl IP queries prohibited!"; + groups = ["spamhaus"]; + } + "DBL_BLOCKED_OPENRESOLVER" { + weight = 0.0; + description = "You are querying Spamhaus from an open resolver, please see https://www.spamhaus.org/returnc/pub/"; + groups = ["spamhaus"]; + } + "DBL_BLOCKED" { + weight = 0.0; + description = "You are exceeding the query limit, please see https://www.spamhaus.org/returnc/vol/"; + groups = ["spamhaus"]; + } + "SPAMHAUS_ZEN_URIBL" { + weight = 0.0; + description = "Spamhaus ZEN URIBL: Filtered result"; + groups = ["spamhaus"]; + } + "URIBL_SBL" { + weight = 6.5; + description = "A domain in the message body resolves to an IP listed in Spamhaus SBL"; + one_shot = true; + groups = ["spamhaus"]; + } + "URIBL_SBL_CSS" { + weight = 6.5; + description = "A domain in the message body resolves to an IP listed in Spamhaus SBL CSS"; + one_shot = true; + groups = ["spamhaus"]; + } + "URIBL_PBL" { + weight = 0.01; + description = "A domain in the message body resolves to an IP listed in Spamhaus PBL"; + one_shot = true; + groups = ["spamhaus"]; + } + "URIBL_DROP" { + weight = 6.5; + description = "A domain in the message body resolves to an IP listed in Spamhaus DROP"; + one_shot = true; + groups = ["spamhaus"]; + } + "URIBL_XBL" { + weight = 5.0; + description = "A domain in the message body resolves to an IP listed in Spamhaus XBL"; + one_shot = true; + groups = ["spamhaus"]; + } + "SPAMHAUS_SBL_URL" { + weight = 6.5; + description = "A numeric URL in the message body is listed in Spamhaus SBL"; + one_shot = true; + groups = ["spamhaus"]; + } + + "SH_HBL_EMAIL" { + weight = 7; + description = "Email listed in HBL"; + groups = ["spamhaus"]; + } + + "SH_HBL_FILE_MALICIOUS" { + weight = 7; + description = "An attachment hash is listed in Spamhaus HBL as malicious"; + groups = ["spamhaus"]; + } + + "SH_HBL_FILE_SUSPICIOUS" { + weight = 5; + description = "An attachment hash is listed in Spamhaus HBL as suspicious"; + groups = ["spamhaus"]; + } + + "RBL_SPAMHAUS_CW_BTC" { + score = 7; + description = "Bitcoin found in Spamhaus cryptowallet list"; + groups = ["spamhaus"]; + } + + "RBL_SPAMHAUS_CW_ETH" { + score = 7; + description = "Ethereum found in Spamhaus cryptowallet list"; + groups = ["spamhaus"]; + } + + "RBL_SPAMHAUS_CW_BCH" { + score = 7; + description = "Bitcoinhash found in Spamhaus cryptowallet list"; + groups = ["spamhaus"]; + } + + "RBL_SPAMHAUS_CW_XMR" { + score = 7; + description = "Monero found in Spamhaus cryptowallet list"; + groups = ["spamhaus"]; + } + + "RBL_SPAMHAUS_CW_LTC" { + score = 7; + description = "Litecoin found in Spamhaus cryptowallet list"; + groups = ["spamhaus"]; + } + + "RBL_SPAMHAUS_CW_XRP" { + score = 7; + description = "Ripple found in Spamhaus cryptowallet list"; + groups = ["spamhaus"]; + } + + "RBL_SPAMHAUS_HBL_URL" { + score = 7; + description = "URL found in spamhaus HBL blocklist"; + groups = ["spamhaus"]; + } + } diff --git a/data/web/autoconfig.php b/data/web/autoconfig.php index 95952df0d..750463419 100644 --- a/data/web/autoconfig.php +++ b/data/web/autoconfig.php @@ -39,6 +39,9 @@ header('Content-Type: application/xml'); %EMAILADDRESS% password-cleartext + @@ -46,6 +49,7 @@ header('Content-Type: application/xml'); %EMAILADDRESS% password-cleartext + %EMAILADDRESS% password-cleartext + @@ -84,6 +91,7 @@ if (count($records) == 0 || $records[0]['target'] != '') { ?> %EMAILADDRESS% password-cleartext + If you didn't change the password given to you by the administrator or if you didn't change it in a long time, please consider doing that now. diff --git a/data/web/inc/lib/sieve/extensions/enotify.xml b/data/web/inc/lib/sieve/extensions/enotify.xml new file mode 100644 index 000000000..b4686a333 --- /dev/null +++ b/data/web/inc/lib/sieve/extensions/enotify.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/web/inc/lib/sieve/extensions/mime.xml b/data/web/inc/lib/sieve/extensions/mime.xml new file mode 100644 index 000000000..d7e200f02 --- /dev/null +++ b/data/web/inc/lib/sieve/extensions/mime.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/web/lang/lang.nb-no.json b/data/web/lang/lang.nb-no.json index 830d5b423..a6a7a0ca7 100644 --- a/data/web/lang/lang.nb-no.json +++ b/data/web/lang/lang.nb-no.json @@ -322,5 +322,148 @@ "invalid_nexthop": "\"Next hop\"-format er ugyldig", "img_dimensions_exceeded": "Bildet overskriver maksimal bildestørrelse", "img_size_exceeded": "Bildet overskrider maksimal filstørrelse" + }, + "debug": { + "logs": "Logger", + "update_available": "En oppdatering er tilgjengelig", + "service": "Tjeneste", + "show_ip": "Vis offentlig IP", + "solr_dead": "Solr starter, er deaktivert eller døde", + "memory": "Minne", + "online_users": "Tilkoblede brukere", + "restart_container": "Omstart", + "size": "Størrelse", + "solr_status": "Solr-status", + "started_at": "Startet ved", + "started_on": "Startet den", + "static_logs": "Statiske logger", + "success": "Suksess", + "system_containers": "System og kontainere", + "timezone": "Tidssone", + "uptime": "Oppetid", + "no_update_available": "Systemet kjører siste versjon", + "update_failed": "Kunne ikke se etter oppdateringer", + "username": "Brukernavn", + "wip": "Foreløpig under utvikling" + }, + "diagnostics": { + "dns_records_24hours": "Vennligst vær oppmerksom på at endringer gjort i DNS kan ta opp til 24 timer før riktig status vises på denne siden. Den er ment som en måte for deg å enkelt se hvordan du kan sette opp DNS-oppføringene dine og se at alle oppføringer er korrekt lagret i DNS.", + "cname_from_a": "Verdi hentet fra A/AAAA-oppføring. Dette er støttet så lenge oppføringen peker til riktig ressurs.", + "dns_records_docs": "Vennligst også se dokumentasjonen.", + "dns_records": "DNS-oppføringer", + "dns_records_data": "Korrekte data", + "dns_records_name": "Navn", + "dns_records_status": "Nåværende status", + "dns_records_type": "Type", + "optional": "Denne oppføringen er valgfri." + }, + "edit": { + "bcc_dest_format": "BCC-destinasjon må være en enkelt, gyldig epostadresse.
Hvis du trenger å sende en kopi til flere adresser, opprett et alias og bruk det her.", + "pushover_info": "Innstillinger for pushvarslinger vil gjelde alle rene (ikke-spam) eposter levert til %s, inkludert aliaser (delte, ikke-delte, taggede).", + "relay_transport_info": "
Info
Du kan definere transportmappinger for et spesifikt mål for dette domenet. Hvis dette ikke er definert, blir det gjort et MX-oppslag.", + "delete2duplicates": "Slett duplikater på målvert", + "description": "Beskrivelse", + "disable_login": "Ikke tillat innlogging (innkommende epost blir likevel mottatt)", + "domain_admin": "Endre domeneadministrator", + "max_mailboxes": "Maks antall mailbokser", + "quota_warning_bcc_info": "Advarsler blir sendt som separate kopier til de følgende mottakerne. Emnet vil få lagt til det korresponderende brukernavnet i parantes, for eksempel: Kvotevarsel (user@example.com).", + "domain_footer_skip_replies": "Ignorer bunntekst ved svar på epost", + "extended_sender_acl": "Eksterne avsenderadresser", + "extended_sender_acl_info": "En DKIM-domenenøkkel bør importeres, hvis tilgjengelig.
\n Husk å legge denne serveren til den korresponderende SPF TXT-oppføringen.
\n Når et domene eller aliasdomene legges til på denne serveren, og det overlapper med en ekstern adresse, blir den eksterne adressen fjernet.
\n Bruk @domain.tld for å tillate sending som *@domain.tld.", + "password_repeat": "Bekreft passord (gjenta)", + "pushover_title": "Varslingstittel", + "pushover_vars": "Når et avsenderfilter ikke er definert, vil alle epostere bli vurdert.
Regex-filtre såvel så eksakte avsendersjekker kan bli individuelt definert og vil bli vurdert sekvensielt. De er ikke avhengige av hverandre.
Tilgjengelige variabler for tekst og tittel (vennligst observer policyer for databeskyttelse)", + "admin": "Endre administrator", + "domain_footer_info": "Bunntekst for hele domenet leggese til alle utgående eposter assosiert med en adresse innenfor dette domenet.
De følgende variablene kan brukes for bunnteksten:", + "domain_footer_info_vars": { + "custom": "{= foo =} - Hvis mailboksen har en spesialattributt \"foo\" med verdi \"bar\", vil den vise \"bar\"", + "auth_user": "{= auth_user =} - Autentisert brukernavn spesifisert av en MTA", + "from_user": "{= from_user =} - Fra brukerdelen av konvolutten, f.eks. for \"moo@mailcow.tld\" vil den returnere \"moo\"", + "from_name": "{= from_name =} - Fra-navn fra konvolutten, f.eks. for \"Mailcow <moo@mailcow.tld>\" vil den vise \"Mailcow\"", + "from_addr": "{= from_addr =} - Fra adressedelen av konvolutten", + "from_domain": "{= from_domain =} - Fra domene-delen av konvolutten" + }, + "mailbox_relayhost_info": "Aktiveres kun for mailboksen og direkte aliaser, overstyrer domene-videresendingsvert.", + "mbox_rl_info": "Denne begrensningen gjelder for SASL-innloggingsnavnet, dersom det er likt noen \"from\"-adresser benyttet av den innloggede brukeren. En mailboks-begrensning overstyrer en domene-begrensning.", + "allow_from_smtp_info": "La stå tom for å tillate alle avsendere.
IPv4/IPv6-adresser og -nettverk.", + "domain": "Endre domene", + "encryption": "Kryptering", + "exclude": "Ekskluder objekter (regex)", + "footer_exclude": "Ekskluder fra bunntekst", + "gal_info": "GAL inneholder alle objeker i et domene og kan ikke redigeres av noen brukere. Ledig/opptatt-informasjon i SOGo mangler dersom den deaktiveres! Start SOGo på nytt for å aktivere endringene.", + "grant_types": "Grant-typer", + "hostname": "Vertsnavn", + "inactive": "Inaktiv", + "kind": "Type", + "last_modified": "Sist endret", + "lookup_mx": "Målet er et regex-uttrykk for å matche mot MX_navnet (*\\.google\\.com for å route all epost som skal til en MX-server som slutter på google.com, via dette målet)", + "mailbox": "Endre mailboks", + "mailbox_quota_def": "Standardkvote for mailboks", + "max_quota": "Maks kvote pr. mailboks (MiB)", + "maxage": "Maksimal alder for meldinger, i dager, som vil hentes fra ekstern
(0 = ignorer alder)", + "maxbytespersecond": "Maks bytes pr. sekund
(0 = ubegrenset)", + "pushover_sender_array": "Bare vurder de følgende avsenderadressene (komma-separert)", + "pushover_sender_regex": "Vurder følgende avsender-regex", + "pushover_text": "Varslingstekst", + "pushover_sound": "Lyd", + "pushover_verify": "Bekreft identifikasjon", + "quota_mb": "Kvote (MiB)", + "quota_warning_bcc": "Kvotevarsling BCC", + "ratelimit": "Mengdebegrensning", + "domain_footer": "Bunntekst for hele domenet", + "private_comment": "Privat kommentar", + "public_comment": "Offentlig kommentar", + "client_id": "Klient-ID", + "full_name": "Fullt navn", + "gal": "Global adresseliste", + "max_aliases": "Maks. antall aliaser", + "mins_interval": "Intervall (min)", + "multiple_bookings": "Flere bookinger", + "none_inherit": "Ingen / arve", + "acl": "ACL (rettighet)", + "active": "Aktiv", + "advanced_settings": "Avanserte innstillinger", + "alias": "Endre alias", + "allow_from_smtp": "Tillat kun disse IPene å bruke SMTP", + "allowed_protocols": "Tillatte protokoller", + "app_name": "Appnavn", + "app_passwd": "App-passord", + "app_passwd_protocols": "Tillatte protokoller for app-passord", + "automap": "Prøv å automatisk mappe opp mapper (\"Sent items\", \"Sent\" => \"Sendt\" etc.)", + "backup_mx_options": "Videresendingsalternativer", + "client_secret": "Klient-hemmelighet", + "comment_info": "En privat kommentar er ikke synlig for brukeren, mens en offentlig kommentar vises som et tooltip når man holder muspekeren over det", + "created_on": "Opprettet den", + "custom_attributes": "Valgfrie attributter", + "delete1": "Slett fra kilde når fullført", + "delete2": "Slett meldinger på målvert som ikke finnes på kildeverten", + "delete_ays": "Vennligst bekreft slettingen.", + "domain_footer_html": "HTML-bunntekst", + "domain_footer_plain": "PLAIN-bunntekst", + "domain_quota": "Domenekvote", + "domains": "Domener", + "dont_check_sender_acl": "Deaktivere sendersjekk for domene %s (+ aliasdomener)", + "edit_alias_domain": "Endre aliasdomene", + "force_pw_update": "Tving endring av passord ved neste innlogging", + "force_pw_update_info": "Denne brukeren vil bare kunne logge inn på %s. App-passord kan fremdeles brukes.", + "generate": "generer", + "nexthop": "Neste hopp", + "password": "Passord", + "previous": "Forrige side", + "pushover": "Pushover", + "pushover_evaluate_x_prio": "Eskaler mail med høy prioritet [X-Priority: 1]", + "pushover_only_x_prio": "Bare vurder epost med høy prioritet [X-Priority: 1]", + "redirect_uri": "Omdirigerings-/tilbakekallings-URL", + "relay_all": "Videresend alle mottakere", + "relay_all_info": "↪ Hvis du velger å ikke videresende alle mottakkere, så må du legge til en (\"blind\") mailboks for hver eneste mottaker det skal videresendes for.", + "relay_domain": "Videresend dette domenet", + "relay_unknown_only": "Videresend kun ikke-eksisterende mailbokser. Eksisterende mailbokser vil bli levert lokalt.", + "relayhost": "Avsender-avhengige transportmetoder", + "remove": "Fjern", + "resource": "Ressurs", + "save": "Lagre endringer", + "scope": "Omfang", + "sender_acl": "Tillat å sende som", + "sender_acl_disabled": "Avsender-sjekk er deaktivert" } } diff --git a/docker-compose.yml b/docker-compose.yml index 665d55085..783613c28 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -80,7 +80,7 @@ services: - clamd rspamd-mailcow: - image: mailcow/rspamd:1.96 + image: mailcow/rspamd:1.97 stop_grace_period: 30s depends_on: - dovecot-mailcow @@ -90,6 +90,7 @@ services: - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64} - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + - SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-} volumes: - ./data/hooks/rspamd:/hooks:Z - ./data/conf/rspamd/custom/:/etc/rspamd/custom:z @@ -110,7 +111,7 @@ services: - rspamd php-fpm-mailcow: - image: mailcow/phpfpm:1.87 + image: mailcow/phpfpm:1.88 command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" depends_on: - redis-mailcow @@ -236,7 +237,7 @@ services: - sogo dovecot-mailcow: - image: mailcow/dovecot:nightly-20240731 + image: mailcow/dovecot:nightly-20240807 depends_on: - mysql-mailcow - netfilter-mailcow @@ -424,7 +425,7 @@ services: condition: service_started unbound-mailcow: condition: service_healthy - image: mailcow/acme:1.88 + image: mailcow/acme:1.89 dns: - ${IPV4_NETWORK:-172.22.1}.254 environment: diff --git a/generate_config.sh b/generate_config.sh index 72f466315..e1569f40d 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -25,6 +25,16 @@ for bin in openssl curl docker git awk sha1sum grep cut; do if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi done +# Check Docker Version (need at least 24.X) +docker_version=$(docker -v | grep -oP '\d+\.\d+\.\d+' | cut -d '.' -f 1) + +if [[ $docker_version -lt 24 ]]; then + echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m" + echo -e "\e[33mmailcow needs a newer Docker version to work properly...\e[0m" + echo -e "\e[31mPlease update your Docker installation... exiting\e[0m" + exit 1 +fi + if docker compose > /dev/null 2>&1; then if docker compose version --short | grep -e "^2." -e "^v2." > /dev/null 2>&1; then COMPOSE_VERSION=native @@ -147,40 +157,44 @@ done MEM_TOTAL=$(awk '/MemTotal/ {print $2}' /proc/meminfo) -if [ ${MEM_TOTAL} -le "2621440" ]; then - echo "Installed memory is <= 2.5 GiB. It is recommended to disable ClamAV to prevent out-of-memory situations." - echo "ClamAV can be re-enabled by setting SKIP_CLAMD=n in mailcow.conf." - read -r -p "Do you want to disable ClamAV now? [Y/n] " response - case $response in - [nN][oO]|[nN]) - SKIP_CLAMD=n +if [ -z "${SKIP_CLAMD}" ]; then + if [ ${MEM_TOTAL} -le "2621440" ]; then + echo "Installed memory is <= 2.5 GiB. It is recommended to disable ClamAV to prevent out-of-memory situations." + echo "ClamAV can be re-enabled by setting SKIP_CLAMD=n in mailcow.conf." + read -r -p "Do you want to disable ClamAV now? [Y/n] " response + case $response in + [nN][oO]|[nN]) + SKIP_CLAMD=n + ;; + *) + SKIP_CLAMD=y ;; - *) - SKIP_CLAMD=y - ;; - esac -else - SKIP_CLAMD=n + esac + else + SKIP_CLAMD=n + fi fi -if [ ${MEM_TOTAL} -le "2097152" ]; then - echo "Disabling Solr on low-memory system." - SKIP_SOLR=y -elif [ ${MEM_TOTAL} -le "3670016" ]; then - echo "Installed memory is <= 3.5 GiB. It is recommended to disable Solr to prevent out-of-memory situations." - echo "Solr is a prone to run OOM and should be monitored. The default Solr heap size is 1024 MiB and should be set in mailcow.conf according to your expected load." - echo "Solr can be re-enabled by setting SKIP_SOLR=n in mailcow.conf but will refuse to start with less than 2 GB total memory." - read -r -p "Do you want to disable Solr now? [Y/n] " response - case $response in - [nN][oO]|[nN]) - SKIP_SOLR=n +if [ -z "${SKIP_SOLR}" ]; then + if [ ${MEM_TOTAL} -le "2097152" ]; then + echo "Disabling Solr on low-memory system." + SKIP_SOLR=y + elif [ ${MEM_TOTAL} -le "3670016" ]; then + echo "Installed memory is <= 3.5 GiB. It is recommended to disable Solr to prevent out-of-memory situations." + echo "Solr is a prone to run OOM and should be monitored. The default Solr heap size is 1024 MiB and should be set in mailcow.conf according to your expected load." + echo "Solr can be re-enabled by setting SKIP_SOLR=n in mailcow.conf but will refuse to start with less than 2 GB total memory." + read -r -p "Do you want to disable Solr now? [Y/n] " response + case $response in + [nN][oO]|[nN]) + SKIP_SOLR=n + ;; + *) + SKIP_SOLR=y ;; - *) - SKIP_SOLR=y - ;; - esac -else - SKIP_SOLR=n + esac + else + SKIP_SOLR=n + fi fi if [[ ${SKIP_BRANCH} != y ]]; then diff --git a/update.sh b/update.sh index 0c8f85fed..b89514e58 100755 --- a/update.sh +++ b/update.sh @@ -328,6 +328,16 @@ for bin in curl docker git awk sha1sum grep cut; do fi done +# Check Docker Version (need at least 24.X) +docker_version=$(docker -v | grep -oP '\d+\.\d+\.\d+' | cut -d '.' -f 1) + +if [[ $docker_version -lt 24 ]]; then + echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m" + echo -e "\e[33mmailcow needs a newer Docker version to work properly... continuing on your own risk!\e[0m" + echo -e "\e[31mPlease update your Docker installation... sleeping 10s\e[0m" + sleep 10 +fi + export LC_ALL=C DATE=$(date +%Y-%m-%d_%H_%M_%S) BRANCH=$(cd ${SCRIPT_DIR}; git rev-parse --abbrev-ref HEAD) @@ -399,17 +409,18 @@ while (($#)); do -f|--force - Force update, do not ask questions -d|--dev - Enables Developer Mode (No Checkout of update.sh for tests) ' - exit 1 + exit 0 esac shift done +[[ ! -f mailcow.conf ]] && { echo -e "\e[31mmailcow.conf is missing! Is mailcow installed?\e[0m"; exit 1;} + chmod 600 mailcow.conf source mailcow.conf detect_docker_compose_command -[[ ! -f mailcow.conf ]] && { echo "mailcow.conf is missing! Is mailcow installed?"; exit 1;} DOTS=${MAILCOW_HOSTNAME//[^.]}; if [ ${#DOTS} -lt 1 ]; then echo -e "\e[31mMAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is not a FQDN!\e[0m" @@ -424,7 +435,7 @@ elif [ ${#DOTS} -eq 1 ]; then echo "Find more information about why this message exists here: https://github.com/mailcow/mailcow-dockerized/issues/1572" read -r -p "Do you want to proceed anyway? [y/N] " response if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then - echo "OK. Procceding." + echo "OK. Proceeding." else echo "OK. Exiting." exit 1 @@ -807,7 +818,7 @@ if ! [ $NEW_BRANCH ]; then echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m" else - echo -e "\e[33mYou are receiving updates from a unsupported branch.\e[0m" + echo -e "\e[33mYou are receiving updates from an unsupported branch.\e[0m" sleep 1 echo -e "\e[33mThe mailcow stack might still work but it is recommended to switch to the master branch (stable builds).\e[0m" echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m" @@ -818,14 +829,14 @@ elif [ $FORCE ]; then echo -e "\e[31mPlease rerun the update.sh Script without the --force/-f parameter.\e[0m" sleep 1 elif [ $NEW_BRANCH == "master" ] && [ $CURRENT_BRANCH != "master" ]; then - echo -e "\e[33mYou are about to switch your mailcow Updates to the stable (master) branch.\e[0m" + echo -e "\e[33mYou are about to switch your mailcow updates to the stable (master) branch.\e[0m" sleep 1 - echo -e "\e[33mBefore you do: Please take a backup of all components to ensure that no Data is lost...\e[0m" + echo -e "\e[33mBefore you do: Please take a backup of all components to ensure that no data is lost...\e[0m" sleep 1 - echo -e "\e[31mWARNING: Please see on GitHub or ask in the communitys if a switch to master is stable or not. - In some rear cases a Update back to master can destroy your mailcow configuration in case of Database Upgrades etc. - Normally a upgrade back to master should be safe during each full release. - Check GitHub for Database Changes and Update only if there similar to the full release!\e[0m" + echo -e "\e[31mWARNING: Please see on GitHub or ask in the community if a switch to master is stable or not. + In some rear cases an update back to master can destroy your mailcow configuration such as database upgrade, etc. + Normally an upgrade back to master should be safe during each full release. + Check GitHub for Database changes and update only if there similar to the full release!\e[0m" read -r -p "Are you sure you that want to continue upgrading to the stable (master) branch? [y/N] " response if [[ ! "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then echo "OK. If you prepared yourself for that please run the update.sh Script with the --stable parameter again to trigger this process here." @@ -972,7 +983,7 @@ if [ ! $DEV ]; 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 elif [[ ${MERGE_RETURN} == 1 ]]; then - echo -e "\e[93mPotenial conflict, trying to fix...\e[0m" + echo -e "\e[93mPotential 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