> ## Documentation Index
> Fetch the complete documentation index at: https://docs.controlplane.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Manticore Search

> Deploy Manticore Search on Control Plane using the Template Catalog. Covers configuration, volumes, scaling, and distributed Galera clustering with orchestrator API and S3 imports.

## Overview

Manticore Search is a high-performance, open-source search engine built for fast full-text search at scale. This template deploys a distributed Manticore Search cluster using Galera replication for high availability, with an orchestrator API for cluster management, a web UI for monitoring and operations, and support for zero-downtime data imports from AWS S3.

### What Gets Created

* **Manticore Search Workload** — A stateful Galera cluster with configurable replicas. Each replica runs a sidecar agent that handles cluster coordination, data imports, and recovery operations.
* **Orchestrator API Workload** — A REST API service for triggering imports, monitoring cluster health, initiating repairs, and managing backup and restore operations.
* **Orchestrator Cron Job** — A scheduled workload that runs import, health check, or repair operations on a configured schedule.
* **UI Workload** — A web dashboard for managing the cluster, monitoring replication, triggering operations, and visualizing queries.
* **Volume Set** — Persistent storage allocated per replica for Manticore data directories.
* **Shared Volume Set** — A shared volume accessible by all replicas and the orchestrator, used for slot-based import coordination.
* **Secrets** — Four opaque secrets: the Manticore `searchd` base configuration, the startup/shutdown handler script, the table schema registry used by the agent, and the agent bearer token. A K6 load test script secret is also created when load testing is enabled.
* **Identities & Policies** — Identities for the main cluster, orchestrator, and backup workloads. Policies grant `reveal` access to the configuration secrets, `exec` permissions on the orchestrator cron job, and `view` access to the Manticore workload for orchestration.
* **Backup Cron Job** (optional) — Scheduled logical backups of delta and full tables to an S3 bucket. Enabled when `orchestrator.backup.enabled: true`.
* **Domain** (optional) — Routes `/api/*` to the orchestrator API and all other traffic to the UI. Enabled when `domain.enabled: true`.
* **Load Test Workload** (optional) — A k6-based load test runner with a controller for automated scheduling. Enabled when `loadTest.enabled: true`.

<Note>
  This template does not create a GVC. You must deploy it into an existing GVC.
</Note>

## Prerequisites

This template requires an AWS S3 bucket for CSV source data and a Control Plane Cloud Account before installation.

### AWS S3 (Source Data)

1. Create an S3 bucket and upload your CSV source files. Set `buckets.sourceBucket` to the bucket name and `buckets.awsRegion` to its region.

2. If you do not have a Control Plane Cloud Account set up, follow the [Create a Cloud Account](https://docs.controlplane.com/guides/create-cloud-account) guide. Set `buckets.cloudAccountName` to the name of your Cloud Account.

3. Set `buckets.awsPolicyRefs` to the IAM policies granting S3 access. For read-only source access, use the AWS managed policy `aws::AmazonS3ReadOnlyAccess`. For custom policies, omit the `aws::` prefix.

### Agent Token

Generate a secure bearer token for internal cluster communication and set it in `orchestrator.agent.token`:

```bash theme={null}
openssl rand -base64 32
```

<Note>
  Anyone with network access to the UI can perform admin operations. Restrict external access using `orchestrator.ui.allowExternalAccess: false` or configure the domain firewall to limit access.
</Note>

### AWS S3 (Backup, Optional)

Only required if `orchestrator.backup.enabled: true`:

1. Create a separate S3 bucket for backups. Set `orchestrator.backup.s3Bucket` and `orchestrator.backup.s3Region`.

2. Create an IAM policy with the following permissions, replacing `YOUR_BUCKET_NAME`:

```json theme={null}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::YOUR_BUCKET_NAME",
                "arn:aws:s3:::YOUR_BUCKET_NAME/*"
            ]
        }
    ]
}
```

3. Set `orchestrator.backup.cloudAccountName` and `orchestrator.backup.s3Policy` to the name of your Cloud Account and the custom policy created above.

## Installation

To install, follow the instructions for your preferred method:

<CardGroup cols={2}>
  <Card title="UI" href="/template-catalog/install-manage/ui" icon="laptop">
    Browse, install, and manage templates visually
  </Card>

  <Card title="CLI" href="/template-catalog/install-manage/cli" icon="terminal">
    Manage templates from your terminal
  </Card>

  <Card title="Terraform" href="/template-catalog/install-manage/terraform" icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M77.941 44.5v36.836L46.324 62.918V26.082zm0 0" fill="#5c4ee5"/><path d="M81.41 81.336l31.633-18.418V26.082L81.41 44.5zm0 0" fill="#4040b2"/><path d="M11.242 42.36L42.86 60.776V23.941L11.242 5.523zm0 0M77.941 85.375L46.324 66.957v36.82l31.617 18.418zm0 0" fill="#5c4ee5"/></g></svg>}>
    Declare templates in your Terraform configurations
  </Card>

  <Card
    title="Pulumi"
    href="/template-catalog/install-manage/pulumi"
    icon={<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" id="Pulumi-Icon--Streamline-Svg-Logos" height="24" width="24">
    <desc>
        Pulumi Icon Streamline Icon: https://streamlinehq.com
    </desc>
    <path fill="#f26e7e" d="M4.683025 13.3318c0.869125 -0.5018 0.870575 -2.1264 0.003225 -3.62865s-2.27504 -2.313275 -3.1441725 -1.811475C0.672945 8.3935 0.6715 10.0181 1.53885 11.52035c0.86735 1.502275 2.27505 2.313275 3.144175 1.81145Zm0.0052 3.2167c0.86735 1.502275 0.865925 3.126875 -0.003225 3.628675 -0.86915 0.5018 -2.2768275 -0.309225 -3.144175 -1.81145 -0.8673525 -1.50225 -0.8659075 -3.126875 0.003225 -3.628675 0.8691325 -0.5018 2.276825 0.309225 3.144175 1.81145Zm5.922875 3.4243c0.86735 1.50225 0.8659 3.126775 -0.003225 3.62875 -0.869125 0.501775 -2.27685 -0.309325 -3.1442 -1.81155 -0.867325 -1.50225 -0.865875 -3.12685 0.00325 -3.628675 0.869125 -0.5018 2.276825 0.309225 3.144175 1.811475Zm-0.001925 -6.845275c0.86735 1.50225 0.8659 3.12685 -0.003225 3.628675 -0.869125 0.5018 -2.276825 -0.309225 -3.144175 -1.811475 -0.86735 -1.50225 -0.8659 -3.12685 0.003225 -3.62865 0.869125 -0.501825 2.276825 0.3092 3.144175 1.81145Z" stroke-width="0.25"></path>
    <path fill="#8a3391" d="M22.45775 11.524125c0.86725 -1.502225 0.865925 -3.12685 -0.003225 -3.62865 -0.869125 -0.501825 -2.276825 0.3092 -3.144175 1.811475 -0.86735 1.50225 -0.8659 3.126825 0.003225 3.62865 0.869125 0.501825 2.276825 -0.3092 3.144175 -1.811475Zm0.000175 3.2151c0.869075 0.5018 0.870625 2.1264 0.003225 3.62865 -0.86735 1.50225 -2.27505 2.313275 -3.144175 1.81145 -0.869125 -0.5018 -0.870575 -2.126425 -0.003225 -3.62865 0.86735 -1.50225 2.27505 -2.313275 3.144175 -1.81145ZM16.536225 18.157875c0.86915 0.501825 0.8706 2.126425 0.00325 3.628675 -0.86735 1.502125 -2.275075 2.313225 -3.1442 1.81145 -0.869125 -0.50175 -0.870575 -2.126425 -0.003225 -3.62865 0.867375 -1.502275 2.27505 -2.3133 3.144175 -1.811475Zm-0.003325 -6.843775c0.869125 0.5018 0.870575 2.126425 0.003225 3.628675s-2.27505 2.313275 -3.1442 1.811475c-0.869125 -0.501825 -0.870575 -2.126425 -0.003225 -3.628675 0.86735 -1.502275 2.27505 -2.313275 3.1442 -1.811475Z" stroke-width="0.25"></path>
    <path fill="#f7bf2a" d="M15.138225 2.06721c0 1.003615 -1.40625 1.817215 -3.14095 1.817215 -1.7347 0 -3.14095 -0.8136 -3.14095 -1.817215C8.856325 1.06359 10.262575 0.25 11.997275 0.25c1.7347 0 3.14095 0.81359 3.14095 1.81721ZM9.2166 5.482375c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172s1.40625 -1.817225 3.14095 -1.817225c1.7347 0 3.14095 0.8136 3.14095 1.817225Zm8.71005 1.8172c1.7347 0 3.14095 -0.813575 3.14095 -1.8172s-1.40625 -1.817225 -3.14095 -1.817225c-1.7347 0 -3.14095 0.8136 -3.14095 1.817225s1.40625 1.8172 3.14095 1.8172Zm-2.788425 1.605625c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172 0 -1.0036 1.40625 -1.8172 3.14095 -1.8172 1.7347 0 3.14095 0.8136 3.14095 1.8172Z" stroke-width="0.25"></path>
    </svg>}
  >
    Declare templates in your Pulumi programs
  </Card>
</CardGroup>

## Configuration

The default `values.yaml` for this template:

```yaml theme={null}
# =============================================================================
# AWS Cloud Account and S3 Configuration
# =============================================================================
buckets:
  cloudAccountName: my-cloud-account    # Name of your configured Cloud Account
  awsPolicyRefs:                        # IAM policies for S3 access
    - aws::AmazonS3ReadOnlyAccess       # Note: if using a custom policy, omit the aws:: prefix
  awsRegion: us-east-1                  # Region of your S3 bucket
  sourceBucket: my-bucket               # S3 bucket containing files to import

# =============================================================================
# Tables Configuration
# =============================================================================
tables:
  - name: addresses
    csvPath:
      - manticore-imports/addresses/data.csv
    config:
      haStrategy: noerrors
      agentRetryCount: 3
      clusterMain: false
      segmentCount: 1
      charsetTable: non_cont
      memLimit: 2G
      hasHeader: true
      secondaryIndexes: false
    schema:
      columns:
        - name: address_id
          type: attr_uint
        - name: street_number
          type: attr_uint
        - name: street_name
          type: field
        - name: city
          type: field
        - name: county
          type: field
        - name: state
          type: field
        - name: postal_code
          type: field
        - name: country
          type: field
        - name: latitude
          type: attr_float
        - name: longitude
          type: attr_float

# =============================================================================
# Manticore Search Configuration
# =============================================================================
manticore:
  image: manticoresearch/manticore:25.0.0
  clusterName: manticore          # Galera cluster name
  resources:
    cpu: 4
    memory: 8Gi
  volumeset:
    capacity: 200                 # GB per replica
  sharedVolumeset:
    capacity: 100                 # GB shared across replicas and orchestrator

  # minScale = replica count used by orchestrator for coordination
  autoscaling:
    minScale: 3
    maxScale: 4
    metric: rps                   # rps for stateful, cpu for standard
    target: 100
    scaleToZeroDelay: 300

  rolloutOptions:
    maxSurgeReplicas: 25%
    maxUnavailableReplicas: '0'
    minReadySeconds: 10
    scalingPolicy: OrderedReady
    terminationGracePeriodSeconds: 60

  # IMPORTANT: same-gvc required for Galera replication
  firewall:
    internalAccess:
      type: same-gvc
      workloads: []

# =============================================================================
# Orchestrator Configuration
# =============================================================================
orchestrator:
  version: v6.0.5
  image: ghcr.io/controlplane-com/manticore-orchestrator/manticore-cpln-api
  logLevel: debug                 # debug, info, warn, error
  resources:
    cpu: 1
    memory: 2Gi

  # Cron job settings
  schedule: "0 * * * *"           # Cron schedule (default = every hour)
  action: import                  # init, import, health, repair
  tableName: addresses            # Must match a name in tables[]
  suspend: true                   # Start suspended (trigger via UI/API)
  timeoutSeconds: 900             # Container timeout (default 15 minutes)
  importMemLimit: 2G              # Memory limit for import jobs
  activeDeadlineSeconds: 14400    # Max job runtime (default 4 hours)

  # Orchestrator API
  api:
    version: v6.0.5
    image: ghcr.io/controlplane-com/manticore-orchestrator/manticore-cpln-api
    logLevel: debug
    importPollInterval: 30s
    importPollTimeout: 2h
    resources:
      cpu: 0.25
      memory: 256Mi
    autoscaling:
      maxScale: 3
      minScale: 2
      metric: cpu
      target: 80

  # Agent sidecar
  agent:
    version: v6.0.5
    image: ghcr.io/controlplane-com/manticore-orchestrator/manticore-cpln-agent
    # REQUIRED: Generate with `openssl rand -base64 32`
    token: "6Gl5uO9KkKAh1u+ymoBW98WCtjTFpljuhpLdKb+tNAA="
    resources:
      cpu: 250m
      minCpu: 100m
      memory: 512Mi
      minMemory: 128Mi
    import:
      batchSize: 20000            # Rows per INSERT statement
    recovery:
      maxRetries: 5               # Retry attempts for cluster recovery
      initialBackoffSec: 5        # Initial delay between retries
      maxBackoffSec: 60           # Max backoff delay (exponential)

  # Web UI
  ui:
    version: v6.0.5
    image: ghcr.io/controlplane-com/manticore-orchestrator/manticore-cpln-ui
    resources:
      cpu: 0.25
      memory: 0.25Gi
    allowExternalAccess: true     # false = internal GVC access only
    autoscaling:
      maxScale: 2
      minScale: 1
      metric: cpu
      target: 80

  # Backup Configuration (Optional)
  backup:
    enabled: false
    version: v6.0.5
    image: ghcr.io/controlplane-com/manticore-orchestrator/manticore-cpln-backup
    cloudAccountName: my-backup-cloud-account
    s3Bucket: my-backup-bucket
    s3Policy:
      - my-backup-policy
    s3Region: us-east-1
    dataSet: addresses            # Data set to back up
    prefix: manticore-backups     # S3 prefix/folder for backups
    schedules:
      - {"table":"addresses","type":"delta","schedule":"0 2 * * *"}   # Daily at 2am UTC
      - {"table":"addresses","type":"main","schedule":"0 2 1 * *"}    # Monthly on 1st at 2am UTC
    activeDeadlineSeconds: 14400
    resources:
      cpu: 1
      memory: 1Gi

# =============================================================================
# Domain Configuration (Optional)
# =============================================================================
domain:
  enabled: false
  name: ""                        # FQDN, e.g., manticore.example.com
  dnsMode: cname                  # cname (subdomains) or ns (zone delegation)

# =============================================================================
# Load Testing Configuration (Optional)
# =============================================================================
loadTest:
  enabled: false
  image: grafana/k6:0.47.0
  resources:
    cpu: 0.5
    memory: 512Mi
  vus: 10                         # Virtual users
  duration: "5m"                  # Test duration (e.g., 30s, 5m, 1h)
  rps: null                       # Target RPS (null = unlimited)
  replicas: 1
  controller:
    image: alpine/curl
    schedule: ""                  # Cron expression (empty = manual only)
    testDurationBuffer: 60        # Seconds added to duration before scale-down
  target:
    port: 9308                    # Manticore HTTP API port
    endpoint: search              # "search" or "sql"
  query:
    index: addresses
    query:
      match:
        "*": "test"
    limit: 10
  thresholds:
    p95ResponseTime: 500          # ms
    errorRate: 0.01               # 1%
```

### S3 and Cloud Account

* `buckets.cloudAccountName` — Name of the Control Plane Cloud Account with AWS trust configured.
* `buckets.awsPolicyRefs` — IAM policies granting read access to the source S3 bucket. Use `aws::AmazonS3ReadOnlyAccess` for the AWS managed policy, or omit the `aws::` prefix for custom policies.
* `buckets.awsRegion` — AWS region of the source S3 bucket.
* `buckets.sourceBucket` — Name of the S3 bucket containing CSV files to import.

### Tables

Each entry in `tables` defines a searchable index imported from a CSV file.

* `name` — Table name used by Manticore and referenced by the orchestrator.
* `csvPath` — List of S3 paths (relative to `sourceBucket`) for the CSV source files. Multiple paths create a distributed multi-segment table.
* `config.haStrategy` — High-availability behavior when agents are unreachable (`noerrors` ignores unreachable agents).
* `config.agentRetryCount` — Number of retry attempts when an agent doesn't respond.
* `config.segmentCount` — Number of distributed segments for this table. Use more than 1 for very large datasets split across multiple CSVs.
* `config.memLimit` — Memory limit for the Manticore index (e.g., `2G`).
* `config.hasHeader` — Set to `true` if the CSV file includes a header row.
* `config.secondaryIndexes` — When `true`, enables secondary indexes on both the main and delta tables for this entry. Defaults to `false`.
* `schema.columns` — Column definitions. Each column has a `name` and a `type`.

**Supported column types:**

| Type             | Description                            |
| ---------------- | -------------------------------------- |
| `field`          | Full-text searchable string field      |
| `attr_uint`      | Unsigned integer attribute             |
| `attr_float`     | Float attribute                        |
| `attr_bigint`    | 64-bit integer attribute               |
| `attr_bool`      | Boolean attribute                      |
| `attr_string`    | Non-indexed string attribute           |
| `attr_json`      | JSON attribute                         |
| `attr_multi`     | Multi-value unsigned integer attribute |
| `attr_multi_64`  | Multi-value 64-bit integer attribute   |
| `attr_timestamp` | Unix timestamp attribute               |

### Manticore Cluster

* `manticore.clusterName` — Galera cluster name used for replication coordination.
* `manticore.resources` — CPU and memory for each Manticore replica.
* `manticore.volumeset.capacity` — Persistent storage per replica in GB.
* `manticore.sharedVolumeset.capacity` — Shared storage in GB, accessible by all replicas and the orchestrator for import slot coordination.
* `manticore.autoscaling.minScale` — Minimum replica count. This value is also used by the orchestrator to determine cluster quorum. It should match your intended fixed replica count.
* `manticore.autoscaling.maxScale` — Maximum replica count for autoscaling.

<Note>
  `manticore.firewall.internalAccess.type` must be set to `same-gvc`. Galera replication requires direct peer-to-peer communication between all replicas within the GVC.
</Note>

### Orchestrator

The orchestrator manages all cluster lifecycle operations including data imports, health checks, and repairs.

**Cron Job**

* `orchestrator.schedule` — Cron schedule for automated operations (default: every hour).
* `orchestrator.action` — Operation to run: `init` (initial cluster setup), `import` (load CSV data), `health` (check cluster state), or `repair` (fix split-brain issues).
* `orchestrator.tableName` — The table to target for the cron job. Must match a name in `tables`.
* `orchestrator.suspend` — When `true`, the cron job is created in a suspended state and must be triggered manually via the UI or CLI. Recommended for production.
* `orchestrator.timeoutSeconds` — Timeout for each cron container execution.
* `orchestrator.activeDeadlineSeconds` — Maximum total runtime for an import job before it is terminated.

**API**

* `orchestrator.api.importPollInterval` — How often the API checks import progress.
* `orchestrator.api.importPollTimeout` — Maximum time the API waits for an import to complete.
* `orchestrator.api.autoscaling` — Min/max replicas and CPU target for the orchestrator API.

**Agent Sidecar**

* `orchestrator.agent.token` — Bearer token securing all internal communication between the orchestrator and agent sidecars. **Generate with `openssl rand -base64 32` and change before deploying.**
* `orchestrator.agent.import.batchSize` — Number of rows per INSERT statement during imports (default: 20000).
* `orchestrator.agent.recovery` — Retry settings for Galera cluster recovery after a split-brain event.

**UI**

* `orchestrator.ui.allowExternalAccess` — When `true`, the UI is accessible from the internet. Set to `false` to restrict access to within the GVC.

### Backup (Optional)

Set `orchestrator.backup.enabled: true` to enable scheduled backups to S3.

* `orchestrator.backup.cloudAccountName` — Cloud Account with write access to the backup S3 bucket.
* `orchestrator.backup.s3Bucket` / `s3Region` — Backup bucket name and region.
* `orchestrator.backup.s3Policy` — Custom IAM policy name(s) granting write access to the backup bucket (see [Prerequisites](#prerequisites)).
* `orchestrator.backup.dataSet` — The table dataset to back up.
* `orchestrator.backup.prefix` — S3 folder prefix for backup archives.
* `orchestrator.backup.schedules` — List of backup schedules. Each entry specifies a `table`, a backup `type` (`delta` for incremental, `main` for full), and a `schedule` in cron format.

### Domain (Optional)

* `domain.enabled` — Enable or disable the domain resource.
* `domain.name` — Fully qualified domain name (e.g., `manticore.example.com`). Requires DNS configuration pointing to the GVC's load balancer.
* `domain.dnsMode` — DNS routing mode: `cname` for subdomain-based routing or `ns` for zone delegation.

When enabled, the domain routes `/api/*` to the orchestrator API and all other traffic to the UI.

### Load Testing (Optional)

* `loadTest.enabled` — Enable or disable the k6 load test workload.
* `loadTest.vus` — Number of virtual users.
* `loadTest.duration` — Total test duration (e.g., `30s`, `5m`, `1h`).
* `loadTest.rps` — Target requests per second (`null` = unlimited).
* `loadTest.target.endpoint` — Search endpoint to target: `search` (JSON body) or `sql`.
* `loadTest.thresholds.p95ResponseTime` — P95 response time threshold in milliseconds.
* `loadTest.thresholds.errorRate` — Maximum acceptable error rate (e.g., `0.01` = 1%).

## External References

<CardGroup cols={2}>
  <Card title="Manticore Search Documentation" icon="book" href="https://manual.manticoresearch.com/">
    Official Manticore Search documentation
  </Card>

  <Card title="Manticore Search GitHub" icon="github" href="https://github.com/manticoresoftware/manticoresearch">
    Manticore Search open-source repository
  </Card>

  <Card title="Cloud Accounts" icon="cloud" href="https://docs.controlplane.com/guides/create-cloud-account">
    Create a Control Plane Cloud Account for S3 access
  </Card>

  <Card title="Manticore Template" icon="github" href="https://github.com/controlplane-com/templates/tree/main/manticore">
    View the source files, default values, and chart definition
  </Card>
</CardGroup>
