Elasticsearch server setup¶
Available on Enterprise and Enterprise Advanced plans
Elasticsearch allows you to search large volumes of data quickly, in near real-time, by creating and managing an index of post data. The indexing process can be managed from the System Console after setting up and connecting an Elasticsearch server. The post index is stored on the Elasticsearch server and updated constantly after new posts are made. In order to index existing posts, a bulk index of the entire post database must be generated.
Deploying Elasticsearch includes the following steps: setting up a single Elasticsearch node, optionally configuring a multi-node cluster, and configuring Mattermost.
Set up a single Elasticsearch node¶
We highly recommend that you set up an Elasticsearch server on a dedicated machine separate from the Mattermost Server.
Download and install the latest release of Elasticsearch v8, or Elasticsearch v7.17+. See the Elasticsearch documentation for installation details.
Set up Elasticsearch with
systemdby running the following commands:
sudo /bin/systemctl daemon-reload sudo /bin/systemctl enable elasticsearch.service sudo systemctl start elasticsearch.service
Confirm Elasticsearch is working on the server. For Elasticsearch 7.x:
curl localhost:9200For Elasticsearch 8.x, TLS is enabled by default:
sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200Note
Elasticsearch 8.x generates a password for the
elasticsuperuser during installation. If you did not save it, reset it by running:sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
Determine the IP address that Elasticsearch should bind to by running the following command:
hostname -INote
When deploying in cloud environments such as AWS EC2, use the instance’s private IP address. The public IP assigned by the cloud provider is not bound to the network interface, and Elasticsearch will fail to start if it cannot bind to the configured address.
Edit the Elasticsearch configuration file:
vi /etc/elasticsearch/elasticsearch.yml
Set the
network.hostvalue to the IP address from step 4, and save your changes.
Important
When
network.hostis set to a specific IP address, Elasticsearch will only bind to that address. Local connections vialocalhostor127.0.0.1(e.g. for health checks or troubleshooting from the node itself) will stop working. To allow both local and network connections, also add the following lines toelasticsearch.yml:http.host: 0.0.0.0 transport.host: 0.0.0.0This tells Elasticsearch to accept HTTP API and inter-node transport connections on all network interfaces, whilst
network.hostcontinues to control the address advertised to other nodes.
When using Elasticsearch v8, ensure you set
action.destructive_requires_nametofalseinelasticsearch.ymlto allow for wildcard operations to work.Restart Elasticsearch by running the following commands:
sudo systemctl stop elasticsearch sudo systemctl start elasticsearch
Confirm the ports are listening by running the following command:
ss -tlnpLook for two lines with a
javaprocess: one listening on port9200(the HTTP API) and one on port9300(the inter-node transport port). If you added thehttp.hostandtransport.hostsettings in step 6, both ports will show as*:9200and*:9300(listening on all interfaces). If not, they will only appear on the specific IP address configured innetwork.host.
Install the icu-analyzer plugin by running the following command:
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-icu
Restart Elasticsearch after installing the plugin:
sudo systemctl restart elasticsearch
Test the connection from your Mattermost server to Elasticsearch by running the following command from the Mattermost server, replacing the example IP address with your Elasticsearch server’s IP address. For Elasticsearch 7.x:
curl 10.0.1.10:9200For Elasticsearch 8.x:
curl -k -u elastic https://10.0.1.10:9200
Set up an Elasticsearch cluster¶
For production environments requiring high availability and fault tolerance, deploy Elasticsearch as a multi-node cluster rather than a single node. A cluster distributes data across multiple nodes, providing redundancy and improved search performance. If one node goes down, the remaining nodes continue to serve search requests without interruption.
Important
Complete the single-node setup above on your first server before proceeding with cluster configuration. The first node becomes the foundation of your cluster.
Cluster prerequisites¶
Before configuring a cluster, ensure the following requirements are met:
Minimum three nodes: Deploy an odd number of master-eligible nodes (minimum of three) to prevent split-brain scenarios, where the cluster partitions into two halves that each elect their own master node.
Same Elasticsearch version: All nodes in the cluster must run the same version of Elasticsearch.
Network connectivity: All nodes must be able to communicate with each other on ports
9200(HTTP API) and9300(inter-node transport).Hostname resolution: Each node must be able to resolve the hostnames of all other nodes, either via DNS or the
/etc/hostsfile.ICU Analyzer plugin: The
analysis-icuplugin must be installed on every node in the cluster, not just the first node.
Note
When deploying in cloud environments such as AWS EC2, use each instance’s private IP address for network.host, discovery.seed_hosts, and any /etc/hosts entries. The public IP assigned by the cloud provider is not bound to the network interface, and Elasticsearch will fail to start if it cannot bind to the configured address. You can find the private IP by running hostname -I on each instance.
Node roles¶
Each Elasticsearch node can serve one or more roles:
Master-eligible: Manages cluster-wide operations such as creating or deleting indexes, tracking cluster membership, and deciding which data shards are allocated to which nodes.
Data: Stores indexed data and handles search and aggregation requests. Data nodes consume significant CPU, memory, and I/O resources.
Coordinating: Routes client requests to the appropriate data nodes and merges results. Every node acts as a coordinating node by default.
For most Mattermost deployments, a three-node cluster where every node is both master-eligible and a data node is the recommended configuration.
Set up a cluster using Elasticsearch 8.x¶
Elasticsearch 8.x enables TLS security by default and generates unique certificates on each node during installation. To form a cluster, nodes must share the same certificate authority (CA). This is handled automatically using enrollment tokens: you start the first node, generate a token, and use it to enrol each additional node. This process copies the CA certificates from the first node to each new node.
Important
You must start and verify the first node before configuring additional nodes. Do not attempt to configure all nodes simultaneously — the enrollment token workflow requires a running, healthy first node to generate tokens and distribute certificates.
Configure and start the first node
Edit the Elasticsearch configuration file on the first node:
vi /etc/elasticsearch/elasticsearch.yml
Configure the following cluster settings. Replace the example IP addresses with the actual private IP addresses of your servers:
# Give your cluster a descriptive name cluster.name: mattermost-es-cluster # Set a unique name for this node node.name: es-node-01 # Bind to this server's private IP address network.host: 10.0.1.10 # Allow local and network connections http.host: 0.0.0.0 transport.host: 0.0.0.0 # List the private IP addresses of all nodes for discovery discovery.seed_hosts: ["10.0.1.10", "10.0.1.11", "10.0.1.12"] # Mattermost requirement action.destructive_requires_name: falseWarning
Elasticsearch 8.x automatically adds a
cluster.initial_master_nodesentry toelasticsearch.ymlduring installation. Do not add a second one — duplicate YAML keys will cause Elasticsearch to fail to start with a parse error. Instead, find the existingcluster.initial_master_nodesline in the file and update it to contain only the first node’s name:cluster.initial_master_nodes: ["es-node-01"]You can check for duplicate entries by running:
grep -n "cluster.initial_master_nodes" /etc/elasticsearch/elasticsearch.yml
Start Elasticsearch on the first node:
sudo systemctl daemon-reload sudo systemctl enable elasticsearch.service sudo systemctl start elasticsearch.service
Verify the first node is running. Elasticsearch 8.x uses HTTPS by default:
sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200You will be prompted for the
elasticsuperuser password that was generated during installation. If you did not save it, reset it by running:sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elasticNote
The same
elasticsuperuser password is used to authenticate against any node in the cluster. You do not need separate passwords for each node.
Generate an enrollment token
On the first node, generate an enrollment token for adding new nodes:
sudo /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s nodeThis token is valid for 30 minutes. If it expires, generate a new one by running the same command again.
Enrol and start each additional node
Repeat the following steps for each additional node (e.g., es-node-02, es-node-03).
Install Elasticsearch and the ICU Analyzer plugin on the additional node (if not already done as part of the single-node setup):
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-icu
Before starting Elasticsearch, run the reconfigure command with the enrollment token from step 5:
sudo /usr/share/elasticsearch/bin/elasticsearch-reconfigure-node --enrollment-token <token-from-step-5>This copies the TLS certificates from the first node and configures security automatically.
Edit the Elasticsearch configuration file on the additional node:
vi /etc/elasticsearch/elasticsearch.yml
Configure the cluster settings. The
cluster.nameanddiscovery.seed_hostsmust match the first node. Set a uniquenode.nameandnetwork.hostfor this node:
# Must match the first node's cluster name cluster.name: mattermost-es-cluster # Set a unique name for this node node.name: es-node-02 # Bind to this server's private IP address network.host: 10.0.1.11 # Allow local and network connections http.host: 0.0.0.0 transport.host: 0.0.0.0 # Same discovery settings as the first node discovery.seed_hosts: ["10.0.1.10", "10.0.1.11", "10.0.1.12"] # Mattermost requirement action.destructive_requires_name: falseAs with the first node, check for and update any existing
cluster.initial_master_nodesentry rather than adding a duplicate. For additional nodes, this line can be removed entirely or updated to match the first node’s value.
Start Elasticsearch on the additional node:
sudo systemctl daemon-reload sudo systemctl enable elasticsearch.service sudo systemctl start elasticsearch.service
Repeat steps 6 through 10 for each remaining node, adjusting
node.nameandnetwork.hostaccordingly. Generate a new enrollment token on the first node if the previous one has expired.
Note
The cluster.initial_master_nodes setting is only used during the very first bootstrap of the cluster. Once the cluster is formed, this setting is ignored. Some administrators choose to remove it after initial cluster formation to prevent accidental re-bootstrapping.
Set up a cluster using Elasticsearch 7.x¶
For Elasticsearch 7.x, enrollment tokens are not available. Instead, configure each node manually. Elasticsearch 7.x does not enable TLS by default, so nodes can discover each other without shared certificates.
On each node, edit the Elasticsearch configuration file:
vi /etc/elasticsearch/elasticsearch.yml
Configure the cluster settings on each node. The
cluster.name,discovery.seed_hosts, andcluster.initial_master_nodesvalues must be the same on every node. Set a uniquenode.nameandnetwork.hostfor each node:
# Same on all nodes cluster.name: mattermost-es-cluster discovery.seed_hosts: ["10.0.1.10", "10.0.1.11", "10.0.1.12"] cluster.initial_master_nodes: ["es-node-01", "es-node-02", "es-node-03"] # Unique per node node.name: es-node-01 network.host: 10.0.1.10 # Allow local and network connections http.host: 0.0.0.0 transport.host: 0.0.0.0
If TLS is required, you must manually generate and distribute certificates to all nodes. See the Elasticsearch security documentation for details.
Start Elasticsearch on all nodes. They can be started in any order:
sudo systemctl daemon-reload sudo systemctl enable elasticsearch.service sudo systemctl start elasticsearch.service
Note
The cluster.initial_master_nodes setting is only used during the very first bootstrap of the cluster. Once the cluster is formed, this setting is ignored. Some administrators choose to remove it after initial cluster formation to prevent accidental re-bootstrapping.
Disable memory swapping¶
Memory swapping can cause Elasticsearch nodes to respond slowly or disconnect from the cluster entirely. It is strongly recommended to disable swapping on all cluster nodes.
To enable memory locking, add or uncomment the following line in elasticsearch.yml on each node:
bootstrap.memory_lock: true
Then configure the systemd service to permit memory locking. Create or edit the systemd override file:
sudo systemctl edit elasticsearch
Add the following content:
[Service]
LimitMEMLOCK=infinity
Reload systemd and restart Elasticsearch:
sudo systemctl daemon-reload
sudo systemctl restart elasticsearch
Verify that memory locking is active. For Elasticsearch 7.x:
curl -X GET "localhost:9200/_nodes?filter_path=**.mlockall"
For Elasticsearch 8.x:
sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200/_nodes?filter_path=**.mlockall
The response should show "mlockall": true for each node.
Note
If localhost does not respond in the commands above, ensure you have configured http.host: 0.0.0.0 and transport.host: 0.0.0.0 in elasticsearch.yml as described in step 6 of the single-node setup.
Verify cluster health¶
After all nodes have joined the cluster, verify that the cluster is healthy.
For Elasticsearch 7.x:
curl -X GET "localhost:9200/_cluster/health?pretty"
curl -X GET "localhost:9200/_cat/nodes?v"
For Elasticsearch 8.x:
sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200/_cluster/health?pretty
sudo curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic https://localhost:9200/_cat/nodes?v
A healthy cluster returns a status of green, indicating that all primary and replica shards are allocated. A yellow status means all primary shards are allocated but some replicas are not yet assigned — this may occur temporarily while the cluster rebalances after a new node joins.
Confirm that the expected number of nodes appears in the _cat/nodes output.
Configure Mattermost¶
Follow these steps to configure Mattermost to use your Elasticsearch server and to generate the post index:
Go to System Console > Environment > Elasticsearch.
Set Enable Elasticsearch Indexing to
trueto enable the other settings on the page. Once the configuration is saved, new posts made to the database are automatically indexed on the Elasticsearch server.Ensure Backend type is set to
elasticsearch.
Configure TLS for Elasticsearch 8.x¶
Elasticsearch 8.x enables TLS by default. Mattermost must be configured to trust the Elasticsearch CA certificate before it can connect.
Note
This section applies only to Elasticsearch 8.x. Elasticsearch 7.x does not enable TLS by default, and Mattermost can connect to it over plain HTTP without additional certificate configuration.
Copy the CA certificate from Elasticsearch to Mattermost¶
On any Elasticsearch 8.x node, locate the CA certificate:
ls -la /etc/elasticsearch/certs/http_ca.crt
Create the certificate directory on the Mattermost server:
sudo mkdir -p /opt/mattermost/data/elasticsearch sudo chown mattermost:mattermost /opt/mattermost/data/elasticsearch
Copy the CA certificate from the Elasticsearch node to the Mattermost server. Run this from the Mattermost server, replacing the example IP address with the private IP of any Elasticsearch 8.x node:
sudo scp root@10.0.1.10:/etc/elasticsearch/certs/http_ca.crt /opt/mattermost/data/elasticsearch/ca.pemNote
The file must be named
ca.pemand placed in/opt/mattermost/data/elasticsearch/. Mattermost expects the certificate at this specific path.
Set the correct ownership and permissions:
sudo chown mattermost:mattermost /opt/mattermost/data/elasticsearch/ca.pem sudo chmod 640 /opt/mattermost/data/elasticsearch/ca.pem
Configure the Mattermost connection¶
Go to System Console > Environment > Elasticsearch.
Set the Server Connection Address to the HTTPS address of any Elasticsearch 8.x node, e.g.
https://10.0.1.10:9200.
Important
The connection address must use
https://, nothttp://. Elasticsearch 8.x does not respond to plain HTTP connections.
Set the Server Username to
elastic.Set the Server Password to the
elasticsuperuser password from your Elasticsearch installation.Set the CA path to
./elasticsearch/ca.pem.The Client Certificate path and Client Certificate Key path fields can be left empty — they are not required for standard Elasticsearch 8.x connections.
Select Test Connection to verify that Mattermost can communicate with the Elasticsearch cluster.
Important
Do not set Skip TLS Verification to true as a workaround for certificate issues. Configure the CA certificate path as described above.
Configure Mattermost for an Elasticsearch cluster¶
When connecting Mattermost to an Elasticsearch cluster rather than a single node, the following additional configuration is recommended.
Enable cluster sniffing¶
Set Enable Cluster Sniffing to true in System Console > Environment > Elasticsearch. Sniffing allows Mattermost to automatically discover and connect to all data nodes in the cluster. With sniffing enabled, you only need to provide the address of one node in the Server Connection Address field — Mattermost will find the rest.
This also means that if nodes are added to or removed from the cluster, Mattermost adapts automatically without requiring a configuration change.
Configure index replicas¶
In a cluster, Elasticsearch stores copies of each data shard (called replicas) on different nodes. This provides redundancy — if a node goes down, the data is still available on another node.
Mattermost provides three settings to control the number of replicas for each type of index. For a cluster with n data nodes, set the number of replicas for each index to n-1:
Channel Index Replicas (
ElasticsearchSettings.ChannelIndexReplicas)Post Index Replicas (
ElasticsearchSettings.PostIndexReplicas)User Index Replicas (
ElasticsearchSettings.UserIndexReplicas)
For example, in a three-node cluster, set all three values to 2.
These settings can be configured in the config.json file or using mmctl. See the enterprise search configuration settings documentation for details.
Important
If the number of data nodes in the cluster changes, these replica settings must be updated accordingly. After changing replica settings, purge and rebuild all indexes to apply the new configuration to existing indexes.
Set server connection details¶
(Optional) Enter Server Username used to access the enterprise search server.
(Optional) Enter Server Password associated with the username.
Set Enable Cluster Sniffing (Optional). Sniffing finds and connects to all data nodes in your cluster automatically.
Optional CA and client certificate configuration settings are available for use with basic authentication credentials or to replace them. See the Enterprise search configuration settings documentation for details.
Select Test Connection and then select Save. If the server connection is unsuccessful you won’t be able to save the configuration or enable searching with Elasticsearch or AWS OpenSearch.
Note
From Mattermost v11, enterprise search server connections are tested during Support Packet generation. Any connection errors encountered during Support Packet generation are automatically included in the packet to help diagnose configuration issues.
Build the post index of existing messages¶
Select Index Now. This process can take up to a few hours depending on the size of the post database and number of messages. The progress percentage can be seen as the index is created. To avoid downtime, set Enable Elasticsearch for search queries to false so that database search is available during the indexing process.
Enable enterprise search¶
Ensure bulk indexing is complete before enabling enterprise search, otherwise search results will be incomplete.
Set Enable Elasticsearch for search queries to true, and setting Enable Elasticsearch for autocomplete to true. Save your configuration updates and restart the Mattermost server.
Note
For high post volume deployments, we strongly encourage you to read and properly configure the Mattermost LiveIndexingBatchSize configuration setting.
Warning
For high post volume deployments, we also strongly recommend disabling Database Search once Elasticsearch or AWS OpenSearch is fully configured and running. The Mattermost Server will fall back on Database search if ElasticSearch or OpenSearch are unavailable which can lead to performance degradation on high post volume deployments.
Once the configuration is saved, new posts made to the database are automatically indexed on the Elasticsearch or AWS OpenSearch server.
Enterprise search limitations¶
Elasticsearch and AWS OpenSearch uses a standard selection of “stop words” to keep search results relevant. Results for the following words will not be returned: “a”, “an”, “and”, “are”, “as”, “at”, “be”, “but”, “by”, “for”, “if”, “in”, “into”, “is”, “it”, “no”, “not”, “of”, “on”, “or”, “such”, “that”, “the”, “their”, “then”, “there”, “these”, “they”, “this”, “to”, “was”, “will”, and “with”.
Searching stop words in quotes returns more results than just the searched terms (ticket).
Search results are limited to a user’s team and channel membership. This is enforced by the Mattermost server. The entities are indexed in Elasticsearch or AWS OpenSearch in a way that allows Mattermost to filter them when querying, so the Mattermost server narrows down the results on every Elasticsearch or AWS OpenSearch request applying those filters.