Set up a production-ready Elasticsearch 8 cluster with dedicated master, data, and coordinating nodes for high availability, fault tolerance, and horizontal scalability across multiple servers.
Prerequisites
- Multiple servers with at least 4GB RAM each
- Root or sudo access on all nodes
- Network connectivity between cluster nodes
- Basic knowledge of Elasticsearch concepts
What this solves
A single Elasticsearch node creates a single point of failure and limits your search performance. This tutorial shows you how to configure a multi-node Elasticsearch 8 cluster with dedicated master-eligible nodes for cluster management, data nodes for indexing and storage, and coordinating nodes for client requests. You'll enable security features, monitoring, and automatic failover to ensure high availability and scalability for production workloads.
Prerequisites and cluster planning
Plan your cluster architecture
Design your cluster with dedicated node roles for optimal performance and resource utilization.
| Node Type | Role | Minimum Count | RAM Requirements |
|---|---|---|---|
| Master-eligible | Cluster management, metadata | 3 (odd number) | 4GB |
| Data nodes | Index and search operations | 2+ | 8GB+ |
| Coordinating | Load balancing, aggregations | 2+ | 4GB |
Prepare the servers
Ensure all nodes meet the prerequisites and have proper network connectivity.
sudo sysctl vm.max_map_count
Should be at least 262144
sudo sysctl -w vm.max_map_count=262144
echo 'vm.max_map_count=262144' | sudo tee -a /etc/sysctl.conf
Install Java and Elasticsearch on all nodes
Install the required Java runtime and Elasticsearch packages on each cluster node.
sudo apt update
sudo apt install -y openjdk-11-jdk wget gpg
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
sudo apt update
sudo apt install -y elasticsearch
Generate cluster certificates
Create SSL certificates for secure inter-node communication on your first master node.
sudo /usr/share/elasticsearch/bin/elasticsearch-certutil ca --pem --out /tmp/elastic-ca.zip
sudo unzip /tmp/elastic-ca.zip -d /tmp/
sudo /usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca-cert /tmp/ca/ca.crt --ca-key /tmp/ca/ca.key --pem --out /tmp/elastic-certificates.zip
sudo unzip /tmp/elastic-certificates.zip -d /tmp/
sudo mkdir -p /etc/elasticsearch/certs
sudo cp /tmp/ca/ca.crt /tmp/instance/instance.crt /tmp/instance/instance.key /etc/elasticsearch/certs/
sudo chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs/
sudo chmod -R 660 /etc/elasticsearch/certs/*
Configure master-eligible nodes
Configure the first master node
Set up the initial master node with cluster discovery and security settings.
cluster.name: production-cluster
node.name: master-node-1
node.roles: [master]
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 203.0.113.10
http.port: 9200
transport.port: 9300
Discovery settings
discovery.seed_hosts: ["203.0.113.10:9300", "203.0.113.11:9300", "203.0.113.12:9300"]
cluster.initial_master_nodes: ["master-node-1", "master-node-2", "master-node-3"]
Security configuration
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.certificate: certs/instance.crt
xpack.security.transport.ssl.key: certs/instance.key
xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.certificate: certs/instance.crt
xpack.security.http.ssl.key: certs/instance.key
xpack.security.http.ssl.certificate_authorities: certs/ca.crt
Monitoring
xpack.monitoring.collection.enabled: true
Configure additional master nodes
Copy certificates to other master nodes and configure them with unique names and IP addresses.
# Copy certificates to other master nodes
sudo scp -r /etc/elasticsearch/certs/ root@203.0.113.11:/etc/elasticsearch/
sudo scp -r /etc/elasticsearch/certs/ root@203.0.113.12:/etc/elasticsearch/
cluster.name: production-cluster
node.name: master-node-2
node.roles: [master]
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 203.0.113.11
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["203.0.113.10:9300", "203.0.113.11:9300", "203.0.113.12:9300"]
cluster.initial_master_nodes: ["master-node-1", "master-node-2", "master-node-3"]
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.certificate: certs/instance.crt
xpack.security.transport.ssl.key: certs/instance.key
xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.certificate: certs/instance.crt
xpack.security.http.ssl.key: certs/instance.key
xpack.security.http.ssl.certificate_authorities: certs/ca.crt
xpack.monitoring.collection.enabled: true
Start master nodes
Start the Elasticsearch service on all master nodes and enable automatic startup.
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch
sudo systemctl status elasticsearch
Set up built-in user passwords
Generate passwords for Elasticsearch built-in users on the first master node.
sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
Save the generated passwords securely
Record the elastic user password for cluster management
Configure data nodes and coordinating nodes
Configure data nodes
Set up dedicated data nodes for indexing and search operations with optimized heap settings.
cluster.name: production-cluster
node.name: data-node-1
node.roles: [data, data_content, data_hot]
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 203.0.113.20
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["203.0.113.10:9300", "203.0.113.11:9300", "203.0.113.12:9300"]
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.certificate: certs/instance.crt
xpack.security.transport.ssl.key: certs/instance.key
xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.certificate: certs/instance.crt
xpack.security.http.ssl.key: certs/instance.key
xpack.security.http.ssl.certificate_authorities: certs/ca.crt
Data node optimizations
indices.memory.index_buffer_size: 30%
indices.memory.min_index_buffer_size: 96mb
thread_pool.write.queue_size: 1000
Configure coordinating nodes
Set up coordinating-only nodes to handle client requests and distribute load across data nodes.
cluster.name: production-cluster
node.name: coord-node-1
node.roles: []
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 203.0.113.30
http.port: 9200
transport.port: 9300
discovery.seed_hosts: ["203.0.113.10:9300", "203.0.113.11:9300", "203.0.113.12:9300"]
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.certificate: certs/instance.crt
xpack.security.transport.ssl.key: certs/instance.key
xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.certificate: certs/instance.crt
xpack.security.http.ssl.key: certs/instance.key
xpack.security.http.ssl.certificate_authorities: certs/ca.crt
Coordinating node optimizations
thread_pool.search.queue_size: 2000
thread_pool.get.queue_size: 1000
Configure JVM heap settings for each node type
Optimize heap allocation based on node roles and available system memory.
# Master nodes - 4GB heap
-Xms4g
-Xmx4g
# Data nodes - 50% of available RAM, max 32GB
-Xms16g
-Xmx16g
# Coordinating nodes - 8GB heap
-Xms8g
-Xmx8g
Start all cluster nodes
Copy certificates to all remaining nodes and start the Elasticsearch service.
# Copy certificates to data and coordinating nodes
for node in 203.0.113.20 203.0.113.21 203.0.113.30 203.0.113.31; do
sudo scp -r /etc/elasticsearch/certs/ root@$node:/etc/elasticsearch/
ssh root@$node "chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs/"
ssh root@$node "chmod -R 660 /etc/elasticsearch/certs/*"
ssh root@$node "systemctl enable --now elasticsearch"
done
Enable cluster security and monitoring
Configure firewall rules
Allow Elasticsearch ports between cluster nodes while restricting external access.
sudo ufw allow from 203.0.113.0/24 to any port 9200
sudo ufw allow from 203.0.113.0/24 to any port 9300
Allow HTTPS API access from application servers
sudo ufw allow from 203.0.113.100/28 to any port 9200
Configure index templates and policies
Set up index lifecycle management and shard allocation policies for optimal cluster performance.
curl -k -u elastic:YOUR_ELASTIC_PASSWORD -X PUT "https://203.0.113.10:9200/_template/default_template" -H "Content-Type: application/json" -d '
{
"index_patterns": ["*"],
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1,
"index.routing.allocation.total_shards_per_node": 3
}
}'
Set up cluster-level shard allocation
Configure shard allocation awareness to distribute replicas across different nodes and availability zones.
curl -k -u elastic:YOUR_ELASTIC_PASSWORD -X PUT "https://203.0.113.10:9200/_cluster/settings" -H "Content-Type: application/json" -d '
{
"persistent": {
"cluster.routing.allocation.awareness.attributes": "node_type",
"cluster.routing.allocation.balance.shard": 0.50,
"cluster.routing.allocation.balance.index": 0.40,
"cluster.routing.allocation.balance.threshold": 1.2
}
}'
Enable audit logging
Configure security audit logging to track access and administrative operations.
# Security audit logging
xpack.security.audit.enabled: true
xpack.security.audit.logfile.events.include: [
"access_denied", "access_granted", "anonymous_access_denied",
"authentication_failed", "connection_denied", "tampered_request",
"run_as_denied", "run_as_granted", "security_config_change"
]
xpack.security.audit.logfile.events.exclude: ["access_granted"]
Verify your setup
Check cluster health, node roles, and security configuration to ensure everything is working correctly.
# Check cluster health
curl -k -u elastic:YOUR_ELASTIC_PASSWORD "https://203.0.113.10:9200/_cluster/health?pretty"
Verify all nodes joined the cluster
curl -k -u elastic:YOUR_ELASTIC_PASSWORD "https://203.0.113.10:9200/_cat/nodes?v&h=name,node.role,master,ip,heap.percent,ram.percent,cpu,load_1m,disk.used_percent"
Check cluster allocation
curl -k -u elastic:YOUR_ELASTIC_PASSWORD "https://203.0.113.10:9200/_cat/allocation?v"
Test index creation and search
curl -k -u elastic:YOUR_ELASTIC_PASSWORD -X PUT "https://203.0.113.30:9200/test-index/_doc/1" -H "Content-Type: application/json" -d '{"message": "cluster test", "timestamp": "2024-01-01T12:00:00"}'
curl -k -u elastic:YOUR_ELASTIC_PASSWORD "https://203.0.113.30:9200/test-index/_search?q=cluster"
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Nodes not joining cluster | Network connectivity or certificate issues | Check firewall rules and certificate permissions with ls -la /etc/elasticsearch/certs/ |
| Cluster status yellow | Replica shards cannot be allocated | Add more data nodes or reduce replica count with PUT /_settings {"number_of_replicas": 0} |
| High memory usage | JVM heap too large or fielddata cache | Set heap to 50% of RAM, monitor with GET /_nodes/stats/jvm |
| SSL connection failed | Certificate mismatch or expired | Regenerate certificates and ensure hostname matches certificate SAN |
| Split brain scenario | Network partition with inadequate master nodes | Ensure odd number of master-eligible nodes and proper discovery.seed_hosts |
Next steps
- Install and configure Elasticsearch 8 with security and performance optimization
- Optimize Elasticsearch 8 indexing performance for large datasets with bulk operations and memory tuning
- Setup nginx reverse proxy with SSL certificates and security hardening
- Configure Elasticsearch index lifecycle management with hot-warm-cold architecture
- Monitor Elasticsearch cluster with Prometheus and Grafana dashboards
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Global variables
CLUSTER_NAME="production-cluster"
NODE_NAME=""
NODE_ROLE=""
NODE_IP=""
DISCOVERY_HOSTS=""
MASTER_NODES=""
# Cleanup function for error handling
cleanup() {
echo -e "${RED}[ERROR] Installation failed. Cleaning up...${NC}"
systemctl stop elasticsearch 2>/dev/null || true
systemctl disable elasticsearch 2>/dev/null || true
rm -rf /tmp/elastic-*.zip /tmp/ca /tmp/instance 2>/dev/null || true
}
trap cleanup ERR
usage() {
cat << EOF
Usage: $0 [OPTIONS]
Configure Elasticsearch 8 cluster node
OPTIONS:
-n, --node-name Node name (required)
-r, --role Node role: master|data|coordinating (required)
-i, --ip Node IP address (required)
-d, --discovery Comma-separated discovery hosts (required)
-m, --masters Comma-separated initial master nodes (required for first master)
-c, --cluster Cluster name (default: production-cluster)
-h, --help Show this help
Example:
$0 -n master-node-1 -r master -i 203.0.113.10 -d "203.0.113.10:9300,203.0.113.11:9300" -m "master-node-1,master-node-2"
EOF
exit 1
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-n|--node-name) NODE_NAME="$2"; shift 2 ;;
-r|--role) NODE_ROLE="$2"; shift 2 ;;
-i|--ip) NODE_IP="$2"; shift 2 ;;
-d|--discovery) DISCOVERY_HOSTS="$2"; shift 2 ;;
-m|--masters) MASTER_NODES="$2"; shift 2 ;;
-c|--cluster) CLUSTER_NAME="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo -e "${RED}Unknown option: $1${NC}"; usage ;;
esac
done
# Validate required arguments
if [[ -z "$NODE_NAME" || -z "$NODE_ROLE" || -z "$NODE_IP" || -z "$DISCOVERY_HOSTS" ]]; then
echo -e "${RED}Missing required arguments${NC}"
usage
fi
if [[ "$NODE_ROLE" != "master" && "$NODE_ROLE" != "data" && "$NODE_ROLE" != "coordinating" ]]; then
echo -e "${RED}Invalid role. Must be: master, data, or coordinating${NC}"
exit 1
fi
# Check if running as root or with sudo
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root or with sudo${NC}"
exit 1
fi
echo -e "${BLUE}=== Elasticsearch 8 Cluster Setup ===${NC}"
# Detect distribution
echo -e "${BLUE}[1/9] Detecting distribution...${NC}"
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
JAVA_PACKAGE="openjdk-11-jdk"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
JAVA_PACKAGE="java-11-openjdk"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
JAVA_PACKAGE="java-11-openjdk"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
echo -e "${GREEN}Detected: $PRETTY_NAME${NC}"
else
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
# Configure system settings
echo -e "${BLUE}[2/9] Configuring system settings...${NC}"
current_max_map_count=$(sysctl -n vm.max_map_count)
if [[ $current_max_map_count -lt 262144 ]]; then
sysctl -w vm.max_map_count=262144
echo 'vm.max_map_count=262144' >> /etc/sysctl.conf
echo -e "${GREEN}Configured vm.max_map_count=262144${NC}"
else
echo -e "${GREEN}vm.max_map_count already configured${NC}"
fi
# Install Java and prerequisites
echo -e "${BLUE}[3/9] Installing Java and prerequisites...${NC}"
$PKG_UPDATE
$PKG_INSTALL $JAVA_PACKAGE wget gpg curl unzip
# Add Elasticsearch repository and install
echo -e "${BLUE}[4/9] Installing Elasticsearch...${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" > /etc/apt/sources.list.d/elastic-8.x.list
apt update
$PKG_INSTALL elasticsearch
else
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
cat > /etc/yum.repos.d/elasticsearch.repo << 'EOF'
[elasticsearch]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
$PKG_INSTALL elasticsearch
fi
# Generate certificates (only for first master node)
echo -e "${BLUE}[5/9] Setting up certificates...${NC}"
mkdir -p /etc/elasticsearch/certs
if [[ "$NODE_ROLE" == "master" && "$NODE_NAME" == *"1"* ]] && [[ -n "$MASTER_NODES" ]]; then
echo -e "${YELLOW}Generating certificates for cluster...${NC}"
/usr/share/elasticsearch/bin/elasticsearch-certutil ca --pem --out /tmp/elastic-ca.zip --silent
unzip -q /tmp/elastic-ca.zip -d /tmp/
/usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca-cert /tmp/ca/ca.crt --ca-key /tmp/ca/ca.key --pem --out /tmp/elastic-certificates.zip --silent
unzip -q /tmp/elastic-certificates.zip -d /tmp/
cp /tmp/ca/ca.crt /tmp/instance/instance.crt /tmp/instance/instance.key /etc/elasticsearch/certs/
chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs/
chmod -R 640 /etc/elasticsearch/certs/*
echo -e "${YELLOW}Copy these certificates to other nodes:${NC}"
echo -e "${YELLOW}/etc/elasticsearch/certs/ca.crt${NC}"
echo -e "${YELLOW}/etc/elasticsearch/certs/instance.crt${NC}"
echo -e "${YELLOW}/etc/elasticsearch/certs/instance.key${NC}"
else
echo -e "${YELLOW}Please copy certificates from the first master node to /etc/elasticsearch/certs/${NC}"
echo -e "${YELLOW}Press Enter when certificates are in place...${NC}"
read -r
chown -R elasticsearch:elasticsearch /etc/elasticsearch/certs/
chmod -R 640 /etc/elasticsearch/certs/*
fi
# Configure node role
echo -e "${BLUE}[6/9] Configuring node role...${NC}"
case "$NODE_ROLE" in
master)
NODE_ROLES="[master]"
;;
data)
NODE_ROLES="[data, data_content, data_hot, data_warm, data_cold]"
;;
coordinating)
NODE_ROLES="[]"
;;
esac
# Format discovery hosts and master nodes
FORMATTED_DISCOVERY=$(echo "$DISCOVERY_HOSTS" | sed 's/,/", "/g' | sed 's/^/"/' | sed 's/$/"/')
FORMATTED_MASTERS=""
if [[ -n "$MASTER_NODES" ]]; then
FORMATTED_MASTERS=$(echo "$MASTER_NODES" | sed 's/,/", "/g' | sed 's/^/"/' | sed 's/$/"/')
fi
# Create Elasticsearch configuration
echo -e "${BLUE}[7/9] Creating Elasticsearch configuration...${NC}"
cat > /etc/elasticsearch/elasticsearch.yml << EOF
# Cluster configuration
cluster.name: $CLUSTER_NAME
node.name: $NODE_NAME
node.roles: $NODE_ROLES
# Paths
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
# Network
network.host: $NODE_IP
http.port: 9200
transport.port: 9300
# Discovery
discovery.seed_hosts: [$FORMATTED_DISCOVERY]
EOF
if [[ -n "$MASTER_NODES" ]]; then
echo "cluster.initial_master_nodes: [$FORMATTED_MASTERS]" >> /etc/elasticsearch/elasticsearch.yml
fi
cat >> /etc/elasticsearch/elasticsearch.yml << 'EOF'
# Security
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.certificate: certs/instance.crt
xpack.security.transport.ssl.key: certs/instance.key
xpack.security.transport.ssl.certificate_authorities: certs/ca.crt
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.certificate: certs/instance.crt
xpack.security.http.ssl.key: certs/instance.key
xpack.security.http.ssl.certificate_authorities: certs/ca.crt
# Monitoring
xpack.monitoring.collection.enabled: true
# Performance
bootstrap.memory_lock: true
EOF
# Configure JVM heap size based on node role
echo -e "${BLUE}[8/9] Configuring JVM settings...${NC}"
TOTAL_RAM=$(free -m | awk 'NR==2{print $2}')
case "$NODE_ROLE" in
master)
HEAP_SIZE="2g"
;;
data)
HEAP_SIZE=$((TOTAL_RAM / 2 / 1024))g
;;
coordinating)
HEAP_SIZE="1g"
;;
esac
sed -i "s/-Xms1g/-Xms$HEAP_SIZE/" /etc/elasticsearch/jvm.options
sed -i "s/-Xmx1g/-Xmx$HEAP_SIZE/" /etc/elasticsearch/jvm.options
# Enable and start Elasticsearch
systemctl daemon-reload
systemctl enable elasticsearch
systemctl start elasticsearch
echo -e "${BLUE}[9/9] Verifying installation...${NC}"
sleep 10
# Check service status
if systemctl is-active --quiet elasticsearch; then
echo -e "${GREEN}✓ Elasticsearch service is running${NC}"
else
echo -e "${RED}✗ Elasticsearch service failed to start${NC}"
journalctl -u elasticsearch --no-pager -n 20
exit 1
fi
# Check if port is listening
if netstat -tlnp 2>/dev/null | grep -q ":9200.*LISTEN" || ss -tlnp 2>/dev/null | grep -q ":9200.*LISTEN"; then
echo -e "${GREEN}✓ Elasticsearch is listening on port 9200${NC}"
else
echo -e "${YELLOW}⚠ Elasticsearch port 9200 not yet available${NC}"
fi
echo -e "${GREEN}=== Installation Complete ===${NC}"
echo -e "${BLUE}Node: $NODE_NAME ($NODE_ROLE)${NC}"
echo -e "${BLUE}IP: $NODE_IP${NC}"
echo -e "${BLUE}Cluster: $CLUSTER_NAME${NC}"
echo ""
echo -e "${YELLOW}Next steps:${NC}"
echo -e "1. Configure other cluster nodes"
echo -e "2. Set up built-in user passwords: /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto"
echo -e "3. Configure firewall to allow ports 9200 and 9300"
echo -e "4. Test cluster health: curl -k https://$NODE_IP:9200/_cluster/health"
# Cleanup temporary files
rm -f /tmp/elastic-*.zip
rm -rf /tmp/ca /tmp/instance
Review the script before running. Execute with: bash install.sh