← Home · Downloads · Docs

Getting Started

Install the server, verify the OpenSearch handshake, create an index, index a document, and run your first full-text, vector and hybrid searches.

The Index Server speaks the OpenSearch 3.5 REST API, so if you know OpenSearch or Elasticsearch you already know how to drive it. It is a private, self-hosted full-text + vector search engine with a high-performance embedded vector engine — that runs entirely on your own infrastructure. Existing OpenSearch clients (opensearch-py, opensearch-java, the REST high-level client) connect unchanged.


1. Prerequisites

2. Install

One line on a Linux host installs the self-contained bundle (server binary + embedded engine + config) as a systemd service on port 9200:

curl -fsSL https://index-server.searchblox.com/install | sudo bash

The bootstrap downloads the tarball, unpacks it, and runs deploy/install-searchai-index.sh, which installs the binary and the engine library under /opt/searchai-index, writes a systemd unit (searchai-index), enables it, and waits for /health.

Prefer to do it by hand? Download a tarball from the downloads page, then:

tar xzf searchai-index-server-1.3.1-linux-amd64.tar.gz
cd searchai-index-server-1.3.1-linux-amd64
./run.sh                                   # foreground; data/ lives alongside
# or, as a systemd service:
sudo deploy/install-searchai-index.sh --port 9200

Set an API key before you expose it. Auth is off by default (blank server.api-key = trusted-network / behind-LB). For anything internet-facing, set server.api-key in conf/server.properties and front the port with a gateway. See production readiness.

3. Verify the server

The root handshake returns the OpenSearch version envelope; /health is the load-balancer probe:

curl http://<host>:9200/
# {"version":{"number":"3.5.0","distribution":"opensearch"}, ...}

curl http://<host>:9200/health
# {"status":"green"}

curl http://<host>:9200/_cluster/health
curl http://<host>:9200/_cat/indices?v

If you set an API key, pass it as HTTP basic auth (-u admin:YOUR_API_KEY) or a Bearer token, exactly as an OpenSearch client would.

4. Create an index

Create an index with an OpenSearch mapping. Text fields get BM25 full-text; add a knn_vector field for semantic/vector search:

curl -X PUT http://<host>:9200/docs -H 'Content-Type: application/json' -d '{
  "settings": { "index": { "knn": true } },
  "mappings": {
    "properties": {
      "title":  { "type": "text" },
      "body":   { "type": "text" },
      "tag":    { "type": "keyword" },
      "views":  { "type": "integer" },
      "created":{ "type": "date" },
      "embedding": { "type": "knn_vector", "dimension": 384 }
    }
  }
}'

5. Index a document

Index one document with _doc, or many with _bulk — the same bodies OpenSearch expects. Refresh to make writes searchable:

# single document
curl -X PUT http://<host>:9200/docs/_doc/1 -H 'Content-Type: application/json' -d '{
  "title": "Hello", "body": "the quick brown fox",
  "tag": "intro", "views": 42, "created": "2026-09-09"
}'

# bulk
curl -X POST http://<host>:9200/_bulk -H 'Content-Type: application/x-ndjson' --data-binary '
{"index":{"_index":"docs","_id":"2"}}
{"title":"Second","body":"a lazy dog sleeps","tag":"intro","views":7}
'

curl -X POST http://<host>:9200/docs/_refresh

Full-text (BM25):

curl -X POST http://<host>:9200/docs/_search -H 'Content-Type: application/json' -d '{
  "query": { "match": { "body": "quick fox" } }
}'

Structured filter + full-text (bool):

curl -X POST http://<host>:9200/docs/_search -H 'Content-Type: application/json' -d '{
  "query": { "bool": {
    "must":   [ { "match": { "body": "fox" } } ],
    "filter": [ { "term": { "tag": "intro" } },
                { "range": { "views": { "gte": 10 } } } ]
  } }
}'

kNN vector search:

curl -X POST http://<host>:9200/docs/_search -H 'Content-Type: application/json' -d '{
  "size": 10,
  "query": { "knn": { "embedding": { "vector": [0.12, 0.03, ...], "k": 10 } } }
}'

Hybrid (full-text + vector, fused with RRF):

curl -X POST http://<host>:9200/docs/_search -H 'Content-Type: application/json' -d '{
  "query": { "hybrid": { "queries": [
    { "match": { "body": "quick fox" } },
    { "knn": { "embedding": { "vector": [0.12, 0.03, ...], "k": 10 } } }
  ] } }
}'

Highlighting, _source filtering, sort, from/size, search_after and scroll all work as in OpenSearch. See the compatibility matrix for the full supported surface.

7. Aggregations & facets

The aggregation DSL powers facets — terms, metrics, histograms and ranges:

curl -X POST http://<host>:9200/docs/_search -H 'Content-Type: application/json' -d '{
  "size": 0,
  "aggs": {
    "by_tag":   { "terms": { "field": "tag" } },
    "avg_views":{ "avg":   { "field": "views" } },
    "over_time":{ "date_histogram": { "field": "created", "calendar_interval": "day" } }
  }
}'

8. Connect a client (opensearch-py)

from opensearchpy import OpenSearch

client = OpenSearch(
    hosts=[{"host": "<host>", "port": 9200}],
    http_auth=("admin", "YOUR_API_KEY"),   # omit if api-key is blank
    use_ssl=False,                          # True once TLS is configured
)

print(client.info())                        # OpenSearch 3.5 handshake
client.index(index="docs", body={"title": "hello", "body": "world"})
client.indices.refresh(index="docs")
print(client.search(index="docs", body={"query": {"match": {"body": "world"}}}))

opensearch-java and the REST high-level client work the same way; so does SearchBlox, which points at this server like any OpenSearch endpoint. Need the Elasticsearch 8.x clients instead? Set compat.flavor=elasticsearch in the config. Other vector-DB clients (Qdrant, Pinecone, Chroma, Algolia) can use the optional dialect listeners — see the dialect matrix.

9. Where everything lives

Next: the documentation hub (compatibility, dialects, backup, clustering, production readiness) and the downloads page.