1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2024-12-21 01:49:22 +02:00

dovecot: replace solr fts with flatcurve (xapian) (#5680)

* fts-flatcurve: inital implementation

* fts: removed solr from compose.yml

* flatcurve: added heap and proc logic to dovecot

* added logic for update.sh & generate for Flatcurve

* delete old iteration of fts-flatcurve.conf

* updated default fts.conf

* updated .gitignore to exclude fts.conf for further git updates

* Remove autogeneration of fts.conf (disable override)

* cleanup all left solr stuff

* renamed SKIP_FLATCURVE to SKIP_FTS

* cleanup leftovers solr in lang files

* moved lazy_expunge plugin only to mail_plugins

* added fts timeout value

* compose: remove dev image of dovecot

* updated japanese translation
This commit is contained in:
Niklas Meyer 2024-12-12 16:44:42 +01:00 committed by GitHub
parent b087ac9e27
commit 3e8bb06a37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 467 additions and 862 deletions

View File

@ -23,7 +23,6 @@ jobs:
- "postfix-mailcow"
- "rspamd-mailcow"
- "sogo-mailcow"
- "solr-mailcow"
- "unbound-mailcow"
- "watchdog-mailcow"
runs-on: ubuntu-latest

1
.gitignore vendored
View File

@ -23,6 +23,7 @@ data/conf/dovecot/sni.conf
data/conf/dovecot/sogo-sso.conf
data/conf/dovecot/sogo_trusted_ip.conf
data/conf/dovecot/sql
data/conf/dovecot/conf.d/fts.conf
data/conf/nextcloud-*.bak
data/conf/nginx/*.active
data/conf/nginx/*.bak

View File

@ -105,7 +105,6 @@ 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" \

View File

@ -110,21 +110,16 @@ EOF
echo -n ${ACL_ANYONE} > /etc/dovecot/acl_anyone
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY]) ]]; then
echo -e "\e[33mActivating Flatcurve as FTS Backend...\e[0m"
echo -e "\e[33mDepending on your previous setup a full reindex might be needed... \e[0m"
echo -e "\e[34mVisit https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-fts/#fts-related-dovecot-commands to learn how to reindex\e[0m"
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_flatcurve listescape replication lazy_expunge' > /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
elif [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
if [[ "${SKIP_FTS}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo -e "\e[33mDetecting SKIP_FTS=y... not enabling Flatcurve (FTS) then...\e[0m"
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify listescape replication lazy_expunge' > /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 lazy_expunge' > /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 -e "\e[32mDetecting SKIP_FTS=n... enabling Flatcurve (FTS)\e[0m"
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_flatcurve listescape replication lazy_expunge' > /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
@ -247,51 +242,6 @@ function script_deinit()
end
EOF
# Temporarily set FTS depending on user choice inside mailcow.conf. Will be removed as soon as Solr is dropped
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])$ ]]; then
cat <<EOF > /etc/dovecot/conf.d/fts.conf
# Autogenerated by mailcow
plugin {
fts_autoindex = yes
fts_autoindex_exclude = \Junk
fts_autoindex_exclude2 = \Trash
fts = flatcurve
# Maximum term length can be set via the 'maxlen' argument (maxlen is
# specified in bytes, not number of UTF-8 characters)
fts_tokenizer_email_address = maxlen=100
fts_tokenizer_generic = algorithm=simple maxlen=30
# 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_tokenizers = generic email-address
# OPTIONAL: Recommended default FTS core configuration
fts_filters = normalizer-icu snowball stopwords
fts_filters_en = lowercase snowball english-possessive stopwords
}
EOF
elif [[ ! "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])$ ]]; then
cat <<EOF > /etc/dovecot/conf.d/fts.conf
# Autogenerated by mailcow
plugin {
fts = solr
fts_autoindex = yes
fts_autoindex_exclude = \Junk
fts_autoindex_exclude2 = \Trash
fts_solr = url=http://solr:8983/solr/dovecot-fts/
fts_tokenizers = generic email-address
fts_tokenizer_generic = algorithm=simple
fts_filters = normalizer-icu snowball stopwords
fts_filters_en = lowercase snowball english-possessive stopwords
}
EOF
fi
# Replace patterns in app-passdb.lua
sed -i "s/__DBUSER__/${DBUSER}/g" /etc/dovecot/lua/passwd-verify.lua
sed -i "s/__DBPASS__/${DBPASS}/g" /etc/dovecot/lua/passwd-verify.lua
@ -398,6 +348,15 @@ mail_replica = tcp:${MAILCOW_REPLICA_IP}:${DOVEADM_REPLICA_PORT}
EOF
fi
# Setting variables for indexer-worker inside fts.conf automatically according to mailcow.conf settings
if [[ "${SKIP_FTS}" =~ ^([nN][oO]|[nN])+$ ]]; then
echo -e "\e[94mConfiguring FTS Settings...\e[0m"
echo -e "\e[94mSetting FTS Memory Limit (per process) to ${FTS_HEAP} MB\e[0m"
sed -i "s/vsz_limit\s*=\s*[0-9]*\s*MB*/vsz_limit=${FTS_HEAP} MB/" /etc/dovecot/conf.d/fts.conf
echo -e "\e[94mSetting FTS Process Limit to ${FTS_PROCS}\e[0m"
sed -i "s/process_limit\s*=\s*[0-9]*/process_limit=${FTS_PROCS}/" /etc/dovecot/conf.d/fts.conf
fi
# 401 is user dovecot
if [[ ! -s /mail_crypt/ecprivkey.pem || ! -s /mail_crypt/ecpubkey.pem ]]; then
openssl ecparam -name prime256v1 -genkey | openssl pkey -out /mail_crypt/ecprivkey.pem

View File

@ -1,7 +1,7 @@
#!/bin/bash
if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ && ! "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
if [[ "${SKIP_FTS}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
exit 0
else
doveadm fts optimize -A
fi
fi

View File

@ -1,31 +0,0 @@
FROM solr:7.7-slim
USER root
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=(?<version>.*)$
ARG GOSU_VERSION=1.17
COPY solr.sh /
COPY solr-config-7.7.0.xml /
COPY solr-schema-7.7.0.xml /
RUN 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-get update && apt-get install -y --no-install-recommends \
tzdata \
curl \
bash \
zip \
&& apt-get autoclean \
&& rm -rf /var/lib/apt/lists/* \
&& chmod +x /solr.sh \
&& sync \
&& bash /solr.sh --bootstrap
RUN zip -q -d /opt/solr/server/lib/ext/log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
RUN apt remove zip -y
CMD ["/solr.sh"]

View File

@ -1,289 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- This is the default config with stuff non-essential to Dovecot removed. -->
<config>
<!-- Controls what version of Lucene various components of Solr
adhere to. Generally, you want to use the latest version to
get all bug fixes and improvements. It is highly recommended
that you fully re-index after changing this setting as it can
affect both how text is indexed and queried.
-->
<luceneMatchVersion>7.7.0</luceneMatchVersion>
<!-- A 'dir' option by itself adds any files found in the directory
to the classpath, this is useful for including all jars in a
directory.
When a 'regex' is specified in addition to a 'dir', only the
files in that directory which completely match the regex
(anchored on both ends) will be included.
If a 'dir' option (with or without a regex) is used and nothing
is found that matches, a warning will be logged.
The examples below can be used to load some solr-contribs along
with their external dependencies.
-->
<lib dir="${solr.install.dir:../../../..}/contrib/extraction/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-cell-\d.*\.jar" />
<lib dir="${solr.install.dir:../../../..}/contrib/clustering/lib/" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-clustering-\d.*\.jar" />
<lib dir="${solr.install.dir:../../../..}/contrib/langid/lib/" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-langid-\d.*\.jar" />
<lib dir="${solr.install.dir:../../../..}/contrib/velocity/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-velocity-\d.*\.jar" />
<!-- Data Directory
Used to specify an alternate directory to hold all index data
other than the default ./data under the Solr home. If
replication is in use, this should match the replication
configuration.
-->
<dataDir>${solr.data.dir:}</dataDir>
<!-- The default high-performance update handler -->
<updateHandler class="solr.DirectUpdateHandler2">
<!-- Enables a transaction log, used for real-time get, durability, and
and solr cloud replica recovery. The log can grow as big as
uncommitted changes to the index, so use of a hard autoCommit
is recommended (see below).
"dir" - the target directory for transaction logs, defaults to the
solr data directory.
"numVersionBuckets" - sets the number of buckets used to keep
track of max version values when checking for re-ordered
updates; increase this value to reduce the cost of
synchronizing access to version buckets during high-volume
indexing, this requires 8 bytes (long) * numVersionBuckets
of heap space per Solr core.
-->
<updateLog>
<str name="dir">${solr.ulog.dir:}</str>
<int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>
</updateLog>
<!-- AutoCommit
Perform a hard commit automatically under certain conditions.
Instead of enabling autoCommit, consider using "commitWithin"
when adding documents.
http://wiki.apache.org/solr/UpdateXmlMessages
maxDocs - Maximum number of documents to add since the last
commit before automatically triggering a new commit.
maxTime - Maximum amount of time in ms that is allowed to pass
since a document was added before automatically
triggering a new commit.
openSearcher - if false, the commit causes recent index changes
to be flushed to stable storage, but does not cause a new
searcher to be opened to make those changes visible.
If the updateLog is enabled, then it's highly recommended to
have some sort of hard autoCommit to limit the log size.
-->
<autoCommit>
<maxTime>${solr.autoCommit.maxTime:15000}</maxTime>
<openSearcher>false</openSearcher>
</autoCommit>
<!-- softAutoCommit is like autoCommit except it causes a
'soft' commit which only ensures that changes are visible
but does not ensure that data is synced to disk. This is
faster and more near-realtime friendly than a hard commit.
-->
<autoSoftCommit>
<maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
</autoSoftCommit>
<!-- Update Related Event Listeners
Various IndexWriter related events can trigger Listeners to
take actions.
postCommit - fired after every commit or optimize command
postOptimize - fired after every optimize command
-->
</updateHandler>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Query section - these settings control query time things like caches
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<query>
<!-- Solr Internal Query Caches
There are two implementations of cache available for Solr,
LRUCache, based on a synchronized LinkedHashMap, and
FastLRUCache, based on a ConcurrentHashMap.
FastLRUCache has faster gets and slower puts in single
threaded operation and thus is generally faster than LRUCache
when the hit ratio of the cache is high (> 75%), and may be
faster under other scenarios on multi-cpu systems.
-->
<!-- Filter Cache
Cache used by SolrIndexSearcher for filters (DocSets),
unordered sets of *all* documents that match a query. When a
new searcher is opened, its caches may be prepopulated or
"autowarmed" using data from caches in the old searcher.
autowarmCount is the number of items to prepopulate. For
LRUCache, the autowarmed items will be the most recently
accessed items.
Parameters:
class - the SolrCache implementation LRUCache or
(LRUCache or FastLRUCache)
size - the maximum number of entries in the cache
initialSize - the initial capacity (number of entries) of
the cache. (see java.util.HashMap)
autowarmCount - the number of entries to prepopulate from
and old cache.
maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed
to occupy. Note that when this option is specified, the size
and initialSize parameters are ignored.
-->
<filterCache class="solr.FastLRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
<!-- Query Result Cache
Caches results of searches - ordered lists of document ids
(DocList) based on a query, a sort, and the range of documents requested.
Additional supported parameter by LRUCache:
maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed
to occupy
-->
<queryResultCache class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
<!-- Document Cache
Caches Lucene Document objects (the stored fields for each
document). Since Lucene internal document ids are transient,
this cache will not be autowarmed.
-->
<documentCache class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
<!-- custom cache currently used by block join -->
<cache name="perSegFilter"
class="solr.search.LRUCache"
size="10"
initialSize="0"
autowarmCount="10"
regenerator="solr.NoOpRegenerator" />
<!-- Lazy Field Loading
If true, stored fields that are not requested will be loaded
lazily. This can result in a significant speed improvement
if the usual case is to not load all stored fields,
especially if the skipped fields are large compressed text
fields.
-->
<enableLazyFieldLoading>true</enableLazyFieldLoading>
<!-- Result Window Size
An optimization for use with the queryResultCache. When a search
is requested, a superset of the requested number of document ids
are collected. For example, if a search for a particular query
requests matching documents 10 through 19, and queryWindowSize is 50,
then documents 0 through 49 will be collected and cached. Any further
requests in that range can be satisfied via the cache.
-->
<queryResultWindowSize>20</queryResultWindowSize>
<!-- Maximum number of documents to cache for any entry in the
queryResultCache.
-->
<queryResultMaxDocsCached>200</queryResultMaxDocsCached>
<!-- Use Cold Searcher
If a search request comes in and there is no current
registered searcher, then immediately register the still
warming searcher and use it. If "false" then all requests
will block until the first searcher is done warming.
-->
<useColdSearcher>false</useColdSearcher>
</query>
<!-- Request Dispatcher
This section contains instructions for how the SolrDispatchFilter
should behave when processing requests for this SolrCore.
-->
<requestDispatcher>
<httpCaching never304="true" />
</requestDispatcher>
<!-- Request Handlers
http://wiki.apache.org/solr/SolrRequestHandler
Incoming queries will be dispatched to a specific handler by name
based on the path specified in the request.
If a Request Handler is declared with startup="lazy", then it will
not be initialized until the first request that uses it.
-->
<!-- SearchHandler
http://wiki.apache.org/solr/SearchHandler
For processing Search Queries, the primary Request Handler
provided with Solr is "SearchHandler" It delegates to a sequent
of SearchComponents (see below) and supports distributed
queries across multiple shards
-->
<requestHandler name="/select" class="solr.SearchHandler">
<!-- default values for query parameters can be specified, these
will be overridden by parameters in the request
-->
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
</lst>
</requestHandler>
<initParams path="/update/**,/select">
<lst name="defaults">
<str name="df">_text_</str>
</lst>
</initParams>
<!-- Response Writers
http://wiki.apache.org/solr/QueryResponseWriter
Request responses will be written using the writer specified by
the 'wt' request parameter matching the name of a registered
writer.
The "default" writer is the default and will be used if 'wt' is
not specified in the request.
-->
<queryResponseWriter name="xml"
default="true"
class="solr.XMLResponseWriter" />
</config>

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema name="dovecot-fts" version="2.0">
<fieldType name="string" class="solr.StrField" omitNorms="true" sortMissingLast="true"/>
<fieldType name="long" class="solr.LongPointField" positionIncrementGap="0"/>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
<fieldType name="text" class="solr.TextField" autoGeneratePhraseQueries="true" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="3" maxGramSize="20"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.WordDelimiterGraphFilterFactory" catenateNumbers="1" generateNumberParts="1" splitOnCaseChange="1" generateWordParts="1" splitOnNumerics="1" catenateAll="1" catenateWords="1"/>
<filter class="solr.FlattenGraphFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymGraphFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/>
<filter class="solr.FlattenGraphFilterFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.WordDelimiterGraphFilterFactory" catenateNumbers="1" generateNumberParts="1" splitOnCaseChange="1" generateWordParts="1" splitOnNumerics="1" catenateAll="1" catenateWords="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
<field name="id" type="string" indexed="true" required="true" stored="true"/>
<field name="uid" type="long" indexed="true" required="true" stored="true"/>
<field name="box" type="string" indexed="true" required="true" stored="true"/>
<field name="user" type="string" indexed="true" required="true" stored="true"/>
<field name="hdr" type="text" indexed="true" stored="false"/>
<field name="body" type="text" indexed="true" stored="false"/>
<field name="from" type="text" indexed="true" stored="false"/>
<field name="to" type="text" indexed="true" stored="false"/>
<field name="cc" type="text" indexed="true" stored="false"/>
<field name="bcc" type="text" indexed="true" stored="false"/>
<field name="subject" type="text" indexed="true" stored="false"/>
<!-- Used by Solr internally: -->
<field name="_version_" type="long" indexed="true" stored="true"/>
<uniqueKey>id</uniqueKey>
</schema>

View File

@ -1,75 +0,0 @@
#!/bin/bash
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "FLATCURVE_EXPERIMENTAL=y, skipping Solr but enabling Flatcurve as FTS for Dovecot!"
echo "Solr will be removed in the future!"
sleep 365d
exit 0
elif [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "SKIP_SOLR=y, skipping Solr..."
echo "HINT: You could try the newer FTS Backend Flatcurve, which is currently in experimental state..."
echo "Simply set FLATCURVE_EXPERIMENTAL=y inside your mailcow.conf and restart the stack afterwards!"
echo "Solr will be removed in the future!"
sleep 365d
exit 0
fi
MEM_TOTAL=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
if [[ "${1}" != "--bootstrap" ]]; then
if [ ${MEM_TOTAL} -lt "2097152" ]; then
echo "System memory less than 2 GB, skipping Solr..."
sleep 365d
exit 0
fi
fi
set -e
# run the optional initdb
. /opt/docker-solr/scripts/run-initdb
# fixing volume permission
[[ -d /opt/solr/server/solr/dovecot-fts/data ]] && chown -R solr:solr /opt/solr/server/solr/dovecot-fts/data
if [[ "${1}" != "--bootstrap" ]]; then
sed -i '/SOLR_HEAP=/c\SOLR_HEAP="'${SOLR_HEAP:-1024}'m"' /opt/solr/bin/solr.in.sh
else
sed -i '/SOLR_HEAP=/c\SOLR_HEAP="256m"' /opt/solr/bin/solr.in.sh
fi
if [[ "${1}" == "--bootstrap" ]]; then
echo "Creating initial configuration"
echo "Modifying default config set"
cp /solr-config-7.7.0.xml /opt/solr/server/solr/configsets/_default/conf/solrconfig.xml
cp /solr-schema-7.7.0.xml /opt/solr/server/solr/configsets/_default/conf/schema.xml
rm /opt/solr/server/solr/configsets/_default/conf/managed-schema
echo "Starting local Solr instance to setup configuration"
gosu solr start-local-solr
echo "Creating core \"dovecot-fts\""
gosu solr /opt/solr/bin/solr create -c "dovecot-fts"
# See https://github.com/docker-solr/docker-solr/issues/27
echo "Checking core"
while ! wget -O - 'http://localhost:8983/solr/admin/cores?action=STATUS' | grep -q instanceDir; do
echo "Could not find any cores, waiting..."
sleep 3
done
echo "Created core \"dovecot-fts\""
echo "Stopping local Solr"
gosu solr stop-local-solr
exit 0
fi
echo "Starting up Solr..."
echo -e "\e[31mSolr is deprecated! You can try the new FTS System now by enabling FLATCURVE_EXPERIMENTAL=y inside mailcow.conf and restarting the stack\e[0m"
echo -e "\e[31mSolr will be removed completely soon!\e[0m"
sleep 15
exec gosu solr solr-foreground

View File

@ -0,0 +1,35 @@
# mailcow FTS Flatcurve Settings, change them as you like.
plugin {
fts_autoindex = yes
fts_autoindex_exclude = \Junk
fts_autoindex_exclude2 = \Trash
fts = flatcurve
# Maximum term length can be set via the 'maxlen' argument (maxlen is
# specified in bytes, not number of UTF-8 characters)
fts_tokenizer_email_address = maxlen=100
fts_tokenizer_generic = algorithm=simple maxlen=30
# 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_tokenizers = generic email-address
# OPTIONAL: Recommended default FTS core configuration
fts_filters = normalizer-icu snowball stopwords
fts_filters_en = lowercase snowball english-possessive stopwords
fts_index_timeout = 300
}
### THIS PART WILL BE CHANGED BY MODIFYING mailcow.conf AUTOMATICALLY DURING RUNTIME! ###
service indexer-worker {
# Max amount of simultaniously running indexer jobs.
process_limit=5
# Max amount of RAM used by EACH indexer process.
vsz_limit=128 MB
}
### THIS PART WILL BE CHANGED BY MODIFYING mailcow.conf AUTOMATICALLY DURING RUNTIME! ###

View File

@ -5415,12 +5415,6 @@ paths:
started_at: "2019-12-22T20:59:58.382274592Z"
state: running
type: info
solr-mailcow:
container: solr-mailcow
image: "mailcow/solr:1.7"
started_at: "2019-12-22T20:59:59.635413798Z"
state: running
type: info
unbound-mailcow:
container: unbound-mailcow
image: "mailcow/unbound:1.10"
@ -5442,30 +5436,6 @@ paths:
hey where started and a few other details.
operationId: Get container status
summary: Get container status
/api/v1/get/status/solr:
get:
responses:
"401":
$ref: "#/components/responses/Unauthorized"
"200":
content:
application/json:
examples:
response:
value:
solr_documents: null
solr_enabled: false
solr_size: null
type: info
description: OK
headers: {}
tags:
- Status
description: >-
Using this endpoint you can get the status of all containers and when
hey where started and a few other details.
operationId: Get solr status
summary: Get solr status
/api/v1/get/status/vmail:
get:
responses:

View File

@ -8,7 +8,6 @@ if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "adm
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
$solr_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_SOLR"])) ? false : solr_status();
$clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ? false : true;
@ -25,7 +24,6 @@ $vmail_df = explode(',', (string)json_decode(docker('post', 'dovecot-mailcow', '
// containers
$containers_info = (array) docker('info');
if ($clamd_status === false) unset($containers_info['clamd-mailcow']);
if ($solr_status === false) unset($containers_info['solr-mailcow']);
ksort($containers_info);
$containers = array();
foreach ($containers_info as $container => $container_info) {
@ -69,8 +67,6 @@ $template_data = [
'timezone' => $timezone,
'gal' => @$_SESSION['gal'],
'license_guid' => license('guid'),
'solr_status' => $solr_status,
'solr_uptime' => round($solr_status['status']['dovecot-fts']['uptime'] / 1000 / 60 / 60),
'clamd_status' => $clamd_status,
'containers' => $containers,
'ip_check' => customize('get', 'ip_check'),

View File

@ -2908,50 +2908,6 @@ function getGUID() {
.substr($charid,16, 4).$hyphen
.substr($charid,20,12);
}
function solr_status() {
$curl = curl_init();
$endpoint = 'http://solr:8983/solr/admin/cores';
$params = array(
'action' => 'STATUS',
'core' => 'dovecot-fts',
'indexInfo' => 'true'
);
$url = $endpoint . '?' . http_build_query($params);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
$response_core = curl_exec($curl);
if ($response_core === false) {
$err = curl_error($curl);
curl_close($curl);
return false;
}
else {
curl_close($curl);
$curl = curl_init();
$status_core = json_decode($response_core, true);
$url = 'http://solr:8983/solr/admin/info/system';
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
$response_sysinfo = curl_exec($curl);
if ($response_sysinfo === false) {
$err = curl_error($curl);
curl_close($curl);
return false;
}
else {
curl_close($curl);
$status_sysinfo = json_decode($response_sysinfo, true);
$status = array_merge($status_core, $status_sysinfo);
return (!empty($status['status']['dovecot-fts']) && !empty($status['jvm']['memory'])) ? $status : false;
}
return (!empty($status['status']['dovecot-fts'])) ? $status['status']['dovecot-fts'] : false;
}
return false;
}
function cleanupJS($ignore = '', $folder = '/tmp/*.js') {
$now = time();

View File

@ -5434,25 +5434,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'msg' => 'Could not move maildir to garbage collector: variables local_part and/or domain empty'
);
}
if (strtolower(getenv('SKIP_SOLR')) == 'n' && strtolower(getenv('FLATCURVE_EXPERIMENTAL')) != 'y') {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://solr:8983/solr/dovecot-fts/update?commit=true');
curl_setopt($curl, CURLOPT_HTTPHEADER,array('Content-Type: text/xml'));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, '<delete><query>user:' . $username . '</query></delete>');
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
$response = curl_exec($curl);
if ($response === false) {
$err = curl_error($curl);
$_SESSION['return'][] = array(
'type' => 'warning',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'Could not remove Solr index: ' . print_r($err, true)
);
}
curl_close($curl);
}
$stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username");
$stmt->execute(array(
':username' => $username

View File

@ -1628,23 +1628,6 @@ if (isset($_GET['query'])) {
);
echo json_encode($temp, JSON_UNESCAPED_SLASHES);
break;
case "solr":
$solr_status = solr_status();
$solr_size = ($solr_status['status']['dovecot-fts']['index']['size']);
$solr_documents = ($solr_status['status']['dovecot-fts']['index']['numDocs']);
if (strtolower(getenv('SKIP_SOLR')) != 'n') {
$solr_enabled = false;
}
else {
$solr_enabled = true;
}
echo json_encode(array(
'type' => 'info',
'solr_enabled' => $solr_enabled,
'solr_size' => $solr_size,
'solr_documents' => $solr_documents
));
break;
case "host":
if (!$extra){
$stats = docker("host_stats");

View File

@ -521,7 +521,6 @@
"external_logs": "Externí logy",
"history_all_servers": "Záznam (všechny servery)",
"in_memory_logs": "Logy v paměti",
"jvm_memory_solr": "Spotřeba paměti JVM",
"last_modified": "Naposledy změněn",
"log_info": "<p><b>Logy v paměti</b> jsou shromažďovány v Redis seznamech a jsou oříznuty na LOG_LINES (%d) každou minutu, aby se nepřetěžoval server.\r\n <br>Logy v paměti nemají být trvalé. Všechny aplikace, které logují do paměti, zároveň logují i do Docker služby podle nastavení logging driveru.\r\n <br>Logy v paměti lze použít pro ladění drobných problémů s kontejnery.</p>\r\n <p><b>Externí logy</b> jsou shromažďovány pomocí API dané aplikace.</p>\r\n <p><b>Statické logy</b> jsou většinou logy činností, které nejsou zaznamenávány do Docker služby, ale přesto je dobré je schraňovat (výjimkou jsou logy API).</p>",
"login_time": "Čas",
@ -530,8 +529,6 @@
"restart_container": "Restartovat",
"service": "Služba",
"size": "Velikost",
"solr_dead": "Solr se spouští, je vypnutý nebo spadl.",
"solr_status": "Stav Solr",
"started_at": "Spuštěn",
"started_on": "Spuštěno",
"static_logs": "Statické logy",

View File

@ -444,12 +444,9 @@
"external_logs": "Eksterne logfiler",
"history_all_servers": "Historie (alle servere)",
"in_memory_logs": "In-memory logs",
"jvm_memory_solr": "Brug af JVM-hukommelse",
"log_info": "<p>mailcow <b>in-memory logs</b> er samlet i Redis-lister og trimmet til LOG_LINES (%d) hvert minut for at reducere hamring.\r\n <br>Logbøger i hukommelsen er ikke beregnet til at være vedholdende. Alle applikationer, der logger ind i hukommelsen, logger også på Docker-dæmonen og derfor til standardlogdriveren.\r\n <br>Logtypen i hukommelsen skal bruges til fejlfinding af mindre problemer med containere.</p>\r\n <p><b>Eksterne logfiler</b> indsamles via API for den givne applikation.</p>\r\n <p><b>Statiske logfiler</b> er for det meste aktivitetslogfiler, der ikke er logget på Dockerd, men stadig skal være vedholdende (undtagen API-logfiler).</p>",
"logs": "Logs",
"restart_container": "Genstart",
"solr_dead": "Solr starter, deaktiveres eller døde.",
"solr_status": "Solr-status",
"started_on": "Startede den",
"static_logs": "Statiske logfiler",
"system_containers": "System og Beholdere",

View File

@ -539,7 +539,6 @@
"external_logs": "Externe Logs",
"history_all_servers": "History (alle Server)",
"in_memory_logs": "In-memory Logs",
"jvm_memory_solr": "JVM-Speicherauslastung",
"last_modified": "Zuletzt geändert",
"log_info": "<p>mailcow <b>in-memory Logs</b> werden in Redis Listen gespeichert, die maximale Anzahl der Einträge pro Anwendung richtet sich nach LOG_LINES (%d).\r\n <br>In-memory Logs sind vergänglich und nicht zur ständigen Aufbewahrung bestimmt. Alle Anwendungen, die in-memory protokollieren, schreiben ebenso in den Docker Daemon.\r\n <br>Das in-memory Protokoll versteht sich als schnelle Übersicht zum Debugging eines Containers, für komplexere Protokolle sollte der Docker Daemon konsultiert werden.</p>\r\n <p><b>Externe Logs</b> werden via API externer Applikationen bezogen.</p>\r\n <p><b>Statische Logs</b> sind weitestgehend Aktivitätsprotokolle, die nicht in den Docker Daemon geschrieben werden, jedoch permanent verfügbar sein müssen (ausgeschlossen API Logs).</p>",
"login_time": "Zeit",
@ -550,8 +549,6 @@
"service": "Dienst",
"show_ip": "Zeige öffentliche IP",
"size": "Größe",
"solr_dead": "Solr startet, ist deaktiviert oder temporär nicht erreichbar.",
"solr_status": "Solr Status",
"started_at": "Gestartet am",
"started_on": "Gestartet am",
"static_logs": "Statische Logs",

View File

@ -539,7 +539,6 @@
"external_logs": "External logs",
"history_all_servers": "History (all servers)",
"in_memory_logs": "In-memory logs",
"jvm_memory_solr": "JVM memory usage",
"last_modified": "Last modified",
"log_info": "<p>mailcow <b>in-memory logs</b> are collected in Redis lists and trimmed to LOG_LINES (%d) every minute to reduce hammering.\r\n <br>In-memory logs are not meant to be persistent. All applications that log in-memory, also log to the Docker daemon and therefore to the default logging driver.\r\n <br>The in-memory log type should be used for debugging minor issues with containers.</p>\r\n <p><b>External logs</b> are collected via API of the given application.</p>\r\n <p><b>Static logs</b> are mostly activity logs, that are not logged to the Dockerd but still need to be persistent (except for API logs).</p>",
"login_time": "Time",
@ -550,8 +549,6 @@
"service": "Service",
"show_ip": "Show public IP",
"size": "Size",
"solr_dead": "Solr is starting, disabled or died.",
"solr_status": "Solr status",
"started_at": "Started at",
"started_on": "Started on",
"static_logs": "Static logs",

View File

@ -346,12 +346,10 @@
"log_info": "<p>Los <b>logs en memoria</b> son recopilados en listas de Redis y recortados a LOG_LINES (%d) cada minuto para prevenir sobrecarga en el sistema.\r\n <br>Los logs en memoria no están destinados a ser persistentes. Todas las aplicaciones que logean a la memoria, también logean en el daemon de Docker y, por lo tanto, en el controlador de registro predeterminado.\r\n El log en memoria se debe utilizar para analizar problemas menores con los contenedores.</p>\r\n <p>Los <b>logs externos</b> se recopilan a través de la API de la aplicación dada.</p>\r\n <p>Los <b>logs estáticos</b> son principalmente registros de actividad, que no están registrados en Dockerd pero que aún deben ser persistentes (excepto los registros de API).</p>",
"logs": "Logs",
"restart_container": "Reiniciar",
"solr_dead": "Solr está empezando, deshabilitado o caído.",
"docs": "Docs",
"last_modified": "Última modificación",
"size": "Tamaño",
"started_at": "Iniciado el",
"solr_status": "Solr status",
"uptime": "Uptime",
"static_logs": "Logs estáticos",
"system_containers": "Sistema y Contenedores"

View File

@ -380,16 +380,13 @@
"disk_usage": "Levyn käyttö",
"external_logs": "Ulkoiset loki",
"in_memory_logs": "Muistissa olevat lokit",
"jvm_memory_solr": "JVM-muistin käyttö",
"log_info": "<p>mailcow <b>muistissa olevat lokit</b> kerätään Redis-luetteloihin ja leikataan LOG_LINES (%d) joka minuutti lyömisen vähentämiseksi.\r\n <br>Muistissa olevien lokien ei ole tarkoitus olla pysyviä. Kaikki sovellukset, jotka kirjautuvat muistiin, kirjautuvat myös Docker-daemoniin ja siten oletusarvoiseen lokitiedostoon.\r\n <br>Muistin lokityyppiä olisi käytettävä virheiden virheenkorjaukseen säilöissä.</p>\r\n <p><b>Ulkoiset lokit</b> kerätään annetun sovelluksen API: n kautta.</p>\r\n <p><b>Staattiset lokit</b> ovat useimmiten toimintalokkeja, joita ei kirjata Dockerdiin, mutta joiden on silti oltava pysyviä (paitsi API-lokit).</p>",
"logs": "Logit tausta palveluista",
"restart_container": "Uudelleen käynnistä",
"solr_dead": "Solr käynnistyy, on poissa käytöstä tai kuoli.",
"docs": "Docs",
"last_modified": "Viimeksi muokattu",
"size": "Koko",
"started_at": "Käynnistetty",
"solr_status": "Solr-tila",
"uptime": "Päällä",
"started_on": "Aloitettiin",
"static_logs": "Staattiset lokit",

View File

@ -498,17 +498,14 @@
"external_logs": "Logs externe",
"history_all_servers": "Historique (tous les serveurs)",
"in_memory_logs": "Logs En-mémoire",
"jvm_memory_solr": "Utilisation mémoire JVM",
"log_info": "<p>Les logs <b>En-mémoire</b> Mailcow sont collectés dans des listes Redis et découpées en LOG_LINES (%d) chaque minute pour réduire la charge.\n <br>Les logs En-mémoire ne sont pas destinés à être persistants. Toutes les applications qui se connectent en mémoire, se connectent également au démon Docker, et donc au pilote de journalisation par défaut.\n <br>Le type de journal en mémoire doit être utilisé pour déboguer les problèmes mineurs avec les conteneurs.</p>\n <p><b>Les logs externes</b> sont collectés via l'API de l'application concernée.</p>\n <p>Les journaux <b>statiques</b> sont principalement des journaux d’activité, qui ne sont pas enregistrés dans Dockerd, mais qui doivent toujours être persistants (sauf pour les logs API).</p>",
"logs": "Logs",
"restart_container": "Redémarrer",
"solr_dead": "Solr est en cours de démarrage, désactivé ou mort.",
"docs": "Docs",
"last_modified": "Dernière modification",
"online_users": "Utilisateurs en ligne",
"size": "Taille",
"started_at": "Démarré à",
"solr_status": "Etat Solr",
"uptime": "Disponibilité",
"started_on": "Démarré à",
"static_logs": "Logs statiques",

View File

@ -494,7 +494,6 @@
"external_logs": "Log esterni",
"history_all_servers": "Cronologia (tutti i server)",
"in_memory_logs": "In-memory logs",
"jvm_memory_solr": "JVM memory usage",
"last_modified": "Ultima modifica",
"log_info": "<p>mailcow <b>in-memory logs</b> are collected in Redis lists and trimmed to LOG_LINES (%d) every minute to reduce hammering.\r\n <br>In-memory logs are not meant to be persistent. All applications that log in-memory, also log to the Docker daemon and therefore to the default logging driver.\r\n <br>The in-memory log type should be used for debugging minor issues with containers.</p>\r\n <p><b>External logs</b> are collected via API of the given application.</p>\r\n <p><b>Static logs</b> are mostly activity logs, that are not logged to the Dockerd but still need to be persistent (except for API logs).</p>",
"login_time": "Orario",
@ -503,8 +502,6 @@
"restart_container": "Riavvio",
"service": "Servizio",
"size": "Dimensione",
"solr_dead": "Solr sta partendo, è disabilitato o morto.",
"solr_status": "Stato Solr",
"started_at": "Iniziato alle",
"started_on": "Iniziato",
"static_logs": "Log statici",

View File

@ -539,7 +539,6 @@
"external_logs": "外部ログ",
"history_all_servers": "履歴(すべてのサーバー)",
"in_memory_logs": "インメモリーログ",
"jvm_memory_solr": "JVMメモリ使用量",
"last_modified": "最終更新日時",
"log_info": "<p>mailcowの<b>インメモリーログ</b>はRedisリストに収集され、ハンマリングを軽減するために1分ごとにLOG_LINES (%d)にトリムされます。\r\n <br>インメモリーログは永続化を目的としたものではありません。インメモリーログを記録するすべてのアプリケーションは、Dockerデーモンとデフォルトのログドライバーにもログを記録します。\r\n <br>インメモリーログタイプは、コンテナの軽微な問題をデバッグするために使用してください。</p>\r\n <p><b>外部ログ</b>は指定されたアプリケーションのAPIを介して収集されます。</p>\r\n <p><b>静的ログ</b>は主にアクティビティログであり、Dockerdには記録されませんが(APIログを除く)、永続化が必要です。</p>",
"login_time": "ログイン時間",
@ -550,8 +549,6 @@
"service": "サービス",
"show_ip": "パブリックIPを表示",
"size": "サイズ",
"solr_dead": "Solrは起動中、無効化、または停止しました。",
"solr_status": "Solrのステータス",
"started_at": "開始時刻",
"started_on": "開始日",
"static_logs": "静的ログ",

View File

@ -424,16 +424,13 @@
"external_logs": "External logs",
"history_all_servers": "History (all servers)",
"in_memory_logs": "In-memory logs",
"jvm_memory_solr": "JVM memory usage",
"log_info": "<p>mailcow <b>in-memory logs</b> are collected in Redis lists and trimmed to LOG_LINES (%d) every minute to reduce hammering.\r\n <br>In-memory logs are not meant to be persistent. All applications that log in-memory, also log to the Docker daemon and therefore to the default logging driver.\r\n <br>The in-memory log type should be used for debugging minor issues with containers.</p>\r\n <p><b>External logs</b> are collected via API of the given application.</p>\r\n <p><b>Static logs</b> are mostly activity logs, that are not logged to the Dockerd but still need to be persistent (except for API logs).</p>",
"logs": "Logs",
"restart_container": "Restart",
"solr_dead": "Solr is starting, disabled or died.",
"docs": "Docs",
"last_modified": "Last modified",
"size": "Size",
"started_at": "Started at",
"solr_status": "Solr status",
"uptime": "Uptime",
"started_on": "Started on",
"static_logs": "Static logs",

View File

@ -643,7 +643,6 @@
"logs": "Žurnāli",
"architecture": "Arhitektūra",
"disk_usage": "Diska lietojums",
"jvm_memory_solr": "JVM atmiņas lietojums",
"memory": "Atmiņa",
"timezone": "Laika josla",
"uptime": "Darbošanās laiks"

View File

@ -328,12 +328,10 @@
"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",

View File

@ -472,17 +472,14 @@
"external_logs": "Externe logs",
"history_all_servers": "Geschiedenis (alle servers)",
"in_memory_logs": "Geheugenlogs",
"jvm_memory_solr": "JVM-geheugengebruik",
"log_info": "<p>Mailcows <b>geheugenlogs</b> worden elke minuut afgesneden naar maximaal %d regels (LOG_LINES) om de stabiliteit te garanderen.<br>Geheugenlogs zijn niet bedoeld om bewaard te blijven. Alle applicaties die geheugenlogs schrijven worden ook naar het Docker-proces gelogd.<br>De geheugenlogs kunnen gebruikt worden voor het oplossen van problemen met bepaalde containers.</p><p><b>Externe logs</b> worden verzameld door middel van de API van deze applicaties.</p><p><b>Statische logs</b> zijn activiteitenlogs die niet naar het Docker-proces worden gelogd, maar wel bewaard moeten blijven (uitgezonderd API-logs).</p>",
"logs": "Logs",
"restart_container": "Herstart",
"solr_dead": "Solr is uitgeschakeld, uitgevallen of nog bezig met opstarten.",
"docs": "Documenten",
"last_modified": "Voor het laatst bijgewerkt op",
"online_users": "Gebruikers online",
"size": "Grootte",
"started_at": "Opgestart op",
"solr_status": "Solr-status",
"uptime": "Uptime",
"started_on": "Gestart op",
"static_logs": "Statische logs",

View File

@ -539,7 +539,6 @@
"external_logs": "Registros externos",
"history_all_servers": "Histórico (todos os servidores)",
"in_memory_logs": "Registros na memória",
"jvm_memory_solr": "Uso de memória JVM",
"last_modified": "Última modificação",
"log_info": "<p>Os <b>registros na memória do</b> mailcow são coletados em listas do Redis e reduzidos para LOG_LINES (%d) a cada minuto para reduzir o martelamento.\r\n Os <br>registros na memória não devem ser persistentes. Todos os aplicativos que fazem login na memória também fazem login no daemon do Docker e, portanto, no driver de registro padrão.\r\n </p><br>O tipo de registro na memória deve ser usado para depurar pequenos problemas com contêineres.\r\n <p>Os <b>registros externos</b> são coletados por meio da API do aplicativo em questão.</p>\r\n <p>Os <b>registros estáticos</b> são principalmente registros de atividades, que não são registrados no Dockerd, mas ainda precisam ser persistentes (exceto os registros da API).</p>",
"login_time": "Hora",
@ -550,8 +549,6 @@
"service": "Serviço",
"show_ip": "Mostrar IP público",
"size": "Tamanho",
"solr_dead": "O Solr está iniciando, desativado ou morreu.",
"solr_status": "Status do solr",
"started_at": "Começou em",
"started_on": "Começou em",
"static_logs": "Registros estáticos",

View File

@ -481,7 +481,6 @@
"external_logs": "Jurnale externe",
"history_all_servers": "Istoric (toate serverele)",
"in_memory_logs": "Jurnale din memorie",
"jvm_memory_solr": "Memorie utilizată de JVM",
"last_modified": "Ultima modificare",
"log_info": "<p><b>jurnalele din memorie</b> pentru mailcow sunt colectate în listele Redis și trimise la LOG_LINES (%d) în fiecare minut pentru a reduce ciocnirea.\n <br>Jurnalele din memorie nu sunt menite a fi persistente. Toate aplicațiile care înregistrează jurnale în memorie, înregistrează de asemenea jurnale în daemonul Docker și, prin urmare, în driverul de jurnale implicit.\n <br>Tipul de jurnal din memorie trebuie utilizat pentru depanarea problemelor minore cu containerele.</p>\n <p><b>Jurnalele externe</b> sunt colectate prin API-ul aplicației respective.</p>\n <p><b>Jurnalele statice</b> sunt, în majoritate, jurnale de activitate care nu sunt înregistrate în Docker, dar trebuie să fie persistente (cu excepția jurnalelor API).</p>",
"login_time": "Moment",
@ -490,8 +489,6 @@
"restart_container": "Repornire",
"service": "Serviciu",
"size": "Mărime",
"solr_dead": "Solr începe, este invalid sau s-a oprit.",
"solr_status": "Stare Solr",
"started_at": "Pornit la",
"started_on": "Început pe",
"static_logs": "Jurnale statice",

View File

@ -539,7 +539,6 @@
"external_logs": "Внешние журналы",
"history_all_servers": "История (все серверы)",
"in_memory_logs": "Журналы контейнеров",
"jvm_memory_solr": "Использовано оперативной памяти JVM",
"last_modified": "Последние изменения",
"log_info": "<p><b>Журналы контейнеров</b> mailcow сохраняются в Redis, и раз в минуту строки журнала за пределами <code>LOG_LINES (%d)</code> удаляются, чтобы уменьшить нагрузку на сервер.\r\n <br>Сами журналы контейнеров не сохраняются после перезагрузки контейнера. Все контейнеры дополнительно пишут логи в службу Docker, и, следовательно, используют драйвер логирования по умолчанию. Журналы контейнеров предусмотрены только для отладки мелких проблем. Для других задач, пожалуйста, настройте драйвер логирования Docker самостоятельно.</p>\r\n <p><b>Внешние журналы</b> собираются через API приложений.</p>\r\n <p><b>Статические журналы</b> &ndash; это, в основном, журналы активности, которые не записываются в Dockerd, но все равно должны быть постоянными (за исключением журналов API).</p>",
"login_time": "Время входа",
@ -551,8 +550,6 @@
"service": "Сервис",
"show_ip": "Показать публичные IP-адреса",
"size": "Индексы занимают",
"solr_dead": "Solr не запущен. Если вы включили Solf в файле настроек <code>mailcow.conf</code> и это сообщение отображается более получаса, скорее всего Solr сломан.",
"solr_status": "Состояние Solr",
"started_at": "Запущен",
"started_on": "Запущен в",
"static_logs": "Статические журналы",

View File

@ -501,12 +501,9 @@
"last_modified": "Nazadnje spremenjeno",
"history_all_servers": "Zgodovina (vsi strežniki)",
"in_memory_logs": "In-memory dnevniki",
"jvm_memory_solr": "JVM zasedenost spomina",
"service": "Servis",
"show_ip": "Prikaži javni IP",
"size": "Velikost",
"solr_dead": "Solr se zaganja, je onemogočen ali se je ustavil.",
"solr_status": "Status Solr",
"started_at": "Zagnano ob",
"started_on": "Zagnano na",
"static_logs": "Statični dnevniki",

View File

@ -499,7 +499,6 @@
"external_logs": "Externé logy",
"history_all_servers": "História (všetky servery)",
"in_memory_logs": "Logy uložené v pamäti",
"jvm_memory_solr": "JVM spotreba pamäte",
"last_modified": "Naposledy upravené",
"log_info": "<b>Logy v pamäti</b> sú zbierané do Redis listu s max. limitom LOG_LINES (%d) riadkov každú minútu, čo bráni nadmernej záťaži servera.\r\n <br>Logy v pamäti nemajú trvalý charakter. Všetky aplikácie ktoré vedú logy v pamäti, tiež logujú do Docker démona a súčasne do nastaveného logging drivera.\r\n <br>Logy v pamäti sa môžu použiť na ladenie menších problémov s kontajnermi.</p>\r\n <p><b>Externé logy</b> sú zbierané cez API danej aplikácie.</p>\r\n <p><b>Statické logy</b> sú väčšinou aktivity, ktoré nie sú logované do Docker démona, ale musia byť trvalo zaznamenané (s výnimkou API záznamov).</p>",
"login_time": "Čas",
@ -508,8 +507,6 @@
"restart_container": "Reštartovať",
"service": "Služba",
"size": "Veľkosť",
"solr_dead": "Solr štartuje, je vypnutý alebo nebeží.",
"solr_status": "Solr status",
"started_at": "Spustený",
"started_on": "Spustený",
"static_logs": "Statické logy",

View File

@ -453,17 +453,14 @@
"external_logs": "Externa loggar",
"history_all_servers": "Historik (alla servrar)",
"in_memory_logs": "Loggar sparade i minnet",
"jvm_memory_solr": "JVM minnesanvändning",
"log_info": "<p>mailcow <b>loggar sparade i minnet</b> samlas in i Redis-listor och trimmas till LOG_LINES (%d) varje minut för att minska lasten.\r\n <br>Loggar sparade i minnet är inte tänkta att vara beständiga. Alla applikationer som loggar i minnet loggar också till Docker-demonen och därefter till standardrutinen för loggning.\r\n <br>Loggar sparade i minnet bör användas för felsökning av mindre problem med olika behållare.</p>\r\n <p><b>Externa loggar</b> samlas in via ett API på den givna applikationen.</p>\r\n <p><b>Statiska loggar</b> är mestadels aktivitetsloggar som inte är loggas i Docker, men som fortfarande måste vara beständiga (utom API-loggar).</p>",
"logs": "Loggar",
"restart_container": "Omstart",
"solr_dead": "Solr är i uppstart, har inaktiveras eller är tillfälligt avstängd.",
"online_users": "Användare online",
"docs": "Dokumentation",
"last_modified": "Senast ändrad",
"size": "Storlek",
"started_at": "Startades kl.",
"solr_status": "Solr status",
"uptime": "Upptid",
"started_on": "Startades",
"static_logs": "Statiska loggar",

View File

@ -694,15 +694,12 @@
"external_logs": "Harici günlükler",
"history_all_servers": "Geçmiş (tüm sunucular)",
"in_memory_logs": "Bellek içi günlükler",
"jvm_memory_solr": "JVM bellek kullanımı",
"memory": "Hafıza",
"online_users": "Aktif kullanıcılar",
"restart_container": "Yeniden başlat",
"service": "Servis",
"show_ip": "Genel IP'yi göster",
"size": "Boyut",
"solr_dead": "Solr başlatılıyor, devre dışı bırakıldı veya öldü.",
"solr_status": "Solr durumu",
"started_at": "Başlangıç",
"system_containers": "Sistem ve Konteynerler",
"timezone": "Zaman Dilimi",

View File

@ -503,8 +503,6 @@
"restart_container": "Перезапустити",
"service": "Сервіс",
"size": "Розмір індексів",
"solr_dead": "Solr запускається, відключений або сламаний.",
"solr_status": "Стан Solr",
"started_at": "Запущений",
"started_on": "Запущений у",
"static_logs": "Статичні журнали",
@ -513,7 +511,6 @@
"uptime": "Час роботи",
"username": "Ім'я користувача",
"external_logs": "Зовнішні журнали",
"jvm_memory_solr": "Використання оперативної пам'яті JVM",
"log_info": "<p><b>Журнали контейнерів</b> mailcow зберігаються в Redis, і раз на хвилину рядки журналу за межами <code>LOG_LINES (%d)</code> видаляються, щоб зменшити навантаження на сервер.\n <br>Самі журнали контейнерів не зберігаються після перезавантаження контейнера. Усі контейнери додатково пишуть логи у службу Docker, і, отже, використовують драйвер логування за промовчанням. Журнали контейнерів призначені лише для налагодження дрібних проблем. Для інших завдань, будь ласка, настройте драйвер логування Docker самостійно.</p>\n <p><b>Зовнішні журнали</b> збираються через API програм.</p>\n <p><b>Статичні журнали</b> &ndash; це в основному журнали активності, які не записуються в Dockerd, але все одно повинні бути постійними (за винятком журналів API).</p>",
"error_show_ip": "Не вдалося розпізнати публічні IP-адреси",
"no_update_available": "Система працює на останній версії",

View File

@ -505,7 +505,6 @@
"external_logs": "外部日志",
"history_all_servers": "历史 (所有服务器)",
"in_memory_logs": "内存日志",
"jvm_memory_solr": "JVM 内存使用",
"last_modified": "最后修改",
"log_info": "<p>Mailcow 的<b>内存日志</b>储存于 Redis 列表中,并且每分钟自动降低到 LOG_LINES (%d) 以减少错误。\r\n <br>内存日志不是为了持久化储存的,所有使用内存日志的应用同时也会写入日志到 Docker 的守护进程的默认日志驱动中。\r\n <br>内存日志应该用于分析 (Debug) 容器中不明显的问题。</p>\r\n <p><b>外部日志</b>通过相应应用提供的 API 收集。</p>\r\n <p><b>静态日志</b>大多数为不写入日志到 Docker ,但仍然需要被持久化的活动日志 (API 日志外的)。</p>",
"login_time": "时间",
@ -514,8 +513,6 @@
"restart_container": "重启",
"service": "服务",
"size": "大小",
"solr_dead": "Solr 在启动中、已关闭或已停止。",
"solr_status": "Solr 状态",
"started_at": "开始于",
"started_on": "启动于",
"static_logs": "静态日志",

View File

@ -505,7 +505,6 @@
"external_logs": "外部紀錄",
"history_all_servers": "歷史 (所有伺服器)",
"in_memory_logs": "記憶體紀錄",
"jvm_memory_solr": "JVM 記憶體使用量",
"last_modified": "上次修改時間",
"log_info": "<p>mailcow 的<b>記憶體紀錄</b>會被收集到 Redis 清單中並且每分鐘自動縮減到 LOG_LINES (%d) 以避免重複撞擊 (hammering) 造成的大量記錄。\r\n<br>記憶體紀錄並不會永久保存。所有記錄到記憶體的應用程式也會同時透過預設紀錄的驅動程式寫入紀錄到 Docker 常駐程式中。\r\n<br>記憶體紀錄是設計用來為容器中的小問題除錯的。</p>\r\n<p><b>外部紀錄</b>透過應用程式提供的 API 收集。</p>\r\n<p><b>靜態紀錄</b>大多為不寫入到 Dockerd,但仍然需要被保存的活動紀錄 (API 紀錄除外)。</p>",
"login_time": "時間",
@ -514,8 +513,6 @@
"restart_container": "重新啟動",
"service": "服務",
"size": "大小",
"solr_dead": "Solr 正在啟動,停用或已停止運行.",
"solr_status": "Solr 狀態",
"started_at": "啟動於",
"started_on": "啟動於",
"static_logs": "靜態紀錄",

File diff suppressed because one or more lines are too long

View File

@ -165,7 +165,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_FTS=${SKIP_FTS:-y}
- SKIP_CLAMD=${SKIP_CLAMD:-n}
- SKIP_SOGO=${SKIP_SOGO:-n}
- ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
@ -174,7 +174,6 @@ services:
- DEMO_MODE=${DEMO_MODE:-n}
- WEBAUTHN_ONLY_TRUSTED_VENDORS=${WEBAUTHN_ONLY_TRUSTED_VENDORS:-n}
- CLUSTERMODE=${CLUSTERMODE:-}
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-}
restart: always
networks:
mailcow-network:
@ -234,6 +233,7 @@ services:
depends_on:
- mysql-mailcow
- netfilter-mailcow
- redis-mailcow
dns:
- ${IPV4_NETWORK:-172.22.1}.254
cap_add:
@ -267,14 +267,15 @@ 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_FTS=${SKIP_FTS:-y}
- FTS_HEAP=${FTS_HEAP:-512}
- FTS_PROCS=${FTS_PROCS:-3}
- MAILDIR_SUB=${MAILDIR_SUB:-}
- MASTER=${MASTER:-y}
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- REDISPASS=${REDISPASS}
- COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-n}
ports:
- "${DOVEADM_PORT:-127.0.0.1:19991}:12345"
- "${IMAP_PORT:-143}:143"
@ -558,28 +559,6 @@ services:
aliases:
- dockerapi
##### Will be removed soon #####
solr-mailcow:
image: mailcow/solr:1.8.3
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}
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-n}
networks:
mailcow-network:
aliases:
- solr
################################
olefy-mailcow:
image: mailcow/olefy:1.13
restart: always
@ -636,7 +615,6 @@ services:
- netfilter-mailcow
- watchdog-mailcow
- dockerapi-mailcow
- solr-mailcow
environment:
- TZ=${TZ}
image: robbertkl/ipv6nat
@ -668,7 +646,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:

View File

@ -175,28 +175,6 @@ if [ -z "${SKIP_CLAMD}" ]; then
fi
fi
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
;;
esac
else
SKIP_SOLR=n
fi
fi
if [[ ${SKIP_BRANCH} != y ]]; then
echo "Which branch of mailcow do you want to use?"
echo ""
@ -305,7 +283,6 @@ POPS_PORT=995
SIEVE_PORT=4190
DOVEADM_PORT=127.0.0.1:19991
SQL_PORT=127.0.0.1:13306
SOLR_PORT=127.0.0.1:18983
REDIS_PORT=127.0.0.1:7654
# Your timezone
@ -402,14 +379,22 @@ 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 FTS (Fulltext Search) for Dovecot on low-memory systems or if you simply want to disable it.
# Dovecot inside mailcow use Flatcurve as FTS Backend.
SKIP_SOLR=${SKIP_SOLR}
SKIP_FTS=n
# 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.
# 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!
SOLR_HEAP=1024
FTS_HEAP=128
# 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
FTS_PROCS=5
# Allow admins to log into SOGo as email user (without any password)

View File

@ -34,8 +34,5 @@ services:
dockerapi-mailcow:
build: ./data/Dockerfiles/dockerapi
solr-mailcow:
build: ./data/Dockerfiles/solr
olefy-mailcow:
build: ./data/Dockerfiles/olefy

414
update.sh
View File

@ -303,6 +303,400 @@ fix_broken_dnslist_conf() {
}
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_FTS"
"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_FTS" ]]; then
if ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
echo '# Skip FTS (Fulltext Search) for Dovecot on low-memory systems or if you simply want to disable it.' >> mailcow.conf
echo "# Dovecot inside mailcow use Flatcurve as FTS Backend." >> mailcow.conf
echo "SKIP_FTS=n" >> 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=2" >> 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() {
sed -i --follow-symlinks '$a\' mailcow.conf
if grep -q "SOLR_HEAP" mailcow.conf; then
echo "Removing SOLR_HEAP in mailcow.conf"
sed -i '/# Solr heap size in MB\b/d' mailcow.conf
sed -i '/# Solr is a prone to run\b/d' mailcow.conf
sed -i '/SOLR_HEAP\b/d' mailcow.conf
fi
if grep -q "SKIP_SOLR" mailcow.conf; then
echo "Removing SKIP_SOLR in mailcow.conf"
sed -i '/\bSkip Solr on low-memory\b/d' mailcow.conf
sed -i '/\bSolr is disabled by default\b/d' mailcow.conf
sed -i '/\bDisable Solr or\b/d' mailcow.conf
sed -i '/\bSKIP_SOLR\b/d' mailcow.conf
fi
if grep -q "SOLR_PORT" mailcow.conf; then
echo "Removing SOLR_PORT in mailcow.conf"
sed -i '/\bSOLR_PORT\b/d' mailcow.conf
fi
if grep -q "FLATCURVE_EXPERIMENTAL" mailcow.conf; then
echo "Removing FLATCURVE_EXPERIMENTAL in mailcow.conf"
sed -i '/\bFLATCURVE_EXPERIMENTAL\b/d' mailcow.conf
fi
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-12.\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
@ -523,8 +917,6 @@ CONFIG_ARRAY=(
"MAILDIR_GC_TIME"
"MAILDIR_SUB"
"ACL_ANYONE"
"SOLR_HEAP"
"SKIP_SOLR"
"ENABLE_SSL_SNI"
"ALLOW_ADMIN_EMAIL_LOGIN"
"SKIP_HTTP_VERIFICATION"
@ -651,21 +1043,6 @@ for option in "${CONFIG_ARRAY[@]}"; do
echo '# Otherwise a user might share data with too many other users.' >> mailcow.conf
echo 'ACL_ANYONE=disallow' >> mailcow.conf
fi
elif [[ "${option}" == "SOLR_HEAP" ]]; then
if ! grep -q "${option}" mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
echo '# Solr heap size, there is no recommendation, please see Solr docs.' >> mailcow.conf
echo '# Solr is a prone to run OOM on large systems and should be monitored. Unmonitored Solr setups are not recommended.' >> mailcow.conf
echo '# Solr will refuse to start with total system memory below or equal to 2 GB.' >> mailcow.conf
echo "SOLR_HEAP=1024" >> mailcow.conf
fi
elif [[ "${option}" == "SKIP_SOLR" ]]; then
if ! grep -q "${option}" mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
echo '# Solr is disabled by default after upgrading from non-Solr to Solr-enabled mailcows.' >> mailcow.conf
echo '# Disable Solr or if you do not want to store a readable index of your mails in solr-vol-1.' >> mailcow.conf
echo "SKIP_SOLR=y" >> mailcow.conf
fi
elif [[ "${option}" == "ENABLE_SSL_SNI" ]]; then
if ! grep -q "${option}" mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
@ -998,7 +1375,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