OpenSearch Installation and Configuration
OpenSearch is an Apache-licensed fork of Elasticsearch that provides full-text search, analytics, and observability capabilities without vendor lock-in. This guide covers deploying OpenSearch on Linux, setting up a cluster, managing indexes, configuring OpenSearch Dashboards, enabling the security plugin, and migrating from Elasticsearch.
Prerequisites
- Ubuntu 20.04+ or CentOS 8+ / Rocky Linux 8+
- Java 11+ (OpenSearch bundles its own JDK)
- 4 GB RAM minimum per node (8–16 GB for production)
- SSD storage for optimal index performance
- Root or sudo access
Installing OpenSearch
# Ubuntu/Debian
curl -o- https://artifacts.opensearch.org/publickeys/opensearch.pgp | sudo gpg --dearmor --batch --yes -o /usr/share/keyrings/opensearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/opensearch-keyring.gpg] https://artifacts.opensearch.org/releases/bundle/opensearch/2.x/apt stable main" \
| sudo tee /etc/apt/sources.list.d/opensearch-2.x.list
sudo apt-get update
# Set the initial admin password (required for OpenSearch 2.12+)
sudo OPENSEARCH_INITIAL_ADMIN_PASSWORD='YourStr0ngP@ssword!' apt-get install -y opensearch
# CentOS/Rocky
sudo rpm --import https://artifacts.opensearch.org/publickeys/opensearch.pgp
cat > /etc/yum.repos.d/opensearch-2.x.repo << 'EOF'
[opensearch-2.x-release]
name=OpenSearch 2.x Release
baseurl=https://artifacts.opensearch.org/releases/bundle/opensearch/2.x/yum
autorefresh=1
type=rpm-md
gpgcheck=1
gpgkey=https://artifacts.opensearch.org/publickeys/opensearch.pgp
priority=1
enabled=1
EOF
sudo OPENSEARCH_INITIAL_ADMIN_PASSWORD='YourStr0ngP@ssword!' dnf install -y opensearch
Configuring OpenSearch
# Edit the main config
sudo nano /etc/opensearch/opensearch.yml
Key settings for a single-node development setup:
# /etc/opensearch/opensearch.yml
cluster.name: my-opensearch-cluster
node.name: node-1
# Data and logs paths
path.data: /var/lib/opensearch
path.logs: /var/log/opensearch
# Network
network.host: 0.0.0.0
http.port: 9200
# Single-node discovery (dev only)
discovery.type: single-node
# Disable security for development (NOT for production)
plugins.security.disabled: true
Tune JVM memory (set to ~50% of available RAM, max 32 GB):
sudo nano /etc/opensearch/jvm.options
# Change:
-Xms4g
-Xmx4g
Set OS limits for OpenSearch:
# Increase virtual memory limit
sudo sysctl -w vm.max_map_count=262144
echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-opensearch.conf
# Increase file descriptor limits
cat >> /etc/security/limits.conf << 'EOF'
opensearch soft nofile 65536
opensearch hard nofile 65536
EOF
# Enable and start
sudo systemctl enable --now opensearch
sudo systemctl status opensearch
# Test
curl http://localhost:9200
Cluster Setup
For a 3-node production cluster, configure each node:
Node 1 (master + data):
# /etc/opensearch/opensearch.yml on node-1
cluster.name: prod-cluster
node.name: node-1
node.roles: [master, data, ingest]
network.host: 192.168.1.10
http.port: 9200
transport.port: 9300
# Cluster formation
cluster.initial_master_nodes:
- node-1
- node-2
- node-3
discovery.seed_hosts:
- 192.168.1.10:9300
- 192.168.1.11:9300
- 192.168.1.12:9300
Node 2 and 3 - same config but change node.name and network.host.
For dedicated master nodes (clusters > 10 nodes):
node.roles: [master] # No data role = master-eligible only
Index Management
# Create an index with settings
curl -X PUT http://localhost:9200/logs-2024 \
-H 'Content-Type: application/json' \
-d '{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.refresh_interval": "5s"
},
"mappings": {
"properties": {
"timestamp": {"type": "date"},
"level": {"type": "keyword"},
"message": {"type": "text", "analyzer": "standard"},
"service": {"type": "keyword"},
"duration_ms":{"type": "float"}
}
}
}'
# Index a document
curl -X POST http://localhost:9200/logs-2024/_doc \
-H 'Content-Type: application/json' \
-d '{"timestamp": "2024-01-15T12:00:00Z", "level": "ERROR", "message": "Connection refused", "service": "api"}'
# Search
curl -X GET http://localhost:9200/logs-2024/_search \
-H 'Content-Type: application/json' \
-d '{
"query": {
"bool": {
"must": [{"match": {"message": "connection"}}],
"filter": [
{"term": {"level": "ERROR"}},
{"range": {"timestamp": {"gte": "now-1d"}}}
]
}
},
"sort": [{"timestamp": "desc"}],
"size": 20
}'
# Create an index template for rolling logs
curl -X PUT http://localhost:9200/_index_template/logs-template \
-H 'Content-Type: application/json' \
-d '{
"index_patterns": ["logs-*"],
"template": {
"settings": {"number_of_shards": 2, "number_of_replicas": 1},
"mappings": {
"properties": {
"timestamp": {"type": "date"},
"level": {"type": "keyword"},
"message": {"type": "text"}
}
}
}
}'
Index State Management (ISM) - auto-rollover and delete old indexes:
curl -X PUT http://localhost:9200/_plugins/_ism/policies/logs-policy \
-H 'Content-Type: application/json' \
-d '{
"policy": {
"description": "Rollover after 50GB or 30 days, delete after 90 days",
"default_state": "hot",
"states": [
{
"name": "hot",
"actions": [{"rollover": {"min_size": "50gb", "min_index_age": "30d"}}],
"transitions": [{"state_name": "delete", "conditions": {"min_index_age": "90d"}}]
},
{
"name": "delete",
"actions": [{"delete": {}}],
"transitions": []
}
]
}
}'
Installing OpenSearch Dashboards
# Ubuntu/Debian
echo "deb [signed-by=/usr/share/keyrings/opensearch-keyring.gpg] https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/2.x/apt stable main" \
| sudo tee /etc/apt/sources.list.d/opensearch-dashboards-2.x.list
sudo apt-get update && sudo apt-get install -y opensearch-dashboards
# Configure
sudo nano /etc/opensearch-dashboards/opensearch_dashboards.yml
server.host: "0.0.0.0"
server.port: 5601
opensearch.hosts: ["https://localhost:9200"]
opensearch.username: "kibanaserver"
opensearch.password: "kibanaserver"
opensearch.ssl.verificationMode: none
sudo systemctl enable --now opensearch-dashboards
# Access at http://your-server:5601
Security Plugin Configuration
The security plugin is included by default. Initialize it:
# Run the security admin script after first start
cd /usr/share/opensearch/plugins/opensearch-security/tools
OPENSEARCH_JAVA_HOME=/usr/share/opensearch/jdk \
./securityadmin.sh \
-cd /etc/opensearch/opensearch-security/ \
-icl -nhnv \
-cacert /etc/opensearch/root-ca.pem \
-cert /etc/opensearch/kirk.pem \
-key /etc/opensearch/kirk-key.pem
Add a user in internal_users.yml:
# Hash the password
/usr/share/opensearch/plugins/opensearch-security/tools/hash.sh -p mypassword
# Edit internal_users.yml and add:
myuser:
hash: "$2y$12$hashedpassword..."
backend_roles:
- "readall"
Alerting and Anomaly Detection
Create an alert monitor via the API:
curl -X POST http://localhost:9200/_plugins/_alerting/monitors \
-H 'Content-Type: application/json' \
-d '{
"type": "monitor",
"name": "High Error Rate",
"enabled": true,
"schedule": {"period": {"interval": 5, "unit": "MINUTES"}},
"inputs": [{
"search": {
"indices": ["logs-*"],
"query": {
"size": 0,
"query": {
"bool": {
"filter": [
{"term": {"level": "ERROR"}},
{"range": {"timestamp": {"gte": "now-5m"}}}
]
}
},
"aggs": {"error_count": {"value_count": {"field": "level"}}}
}
}
}],
"triggers": [{
"name": "Error spike",
"severity": "1",
"condition": {"script": {"source": "ctx.results[0].aggregations.error_count.value > 100"}}
}]
}'
Troubleshooting
OpenSearch fails to start:
sudo journalctl -u opensearch -f
# Common: vm.max_map_count too low, or JVM heap too large
sudo sysctl vm.max_map_count
Cluster health is yellow or red:
curl http://localhost:9200/_cluster/health?pretty
# Yellow = unassigned replica shards (OK for single-node)
# Red = missing primary shards
# Check unassigned shards
curl http://localhost:9200/_cluster/allocation/explain?pretty
High disk usage:
curl http://localhost:9200/_cat/indices?v&s=store.size:desc
# Delete old indexes or enable ISM policy
Out of memory errors:
# Check JVM heap usage
curl http://localhost:9200/_nodes/stats/jvm?pretty | grep heap_used_percent
Conclusion
OpenSearch is a production-ready search and analytics platform that works as a drop-in replacement for Elasticsearch without licensing concerns. The built-in security plugin, ISM for index lifecycle management, and alerting capabilities make it suitable for log analytics, application search, and observability use cases. For production, deploy a minimum 3-node cluster with dedicated master nodes, configure ISM policies to manage index retention, and use the security plugin with TLS from day one.


