Kituwa IT · Self-hosting guides

Install Meilisearch with Docker Compose

Self-hosted typo-tolerant search engine

searchtypo tolerantAPI

Meilisearch is a search-as-you-type engine that's genuinely easy to run. It handles typo tolerance, ranking, faceting, filters and synonyms out of the box, has a drop-in JavaScript SDK, and returns results in a few milliseconds on a few hundred thousand documents.

Category
Dev & data
License
MIT (core)
Needs
Nothing
Image
getmeili/meilisearch

What it is

Drop a JSON document into an index and it becomes searchable within a second. It's opinionated in the good way: the ranking rules work sensibly out of the box, so you get usable search without a relevance-tuning project. Restrict it with a master key for writes and a search-only key for the frontend.

Before you start

  • Meilisearch must not be exposed directly to the internet. A search key grants read access to an index, and an open instance is scraped within days. Put it behind a reverse proxy with auth.
  • The master key grants full control including reindexing. Generate it explicitly, then never put it in frontend code.
  • There's no built-in auth. A search-only API key is a capability, not a user identity — it's safe to ship in a browser, and anyone who has it can read that index.

1 — Write the compose file

Command / configuration
services:
  meilisearch:
    image: getmeili/meilisearch:v1.12
    container_name: meilisearch
    restart: unless-stopped
    ports:
      - "127.0.0.1:7700:7700"
    environment:
      MEILI_ENV: production
      MEILI_MASTER_KEY: CHANGE_ME_master_key_32_chars_min
      MEILI_NO_ANALYTICS: "true"
      MEILI_DB_PATH: /meili_data
    volumes:
      - ./data.ms:/meili_data
    healthcheck:
      test: ["CMD", "curl", "-fs", "http://localhost:7700/health"]
      interval: 30s
      timeout: 5s
      retries: 3
    ulimits:
      nofile:
        soft: 65536
        hard: 65536

The ulimits block is not decoration. Without a high nofile, Meilisearch hits the descriptor limit under a decent number of documents and starts returning errors that look like corruption.

2 — Start it

Command / configuration
mkdir -p ~/services/meilisearch
cd ~/services/meilisearch
docker compose up -d
curl -s http://127.0.0.1:7700/health | jq

A healthy instance answers {"status":"available"}.

3 — First-run setup

  1. Add an index and set its primary key: curl -X POST http://127.0.0.1:7700/indexes -H "Authorization: Bearer CHANGE_ME_master_key_32_chars_min" -H "Content-Type: application/json" -d '{"uid":"books","primaryKey":"id"}'
  2. Load documents: curl -X POST http://127.0.0.1:7700/indexes/books/documents -H "Authorization: Bearer CHANGE_ME" --data-binary @books.json
  3. Mark settings as searchable/filterable/sortable. Meilisearch indexes all fields by default, which is rarely what you want once you hit real data — filterable fields in particular are needed before you can filter on them.
  4. Create a search-only key scoped to that one index with actions: ["search"] and no indexes restriction beyond it. That key is safe in a browser bundle.
  5. Test typo tolerance by searching a deliberately misspelled word. If it returns nothing, your searchable attributes are wrong, not the engine.

4 — Query it

Command / configuration
# the widget UI, for a sanity check
open http://127.0.0.1:7700

# a real query
curl -s -X POST "http://127.0.0.1:7700/indexes/books/search" \
  -H "Authorization: Bearer SEARCH_ONLY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q":"hikari","limit":5,"attributesToHighlight":["title"]}' | jq
Indexing is asynchronousMeilisearch returns a task for every document update. Poll /tasks or watch the task status before assuming a document is searchable. This trips up everyone exactly once.

Help when you need it

Want help getting this running?

We can help with a supported Linux host, application setup, migration or troubleshooting. Contact us to confirm the software, scope and scheduling before ordering.

Related guides

← Browse all 30 guides · Back to top