# How to Configure Elasticsearch Indexing in OpenCTI: Complete Setup Guide

> Learn to configure Elasticsearch indexing in OpenCTI. Follow this guide to set up cluster URL, credentials, and advanced settings for optimal performance.

- Repository: [OpenCTI Platform/opencti](https://github.com/opencti-platform/opencti)
- Tags: how-to-guide
- Published: 2026-02-19

---

**To configure Elasticsearch indexing in OpenCTI, modify the `elasticsearch` section in [`opencti-platform/opencti-graphql/config/default.json`](https://github.com/OpenCTI-Platform/opencti/blob/main/opencti-platform/opencti-graphql/config/default.json) (or an overriding configuration file) to set the cluster URL, authentication credentials, index prefix, shard/replica counts, and rollover policies before starting the platform.**

OpenCTI stores all STIX-compatible data in an Elasticsearch or OpenSearch cluster, making proper indexing configuration critical for performance, scalability, and data retention. This guide explains how to configure Elasticsearch indexing in OpenCTI based on the source code implementation in the [OpenCTI-Platform/opencti](https://github.com/OpenCTI-Platform/opencti) repository.

## Elasticsearch Indexing Configuration File Location

All Elasticsearch indexing settings are read from **[`opencti-platform/opencti-graphql/config/default.json`](https://github.com/OpenCTI-Platform/opencti/blob/main/opencti-platform/opencti-graphql/config/default.json)**. You can override these defaults by providing a custom configuration file that merges with or replaces the default values.

### Core Configuration Parameters

The following table lists the key parameters that control how OpenCTI configures Elasticsearch indexing:

| Setting | Description | Default Value |
|---------|-------------|---------------|
| `elasticsearch:index_prefix` | Prefix for all OpenCTI indices (e.g., `opencti-*`) | `"opencti"` |
| `elasticsearch:url` | HTTP URL of the Elasticsearch node | `"http://localhost:9200"` |
| `elasticsearch:username` | Basic auth username | `null` |
| `elasticsearch:password` | Basic auth password | `null` |
| `elasticsearch:api_key` | API key for authentication | `null` |
| `elasticsearch:proxy` | HTTP proxy for the connection | `null` |
| `elasticsearch:ssl:ca` | Array of CA certificate paths | `[]` |
| `elasticsearch:ssl:ca_plain` | Base64-encoded CA certificate | `null` |
| `elasticsearch:ssl:reject_unauthorized` | Reject self-signed certificates | `true` |
| `elasticsearch:index_creation_pattern` | Suffix for new indices (rollover) | `"-000001"` |
| `elasticsearch:number_of_shards` | Primary shards per index | `1` |
| `elasticsearch:number_of_replicas` | Replica shards per index | `1` |
| `elasticsearch:max_primary_shard_size` | Rollover trigger size | `"50gb"` |
| `elasticsearch:max_docs` | Rollover trigger document count | `75000000` |
| `elasticsearch:max_result_window` | Maximum `from+size` pagination | `100000` |
| `elasticsearch:max_bulk_operations` | Bulk request size limit | `5000` |
| `elasticsearch:max_concurrency` | Concurrent request limit | `4` |

These values are accessed via the `conf` helper throughout the engine implementation.

## How to Configure the Elasticsearch Client Engine

When the platform starts, the `searchEngineInit()` function in **[`src/database/engine.ts`](https://github.com/OpenCTI-Platform/opencti/blob/main/src/database/engine.ts)** constructs the Elasticsearch client using your configuration.

### Client Initialization Code

The engine builds the client configuration object as follows:

```typescript
const elkSearchConfiguration = {
  node: conf.get('elasticsearch:url'),
  proxy: conf.get('elasticsearch:proxy') || null,
  auth: {
    username: conf.get('elasticsearch:username') || null,
    password: conf.get('elasticsearch:password') || null,
    apiKey: conf.get('elasticsearch:api_key') || null,
  },
  maxRetries: conf.get('elasticsearch:max_retries') || 3,
  requestTimeout: conf.get('elasticsearch:request_timeout') || 3600000,
  sniffOnStart: booleanConf('elasticsearch:sniff_on_start', false),
  ssl: { 
    ca, 
    rejectUnauthorized: booleanConf('elasticsearch:ssl:reject_unauthorized', true) 
  },
  tls: { 
    ca, 
    rejectUnauthorized: booleanConf('elasticsearch:ssl:reject_unauthorized', true) 
  },
};
engine = new ElkClient(elkSearchConfiguration);

```

If `engine_selector` is set to `opensearch`, the platform instantiates an OpenSearch client instead. The resulting `engine` instance is stored as a module-level variable and reused by all CRUD helpers such as `elRawIndex`, `elRawSearch`, and `elCreateIndex`.

## Index Templates and Lifecycle Management

OpenCTI uses index templates and Index Lifecycle Management (ILM) policies to ensure consistent mappings and automated rollover.

### Component Template: opencti-core-settings

The `updateCoreSettings()` function in [`src/database/engine.ts`](https://github.com/OpenCTI-Platform/opencti/blob/main/src/database/engine.ts) creates a component template named `opencti-core-settings` that defines:

- `max_result_window`, `number_of_shards`, and `number_of_replicas`
- A `string_normalizer` for keyword fields

### Index Template Generation

The `engineMappingGenerator()` function generates the full index template (`opencti-index-template`) from schema attribute definitions. This template is applied to every new index and includes the rollover alias for platforms newer than version 5.9.

### ILM Policy and Rollover Configuration

The `elCreateLifecyclePolicy()` function creates the `opencti-ilm-policy` with a hot phase that triggers rollover when either:

- Primary shard size exceeds `max_primary_shard_size` (default **50 GB**)
- Document count exceeds `max_docs` (default **75,000,000**)

## Index Creation and Naming Conventions

When a new entity type requires storage, OpenCTI calls `elCreateIndex(index, mappingProperties)` in [`src/database/engine.ts`](https://github.com/OpenCTI-Platform/opencti/blob/main/src/database/engine.ts). This function:

1. Ensures the component and index templates exist via `elCreateIndexTemplate`
2. Appends `elasticsearch:index_creation_pattern` (default `"-000001"`) to the index name
3. Executes a `PUT` request to Elasticsearch via `engine.indices.create`

All indices share the prefix defined by `elasticsearch:index_prefix` (default **`opencti`**), making it easy to identify platform indices using `elPlatformIndices()`.

## Updating Mappings and Schema Migrations

When the schema evolves, `elUpdateIndicesMappings()` executes automatically during startup or can be triggered manually. Located in [`src/database/engine.ts`](https://github.com/OpenCTI-Platform/opencti/blob/main/src/database/engine.ts), this function:

1. Regenerates the complete mapping via `engineMappingGenerator()`
2. Retrieves existing indices using `elPlatformIndices()`
3. Compares current mappings with expected mappings using `jsonpatch.compare`
4. Sends *add* operations only (no replacements) to each index via `indices.putMapping`

This incremental approach ensures **zero-downtime upgrades** when adding new fields.

## Practical Configuration Examples

### Minimal Custom Configuration

Create a file named [`config/custom.json`](https://github.com/OpenCTI-Platform/opencti/blob/main/config/custom.json) to override defaults:

```json
{
  "elasticsearch": {
    "url": "https://es.mycorp.com:9200",
    "username": "opencti",
    "password": "MySecretPassword",
    "ssl": {
      "reject_unauthorized": false
    },
    "index_prefix": "myorg",
    "number_of_shards": 3,
    "number_of_replicas": 2,
    "max_primary_shard_size": "30gb",
    "max_docs": 50000000,
    "index_creation_pattern": "-000001"
  }
}

```

Start the platform with your custom configuration:

```bash
docker-compose -f docker-compose.yml -f custom-compose.yml up

```

All indices will be prefixed with `myorg-*` instead of the default `opencti-*`.

### Force a Full Re-index After Schema Change

```bash

# 1. Validate the new schema mapping

node ./opencti-platform/opencti-graphql/script/script-generate-schema.js

# 2. Optional: Clean up stale relationships

node ./opencti-platform/opencti-graphql/script/script-clean-relations.js

# 3. Trigger the mapping update via GraphQL

curl -X POST http://localhost:4000/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"mutation { updateIndicesMappings }"}'

```

The `updateIndicesMappings` mutation invokes `elUpdateIndicesMappings()` and adds only missing fields without requiring downtime.

### Delete All OpenCTI Indices (Fresh Install)

Use this TypeScript snippet to purge all OpenCTI indices:

```typescript
import { elPlatformIndices, elDeleteIndex } from './src/database/engine';

async function deleteAll() {
  const indices = await elPlatformIndices();  // Lists all opencti-* indices
  for (const { index } of indices) {
    await elDeleteIndex(index);             // Drops alias and underlying index
    console.log(`Removed ${index}`);
  }
}

deleteAll();

```

## Summary

- **Configuration Location**: All Elasticsearch settings reside in [`opencti-platform/opencti-graphql/config/default.json`](https://github.com/OpenCTI-Platform/opencti/blob/main/opencti-platform/opencti-graphql/config/default.json) and are accessed via the `conf` helper.
- **Client Initialization**: The `searchEngineInit()` function in [`src/database/engine.ts`](https://github.com/OpenCTI-Platform/opencti/blob/main/src/database/engine.ts) constructs the Elasticsearch client using `url`, `auth`, and `ssl` parameters.
- **Index Management**: OpenCTI uses component templates (`opencti-core-settings`), index templates (`opencti-index-template`), and ILM policies (`opencti-ilm-policy`) to manage shards, replicas, and rollover triggers.
- **Schema Evolution**: The `elUpdateIndicesMappings()` function performs zero-downtime mapping updates by adding only new fields during platform upgrades.
- **Customization**: Override `index_prefix`, `number_of_shards`, `max_primary_shard_size`, and other parameters to tailor indexing performance to your infrastructure.

## Frequently Asked Questions

### Where does OpenCTI store its Elasticsearch configuration?

OpenCTI stores Elasticsearch configuration in **[`opencti-platform/opencti-graphql/config/default.json`](https://github.com/OpenCTI-Platform/opencti/blob/main/opencti-platform/opencti-graphql/config/default.json)**. The platform reads these settings at startup via the `conf` helper and uses them to initialize the client in [`src/database/engine.ts`](https://github.com/OpenCTI-Platform/opencti/blob/main/src/database/engine.ts). You can override defaults by providing a custom configuration file that merges with or replaces the default JSON.

### How do I change the index prefix in OpenCTI?

Set the `elasticsearch:index_prefix` value in your configuration file. For example, changing it from the default `"opencti"` to `"myorg"` causes all indices to be created as `myorg-*` instead of `opencti-*`. This is useful for multi-tenant environments or when running multiple OpenCTI instances against a single cluster.

### What is the default rollover policy for OpenCTI indices?

The default ILM policy (`opencti-ilm-policy`) rolls over indices when the primary shard size exceeds **50 GB** or when the document count exceeds **75,000,000**. You can customize these thresholds via `elasticsearch:max_primary_shard_size` and `elasticsearch:max_docs` in the configuration file.

### How do I update Elasticsearch mappings after upgrading OpenCTI?

OpenCTI automatically updates mappings during startup via the `elUpdateIndicesMappings()` function in [`src/database/engine.ts`](https://github.com/OpenCTI-Platform/opencti/blob/main/src/database/engine.ts). This function compares current mappings with the expected schema and adds only missing fields using `indices.putMapping`. To manually trigger this process, execute the GraphQL mutation `updateIndicesMappings` against the platform API.