diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index c33772db4b..ed5ce90a11 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -24,6 +24,7 @@ RUN addgroup -g 5000 vmail \ envsubst \ ca-certificates \ curl \ + coreutils \ jq \ lua \ lua-cjson \ @@ -103,7 +104,7 @@ RUN addgroup -g 5000 vmail \ dovecot-submissiond \ dovecot-pigeonhole-plugin \ dovecot-pop3d \ - dovecot-fts-solr \ + dovecot-fts-flatcurve \ && 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 \ @@ -127,6 +128,7 @@ COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh COPY quarantine_notify.py /usr/local/bin/quarantine_notify.py COPY quota_notify.py /usr/local/bin/quota_notify.py COPY repl_health.sh /usr/local/bin/repl_health.sh +COPY optimize-fts.sh /usr/local/bin/optimize-fts.sh ENTRYPOINT ["/docker-entrypoint.sh"] CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf diff --git a/data/Dockerfiles/dovecot/docker-entrypoint.sh b/data/Dockerfiles/dovecot/docker-entrypoint.sh index a9545f338b..1abb8dfc1d 100755 --- a/data/Dockerfiles/dovecot/docker-entrypoint.sh +++ b/data/Dockerfiles/dovecot/docker-entrypoint.sh @@ -109,14 +109,14 @@ EOF echo -n ${ACL_ANYONE} > /etc/dovecot/acl_anyone -if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then +if [[ "${SKIP_FLATCURVE}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify listescape replication' > /etc/dovecot/mail_plugins echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify listescape replication mail_log' > /etc/dovecot/mail_plugins_imap echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl notify listescape replication' > /etc/dovecot/mail_plugins_lmtp else -echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_solr listescape replication' > /etc/dovecot/mail_plugins -echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify mail_log fts fts_solr listescape replication' > /etc/dovecot/mail_plugins_imap -echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl fts fts_solr notify listescape replication' > /etc/dovecot/mail_plugins_lmtp +echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_flatcurve listescape replication' > /etc/dovecot/mail_plugins +echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify mail_log fts fts_flatcurve listescape replication' > /etc/dovecot/mail_plugins_imap +echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl fts fts_flatcurve notify listescape replication' > /etc/dovecot/mail_plugins_lmtp fi chmod 644 /etc/dovecot/mail_plugins /etc/dovecot/mail_plugins_imap /etc/dovecot/mail_plugins_lmtp /templates/quarantine.tpl @@ -343,6 +343,10 @@ mail_replica = tcp:${MAILCOW_REPLICA_IP}:${DOVEADM_REPLICA_PORT} EOF fi +if [[ "${SKIP_FLATCURVE}" =~ ^([nN][oO]|[nN])+$ ]]; then + sed -i "s/vsz_limit\s*=\s*[0-9]*\s*MB*/vsz_limit=${FTS_HEAP} MB/" /etc/dovecot/conf.d/fts-flatcurve.conf + sed -i "s/process_limit\s*=\s*[0-9]*/process_limit=${FTS_PROCS}/" /etc/dovecot/conf.d/fts-flatcurve.conf +fi # 401 is user dovecot if [[ ! -s /mail_crypt/ecprivkey.pem || ! -s /mail_crypt/ecpubkey.pem ]]; then @@ -387,7 +391,8 @@ chmod +x /usr/lib/dovecot/sieve/rspamd-pipe-ham \ /usr/local/bin/maildir_gc.sh \ /usr/local/sbin/stop-supervisor.sh \ /usr/local/bin/quota_notify.py \ - /usr/local/bin/repl_health.sh + /usr/local/bin/repl_health.sh \ + /usr/local/bin/optimize-fts.sh # Prepare environment file for cronjobs printenv | sed 's/^\(.*\)$/export \1/g' > /source_env.sh diff --git a/data/Dockerfiles/dovecot/optimize-fts.sh b/data/Dockerfiles/dovecot/optimize-fts.sh new file mode 100644 index 0000000000..d9de7da3e3 --- /dev/null +++ b/data/Dockerfiles/dovecot/optimize-fts.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +if [[ "${SKIP_FLATCURVE}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + exit 0 +else + doveadm fts optimize -A +fi diff --git a/data/conf/dovecot/conf.d/fts-flatcurve.conf b/data/conf/dovecot/conf.d/fts-flatcurve.conf new file mode 100644 index 0000000000..a9240f5519 --- /dev/null +++ b/data/conf/dovecot/conf.d/fts-flatcurve.conf @@ -0,0 +1,24 @@ +plugin { + fts_autoindex = yes + fts_autoindex_exclude = \Junk + fts_autoindex_exclude2 = \Trash + fts = flatcurve + + # These are not flatcurve settings, but required for Dovecot FTS. See + # Dovecot FTS Configuration link above for further information. + fts_languages = en es de + fts_tokenizer_generic = algorithm=simple + fts_tokenizers = generic email-address + + # OPTIONAL: Recommended default FTS core configuration + fts_filters = normalizer-icu snowball stopwords + fts_filters_en = lowercase snowball english-possessive stopwords + +} + +service indexer-worker { + executable = /bin/nice -n 10 /usr/libexec/dovecot/indexer-worker + process_limit=5 + + vsz_limit=256 MB +} \ No newline at end of file diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index 729686fb18..f71f85c00a 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -10,6 +10,7 @@ auth_mechanisms = plain login #mail_debug = yes #auth_debug = yes +log_debug = category=fts-flatcurve log_path = syslog disable_plaintext_auth = yes # Uncomment on NFS share @@ -194,9 +195,6 @@ plugin { acl_shared_dict = file:/var/vmail/shared-mailboxes.db acl = vfile acl_user = %u - fts = solr - fts_autoindex = yes - fts_solr = url=http://solr:8983/solr/dovecot-fts/ quota = dict:Userquota::proxy::sqlquota quota_rule2 = Trash:storage=+100%% sieve = /var/vmail/sieve/%u.sieve @@ -305,6 +303,7 @@ replication_dsync_parameters = -d -l 30 -U -n INBOX !include_try /etc/dovecot/extra.conf !include_try /etc/dovecot/sogo-sso.conf !include_try /etc/dovecot/shared_namespace.conf +!include_try /etc/dovecot/conf.d/fts-flatcurve.conf # default_client_limit = 10400 default_vsz_limit = 1024 M diff --git a/docker-compose.yml b/docker-compose.yml index 1a0588877f..f3e9c3f128 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -158,7 +158,7 @@ services: - API_KEY_READ_ONLY=${API_KEY_READ_ONLY:-invalid} - API_ALLOW_FROM=${API_ALLOW_FROM:-invalid} - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized} - - SKIP_SOLR=${SKIP_SOLR:-y} + - SKIP_FLATCURVE=${SKIP_FLATCURVE:-y} - SKIP_CLAMD=${SKIP_CLAMD:-n} - SKIP_SOGO=${SKIP_SOGO:-n} - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} @@ -221,7 +221,7 @@ services: - sogo dovecot-mailcow: - image: mailcow/dovecot:1.29 + image: mailcow/dovecot:dev depends_on: - mysql-mailcow - netfilter-mailcow @@ -258,7 +258,9 @@ services: - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} - MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-7200} - ACL_ANYONE=${ACL_ANYONE:-disallow} - - SKIP_SOLR=${SKIP_SOLR:-y} + - SKIP_FLATCURVE=${SKIP_FLATCURVE:-y} + - FTS_HEAP=${FTS_HEAP:-512} + - FTS_PROCS=${FTS_PROCS:-3} - MAILDIR_SUB=${MAILDIR_SUB:-} - MASTER=${MASTER:-y} - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} @@ -550,27 +552,6 @@ services: aliases: - dockerapi - - ##### Will be removed soon ##### - solr-mailcow: - image: mailcow/solr:1.8.2 - restart: always - depends_on: - - netfilter-mailcow - volumes: - - solr-vol-1:/opt/solr/server/solr/dovecot-fts/data - ports: - - "${SOLR_PORT:-127.0.0.1:18983}:8983" - environment: - - TZ=${TZ} - - SOLR_HEAP=${SOLR_HEAP:-1024} - - SKIP_SOLR=${SKIP_SOLR:-y} - networks: - mailcow-network: - aliases: - - solr - ################################ - olefy-mailcow: image: mailcow/olefy:1.13 restart: always @@ -626,7 +607,6 @@ services: - netfilter-mailcow - watchdog-mailcow - dockerapi-mailcow - - solr-mailcow environment: - TZ=${TZ} image: robbertkl/ipv6nat @@ -658,7 +638,6 @@ volumes: mysql-socket-vol-1: redis-vol-1: rspamd-vol-1: - solr-vol-1: postfix-vol-1: crypt-vol-1: sogo-web-vol-1: diff --git a/generate_config.sh b/generate_config.sh index f97ddd9a4e..2441a9e3ea 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -163,26 +163,6 @@ else SKIP_CLAMD=n 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 - ;; - *) - SKIP_SOLR=y - ;; - esac -else - SKIP_SOLR=n -fi - if [[ ${SKIP_BRANCH} != y ]]; then echo "Which branch of mailcow do you want to use?" echo "" @@ -382,14 +362,21 @@ SKIP_CLAMD=${SKIP_CLAMD} SKIP_SOGO=n -# Skip Solr on low-memory systems or if you do not want to store a readable index of your mails in solr-vol-1. +# Skip Flatcurve (FTS) on low-memory systems or if you simply want to disable it. + +SKIP_FLATCURVE=n + +# Dovecot Indexing (FTS) Process maximum heap size in MB, there is no recommendation, please see Dovecot docs. +# Flatcurve (Xapian backend) is used as the FTS Indexer. It is supposed to be efficient in CPU and RAM consumption. +# However: Please always monitor your Resource consumption! -SKIP_SOLR=${SKIP_SOLR} +FTS_HEAP=512 -# Solr heap size in MB, there is no recommendation, please see Solr docs. -# Solr is a prone to run OOM and should be monitored. Unmonitored Solr setups are not recommended. +# Controls how many processes the Dovecot indexing process can spawn at max. +# Too many indexing processes can use a lot of CPU and Disk I/O. +# Please visit: https://doc.dovecot.org/configuration_manual/service_configuration/#indexer-worker for more informations -SOLR_HEAP=1024 +FTS_PROCS=5 # Allow admins to log into SOGo as email user (without any password) diff --git a/update.sh b/update.sh index 0c8f85fedc..338ed4a4cb 100755 --- a/update.sh +++ b/update.sh @@ -275,6 +275,405 @@ detect_bad_asn() { fi } +adapt_new_options() { + + CONFIG_ARRAY=( + "SKIP_LETS_ENCRYPT" + "SKIP_SOGO" + "USE_WATCHDOG" + "WATCHDOG_NOTIFY_EMAIL" + "WATCHDOG_NOTIFY_WEBHOOK" + "WATCHDOG_NOTIFY_WEBHOOK_BODY" + "WATCHDOG_NOTIFY_BAN" + "WATCHDOG_NOTIFY_START" + "WATCHDOG_EXTERNAL_CHECKS" + "WATCHDOG_SUBJECT" + "SKIP_CLAMD" + "SKIP_IP_CHECK" + "ADDITIONAL_SAN" + "DOVEADM_PORT" + "IPV4_NETWORK" + "IPV6_NETWORK" + "LOG_LINES" + "SNAT_TO_SOURCE" + "SNAT6_TO_SOURCE" + "COMPOSE_PROJECT_NAME" + "DOCKER_COMPOSE_VERSION" + "SQL_PORT" + "API_KEY" + "API_KEY_READ_ONLY" + "API_ALLOW_FROM" + "MAILDIR_GC_TIME" + "MAILDIR_SUB" + "ACL_ANYONE" + "FTS_HEAP" + "FTS_PROCS" + "SKIP_FLATCURVE" + "ENABLE_SSL_SNI" + "ALLOW_ADMIN_EMAIL_LOGIN" + "SKIP_HTTP_VERIFICATION" + "SOGO_EXPIRE_SESSION" + "REDIS_PORT" + "DOVECOT_MASTER_USER" + "DOVECOT_MASTER_PASS" + "MAILCOW_PASS_SCHEME" + "ADDITIONAL_SERVER_NAMES" + "ACME_CONTACT" + "WATCHDOG_VERBOSE" + "WEBAUTHN_ONLY_TRUSTED_VENDORS" + "SPAMHAUS_DQS_KEY" + "SKIP_UNBOUND_HEALTHCHECK" + "DISABLE_NETFILTER_ISOLATION_RULE" + ) + + sed -i --follow-symlinks '$a\' mailcow.conf + for option in ${CONFIG_ARRAY[@]}; do + if [[ ${option} == "ADDITIONAL_SAN" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "${option}=" >> mailcow.conf + fi + elif [[ ${option} == "COMPOSE_PROJECT_NAME" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "COMPOSE_PROJECT_NAME=mailcowdockerized" >> mailcow.conf + fi + elif [[ ${option} == "DOCKER_COMPOSE_VERSION" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "# Used Docker Compose version" >> mailcow.conf + echo "# Switch here between native (compose plugin) and standalone" >> mailcow.conf + echo "# For more informations take a look at the mailcow docs regarding the configuration options." >> mailcow.conf + echo "# Normally this should be untouched but if you decided to use either of those you can switch it manually here." >> mailcow.conf + echo "# Please be aware that at least one of those variants should be installed on your maschine or mailcow will fail." >> mailcow.conf + echo "" >> mailcow.conf + echo "DOCKER_COMPOSE_VERSION=${DOCKER_COMPOSE_VERSION}" >> mailcow.conf + fi + elif [[ ${option} == "DOVEADM_PORT" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "DOVEADM_PORT=127.0.0.1:19991" >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_NOTIFY_EMAIL" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "WATCHDOG_NOTIFY_EMAIL=" >> mailcow.conf + fi + elif [[ ${option} == "LOG_LINES" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Max log lines per service to keep in Redis logs' >> mailcow.conf + echo "LOG_LINES=9999" >> mailcow.conf + fi + elif [[ ${option} == "IPV4_NETWORK" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Internal IPv4 /24 subnet, format n.n.n. (expands to n.n.n.0/24)' >> mailcow.conf + echo "IPV4_NETWORK=172.22.1" >> mailcow.conf + fi + elif [[ ${option} == "IPV6_NETWORK" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Internal IPv6 subnet in fc00::/7' >> mailcow.conf + echo "IPV6_NETWORK=fd4d:6169:6c63:6f77::/64" >> mailcow.conf + fi + elif [[ ${option} == "SQL_PORT" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Bind SQL to 127.0.0.1 on port 13306' >> mailcow.conf + echo "SQL_PORT=127.0.0.1:13306" >> mailcow.conf + fi + elif [[ ${option} == "API_KEY" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Create or override API key for web UI' >> mailcow.conf + echo "#API_KEY=" >> mailcow.conf + fi + elif [[ ${option} == "API_KEY_READ_ONLY" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Create or override read-only API key for web UI' >> mailcow.conf + echo "#API_KEY_READ_ONLY=" >> mailcow.conf + fi + elif [[ ${option} == "API_ALLOW_FROM" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Must be set for API_KEY to be active' >> mailcow.conf + echo '# IPs only, no networks (networks can be set via UI)' >> mailcow.conf + echo "#API_ALLOW_FROM=" >> mailcow.conf + fi + elif [[ ${option} == "SNAT_TO_SOURCE" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Use this IPv4 for outgoing connections (SNAT)' >> mailcow.conf + echo "#SNAT_TO_SOURCE=" >> mailcow.conf + fi + elif [[ ${option} == "SNAT6_TO_SOURCE" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Use this IPv6 for outgoing connections (SNAT)' >> mailcow.conf + echo "#SNAT6_TO_SOURCE=" >> mailcow.conf + fi + elif [[ ${option} == "MAILDIR_GC_TIME" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Garbage collector cleanup' >> mailcow.conf + echo '# Deleted domains and mailboxes are moved to /var/vmail/_garbage/timestamp_sanitizedstring' >> mailcow.conf + echo '# How long should objects remain in the garbage until they are being deleted? (value in minutes)' >> mailcow.conf + echo '# Check interval is hourly' >> mailcow.conf + echo 'MAILDIR_GC_TIME=1440' >> mailcow.conf + fi + elif [[ ${option} == "ACL_ANYONE" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Set this to "allow" to enable the anyone pseudo user. Disabled by default.' >> mailcow.conf + echo '# When enabled, ACL can be created, that apply to "All authenticated users"' >> mailcow.conf + echo '# This should probably only be activated on mail hosts, that are used exclusivly by one organisation.' >> mailcow.conf + echo '# Otherwise a user might share data with too many other users.' >> mailcow.conf + echo 'ACL_ANYONE=disallow' >> mailcow.conf + fi + elif [[ ${option} == "FTS_HEAP" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Dovecot Indexing (FTS) Process maximum heap size in MB, there is no recommendation, please see Dovecot docs.' >> mailcow.conf + echo '# Flatcurve is used as FTS Engine. It is supposed to be pretty efficient in CPU and RAM consumption.' >> mailcow.conf + echo '# Please always monitor your Resource consumption!' >> mailcow.conf + echo "FTS_HEAP=1024" >> mailcow.conf + fi + elif [[ ${option} == "SKIP_FLATCURVE" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Skip Flatcurve (FTS) on low-memory systems or if you simply want to disable it.' >> mailcow.conf + echo "SKIP_FLATCURVE=y" >> mailcow.conf + fi + elif [[ ${option} == "FTS_PROCS" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Controls how many processes the Dovecot indexing process can spawn at max.' >> mailcow.conf + echo '# Too many indexing processes can use a lot of CPU and Disk I/O' >> mailcow.conf + echo '# Please visit: https://doc.dovecot.org/configuration_manual/service_configuration/#indexer-worker for more informations' >> mailcow.conf + echo "FTS_PROCS=5" >> mailcow.conf + fi + elif [[ ${option} == "ENABLE_SSL_SNI" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Create seperate certificates for all domains - y/n' >> mailcow.conf + echo '# this will allow adding more than 100 domains, but some email clients will not be able to connect with alternative hostnames' >> mailcow.conf + echo '# see https://wiki.dovecot.org/SSL/SNIClientSupport' >> mailcow.conf + echo "ENABLE_SSL_SNI=n" >> mailcow.conf + fi + elif [[ ${option} == "SKIP_SOGO" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Skip SOGo: Will disable SOGo integration and therefore webmail, DAV protocols and ActiveSync support (experimental, unsupported, not fully implemented) - y/n' >> mailcow.conf + echo "SKIP_SOGO=n" >> mailcow.conf + fi + elif [[ ${option} == "MAILDIR_SUB" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# MAILDIR_SUB defines a path in a users virtual home to keep the maildir in. Leave empty for updated setups.' >> mailcow.conf + echo "#MAILDIR_SUB=Maildir" >> mailcow.conf + echo "MAILDIR_SUB=" >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_NOTIFY_WEBHOOK" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Send notifications to a webhook URL that receives a POST request with the content type "application/json".' >> mailcow.conf + echo '# You can use this to send notifications to services like Discord, Slack and others.' >> mailcow.conf + echo '#WATCHDOG_NOTIFY_WEBHOOK=https://discord.com/api/webhooks/XXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_NOTIFY_WEBHOOK_BODY" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# JSON body included in the webhook POST request. Needs to be in single quotes.' >> mailcow.conf + echo '# Following variables are available: SUBJECT, BODY' >> mailcow.conf + WEBHOOK_BODY='{"username": "mailcow Watchdog", "content": "**${SUBJECT}**\n${BODY}"}' + echo "#WATCHDOG_NOTIFY_WEBHOOK_BODY='${WEBHOOK_BODY}'" >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_NOTIFY_BAN" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Notify about banned IP. Includes whois lookup.' >> mailcow.conf + echo "WATCHDOG_NOTIFY_BAN=y" >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_NOTIFY_START" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Send a notification when the watchdog is started.' >> mailcow.conf + echo "WATCHDOG_NOTIFY_START=y" >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_SUBJECT" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Subject for watchdog mails. Defaults to "Watchdog ALERT" followed by the error message.' >> mailcow.conf + echo "#WATCHDOG_SUBJECT=" >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_EXTERNAL_CHECKS" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Checks if mailcow is an open relay. Requires a SAL. More checks will follow.' >> mailcow.conf + echo '# No data is collected. Opt-in and anonymous.' >> mailcow.conf + echo '# Will only work with unmodified mailcow setups.' >> mailcow.conf + echo "WATCHDOG_EXTERNAL_CHECKS=n" >> mailcow.conf + fi + elif [[ ${option} == "SOGO_EXPIRE_SESSION" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# SOGo session timeout in minutes' >> mailcow.conf + echo "SOGO_EXPIRE_SESSION=480" >> mailcow.conf + fi + elif [[ ${option} == "REDIS_PORT" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "REDIS_PORT=127.0.0.1:7654" >> mailcow.conf + fi + elif [[ ${option} == "DOVECOT_MASTER_USER" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# DOVECOT_MASTER_USER and _PASS must _both_ be provided. No special chars.' >> mailcow.conf + echo '# Empty by default to auto-generate master user and password on start.' >> mailcow.conf + echo '# User expands to DOVECOT_MASTER_USER@mailcow.local' >> mailcow.conf + echo '# LEAVE EMPTY IF UNSURE' >> mailcow.conf + echo "DOVECOT_MASTER_USER=" >> mailcow.conf + fi + elif [[ ${option} == "DOVECOT_MASTER_PASS" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# LEAVE EMPTY IF UNSURE' >> mailcow.conf + echo "DOVECOT_MASTER_PASS=" >> mailcow.conf + fi + elif [[ ${option} == "MAILCOW_PASS_SCHEME" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Password hash algorithm' >> mailcow.conf + echo '# Only certain password hash algorithm are supported. For a fully list of supported schemes,' >> mailcow.conf + echo '# see https://docs.mailcow.email/models/model-passwd/' >> mailcow.conf + echo "MAILCOW_PASS_SCHEME=BLF-CRYPT" >> mailcow.conf + fi + elif [[ ${option} == "ADDITIONAL_SERVER_NAMES" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Additional server names for mailcow UI' >> mailcow.conf + echo '#' >> mailcow.conf + echo '# Specify alternative addresses for the mailcow UI to respond to' >> mailcow.conf + echo '# This is useful when you set mail.* as ADDITIONAL_SAN and want to make sure mail.maildomain.com will always point to the mailcow UI.' >> mailcow.conf + echo '# If the server name does not match a known site, Nginx decides by best-guess and may redirect users to the wrong web root.' >> mailcow.conf + echo '# You can understand this as server_name directive in Nginx.' >> mailcow.conf + echo '# Comma separated list without spaces! Example: ADDITIONAL_SERVER_NAMES=a.b.c,d.e.f' >> mailcow.conf + echo 'ADDITIONAL_SERVER_NAMES=' >> mailcow.conf + fi + elif [[ ${option} == "ACME_CONTACT" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Lets Encrypt registration contact information' >> mailcow.conf + echo '# Optional: Leave empty for none' >> mailcow.conf + echo '# This value is only used on first order!' >> mailcow.conf + echo '# Setting it at a later point will require the following steps:' >> mailcow.conf + echo '# https://docs.mailcow.email/troubleshooting/debug-reset_tls/' >> mailcow.conf + echo 'ACME_CONTACT=' >> mailcow.conf + fi + elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "# WebAuthn device manufacturer verification" >> mailcow.conf + echo '# After setting WEBAUTHN_ONLY_TRUSTED_VENDORS=y only devices from trusted manufacturers are allowed' >> mailcow.conf + echo '# root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates' >> mailcow.conf + echo 'WEBAUTHN_ONLY_TRUSTED_VENDORS=n' >> mailcow.conf + fi + elif [[ ${option} == "SPAMHAUS_DQS_KEY" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "# Spamhaus Data Query Service Key" >> mailcow.conf + echo '# Optional: Leave empty for none' >> mailcow.conf + echo '# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist.' >> mailcow.conf + echo '# If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS.' >> mailcow.conf + echo '# Otherwise it will work as usual.' >> mailcow.conf + echo 'SPAMHAUS_DQS_KEY=' >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_VERBOSE" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Enable watchdog verbose logging' >> mailcow.conf + echo 'WATCHDOG_VERBOSE=n' >> mailcow.conf + fi + elif [[ ${option} == "SKIP_UNBOUND_HEALTHCHECK" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!) - y/n' >> mailcow.conf + echo 'SKIP_UNBOUND_HEALTHCHECK=n' >> mailcow.conf + fi + elif [[ ${option} == "DISABLE_NETFILTER_ISOLATION_RULE" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Prevent netfilter from setting an iptables/nftables rule to isolate the mailcow docker network - y/n' >> mailcow.conf + echo '# CAUTION: Disabling this may expose container ports to other neighbors on the same subnet, even if the ports are bound to localhost' >> mailcow.conf + echo 'DISABLE_NETFILTER_ISOLATION_RULE=n' >> mailcow.conf + fi + elif ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo "${option}=n" >> mailcow.conf + fi + done +} + +migrate_solr_config_options() { + + SOLR_OPTIONS=( + "SOLR_HEAP" + "SOLR_PORT" + "SKIP_SOLR" + ) + + sed -i --follow-symlinks '$a\' mailcow.conf + for option in "${SOLR_OPTIONS[@]}"; do + if [[ $option == "SOLR_HEAP" ]]; then + if grep -q "${option}" mailcow.conf; then + echo "Replacing SOLR_HEAP with \"${option}\" in mailcow.conf" + sed -i '/# Solr heap size in MB\b/c\# Dovecot Indexing (FTS) Process heap size in MB, there is no recommendation, please see Dovecot docs.' mailcow.conf + sed -i '/# Solr is a prone to run\b/c\# Flatcurve is replacing solr as FTS Indexer completely. It is supposed to be much more efficient in CPU and RAM consumption.' mailcow.conf + sed -i 's/SOLR_HEAP/FTS_HEAP/g' mailcow.conf + fi + fi + if [[ $option == "SKIP_SOLR" ]]; then + if grep -q "${option}" mailcow.conf; then + echo "Replacing $option in mailcow.conf with SKIP_FLATCURVE" + sed -i '/\bSkip Solr on low-memory\b/c\# Skip Flatcurve (FTS) on low-memory systems or if you simply want to disable it.' mailcow.conf + sed -i '/\bSolr is disabled by default\b/d' mailcow.conf + sed -i '/\bDisable Solr or\b/d' mailcow.conf + sed -i 's/SKIP_SOLR/SKIP_FLATCURVE/g' mailcow.conf + fi + fi + if [[ $option == "SOLR_PORT" ]]; then + if grep -q "${option}" mailcow.conf; then + echo "Removing ${option} in mailcow.conf" + sed -i '/\bSOLR_PORT\b/d' mailcow.conf + fi + fi + done + + solr_volume=$(docker volume ls -qf name=^${COMPOSE_PROJECT_NAME}_solr-vol-1) + if [[ -n $solr_volume ]]; then + echo -e "\e[34mSolr has been replaced within mailcow since 2024-XX.\e[0m" + sleep 1 + echo -e "\e[34mTherefore the volume $solr_volume is unused.\e[0m" + sleep 1 + read -r -p "Would you like to remove the $solr_volume? " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + echo -e "\e[33mRemoving $solr_volume...\e[0m" + docker volume rm $solr_volume + if [[ $? != 0 ]]; then + echo -e "\e[31mCould not remove the volume... Please remove it manually!\e[0m" + else + echo -e "\e[32mSucessfully removed $solr_volume!\e[0m" + fi + else + echo "Ok! Not removing $solr_volume then." + echo "Once you decided on removing the volume simply run docker volume rm $solr_volume to remove it manually." + echo "This can be done anytime. mailcow does not use this volume anymore." + fi + fi +} + ############## End Function Section ############## # Check permissions @@ -932,7 +1331,8 @@ for container in "${MAILCOW_CONTAINERS[@]}"; do done [[ -f data/conf/nginx/ZZZ-ejabberd.conf ]] && rm data/conf/nginx/ZZZ-ejabberd.conf - +migrate_solr_config_options +adapt_new_options # Silently fixing remote url from andryyy to mailcow # git remote set-url origin https://github.com/mailcow/mailcow-dockerized