MAATRIX / Блог / Как установить и настроить Meilisearch на VPS

Как установить и настроить Meilisearch на VPS

MAATRIX

Когда встроенный LIKE '%...%' в PostgreSQL или MySQL перестаёт справляться с поиском по каталогу товаров, статьям блога или базе клиентов, первая мысль — поднять Elasticsearch. И тут же упереться в то, что ему нужно 2-4 ГБ памяти только на JVM, отдельный кластер и неделя на изучение DSL-запросов. Meilisearch решает ту же задачу — быстрый полнотекстовый поиск с устойчивостью к опечаткам — но ставится за пять минут на скромный VPS и настраивается через понятный REST API. Ниже — установка с нуля: от выбора сервера до первого проиндексированного каталога и бэкапов.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Зачем Meilisearch и какой сервер под него выбрать

Meilisearch написан на Rust, хранит индекс в отдельной embedded-базе (LMDB) и не требует JVM, Java-хипа или отдельного узла под кластеризацию — для 90% задач малого и среднего проекта хватает одного процесса. Из коробки он даёт:

  • нечувствительность к опечаткам (типографический поиск на основе расстояния Левенштейна);
  • фасетный поиск и фильтрацию по атрибутам;
  • ранжирование по релевантности без ручной настройки скоринга;
  • ответ на запрос обычно укладывается в единицы-десятки миллисекунд на небольших коллекциях — точные цифры зависят от объёма данных и железа, ориентируйтесь на собственные замеры, а не на маркетинговые цифры.

Для сравнения с более тяжёлыми альтернативами на базе Lucene есть отдельный разбор — установка OpenSearch на VPS: если нужны сложные агрегации, логи в духе ELK-стека или уже используется Elasticsearch-совместимый клиент, это может быть более уместным выбором. Meilisearch же — про быстрый поиск по сайту, каталогу, документации, CRM.

По ресурсам ориентируйтесь так:

Объём документовRAMДискCPU
до 100 тыс. записей1-2 ГБ10-20 ГБ SSD1-2 vCPU
100 тыс. - 1 млн4 ГБ40-60 ГБ SSD2-4 vCPU
1 млн+8 ГБ и вышепо объёму данных ×2-34+ vCPU

Индекс весит заметно больше исходных данных (за счёт структур для типо-устойчивого поиска), поэтому диск закладывайте с запасом в 2-3 раза от сырого объёма документов. Для прод-нагрузки лучше держать поиск на отдельном VPS, а не подселять к основному приложению — так не потеряете производительность сайта при переиндексации большого каталога.

Установка Meilisearch на Ubuntu 24.04

Официальный установочный скрипт кладёт готовый бинарник — это самый простой путь для systemd-сервиса:

curl -L https://install.meilisearch.com | sh
sudo install -m 755 ./meilisearch /usr/local/bin/meilisearch
meilisearch --version

Создайте отдельного пользователя и каталоги под данные и конфиг — не запускайте сервис от root:

sudo useradd -r -s /bin/false meilisearch
sudo mkdir -p /var/lib/meilisearch/data.ms /etc/meilisearch
sudo chown -R meilisearch:meilisearch /var/lib/meilisearch

Сгенерируйте мастер-ключ — без него в production-режиме Meilisearch вообще не запустится, и это правильно: незащищённый поиск, торчащий наружу, значит, что любой сможет читать и переписывать ваш индекс:

openssl rand -base64 48 | tr -d '\n' | sudo tee /etc/meilisearch/master.key
sudo chmod 600 /etc/meilisearch/master.key
sudo chown meilisearch:meilisearch /etc/meilisearch/master.key

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Systemd-сервис и базовая конфигурация

Опишите юнит /etc/systemd/system/meilisearch.service:

[Unit]
Description=Meilisearch
After=network.target

[Service]
Type=simple
User=meilisearch
Group=meilisearch
EnvironmentFile=/etc/meilisearch/meilisearch.env
ExecStart=/usr/local/bin/meilisearch \
  --db-path /var/lib/meilisearch/data.ms \
  --http-addr 127.0.0.1:7700 \
  --env production
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Файл окружения /etc/meilisearch/meilisearch.env:

MEILI_MASTER_KEY=вставьте_сгенерированный_ключ
MEILI_ENV=production

HTTP-адрес привязан к 127.0.0.1 — наружу Meilisearch торчать не будет, доступ пойдёт только через reverse proxy на следующем шаге. Даже с мастер-ключом голый сервис в интернете — лишняя точка атаки и повод для сканеров портов.

Запускаем и проверяем:

sudo systemctl daemon-reload
sudo systemctl enable --now meilisearch
sudo systemctl status meilisearch

curl -H "Authorization: Bearer $(sudo cat /etc/meilisearch/master.key)" \
  http://127.0.0.1:7700/health

Ответ {"status":"available"} значит, что сервис поднялся и ключ работает. Тот же процесс можно запустить и в Docker вместо systemd — образ getmeili/meilisearch с теми же переменными окружения, разница только в способе управления процессом; общий разбор подходов есть в статье про продакшен-развёртывание на Ubuntu 24.04.

Nginx как reverse proxy и SSL

Открывать 7700 порт напрямую в интернет не нужно — заведите поддомен и проксируйте через Nginx, добавив TLS. Если Nginx на сервере ещё не настроен, сначала пройдите установку Nginx как reverse proxy на VPS — там разобрана база, здесь только специфика Meilisearch.

Конфиг /etc/nginx/sites-available/search.example.com:

server {
    listen 80;
    server_name search.example.com;

    location / {
        proxy_pass http://127.0.0.1:7700;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # у больших batch-запросов на индексацию бывают крупные тела
        client_max_body_size 100m;
    }
}
sudo ln -s /etc/nginx/sites-available/search.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d search.example.com

Certbot сам перепишет конфиг на listen 443 ssl и добавит редирект с 80-го порта. С этого момента поиск снаружи доступен только по HTTPS, и без ключа API каждый запрос получит 401. Отдельно закройте на фаерволе прямой доступ к 7700 извне — если UFW ещё не настроен, вот пошаговая установка и настройка UFW.

Ключи API и модель доступа

Мастер-ключ — это ключ от всего: создание индексов, удаление данных, управление другими ключами. Использовать его в клиентском JS-коде нельзя. Вместо этого создайте два ограниченных ключа: один для поиска (публичный, read-only), второй для индексации (серверный, write в конкретные индексы).

MASTER_KEY=$(sudo cat /etc/meilisearch/master.key)

# ключ только для поиска, привязанный к конкретному индексу
curl -X POST 'https://search.example.com/keys' \
  -H "Authorization: Bearer $MASTER_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
    "description": "Search-only key for products index",
    "actions": ["search"],
    "indexes": ["products"],
    "expiresAt": null
  }'

# ключ для серверной индексации
curl -X POST 'https://search.example.com/keys' \
  -H "Authorization: Bearer $MASTER_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
    "description": "Indexing key for products",
    "actions": ["documents.add", "documents.delete", "settings.update"],
    "indexes": ["products"],
    "expiresAt": null
  }'

Оба ключа приходят в ответе — сохраните сразу, повторно значение не показывается, только пересоздание. Search-key безопасно класть во фронтенд-код: он даёт только чтение того индекса, к которому привязан.

Первый индекс: загрузка данных и тюнинг поиска

Создаём индекс и грузим документы (JSON-массив с уникальным полем id):

curl -X POST 'https://search.example.com/indexes' \
  -H "Authorization: Bearer $MASTER_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"uid": "products", "primaryKey": "id"}'

curl -X POST 'https://search.example.com/indexes/products/documents' \
  -H "Authorization: Bearer $MASTER_KEY" \
  -H 'Content-Type: application/json' \
  --data '[
    {"id": 1, "name": "Клавиатура механическая", "category": "periferiya", "price": 4990},
    {"id": 2, "name": "Мышь беспроводная", "category": "periferiya", "price": 1490}
  ]'

Настройте, по каким полям искать, а по каким — фильтровать и сортировать:

curl -X PATCH 'https://search.example.com/indexes/products/settings' \
  -H "Authorization: Bearer $MASTER_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
    "searchableAttributes": ["name", "category"],
    "filterableAttributes": ["category", "price"],
    "sortableAttributes": ["price"],
    "typoTolerance": {"enabled": true, "minWordSizeForTypos": {"oneTypo": 4, "twoTypos": 8}}
  }'

Пробуем поиск с опечаткой:

curl -X POST 'https://search.example.com/indexes/products/search' \
  -H "Authorization: Bearer $SEARCH_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"q": "клавиотура", "filter": "category = periferiya", "sort": ["price:asc"]}'

Запрос с опечаткой в слове «клавиатура» всё равно найдёт нужный товар — это и есть основное преимущество перед LIKE-поиском. Дополнительно настройте синонимы (/settings/synonyms) и стоп-слова (/settings/stop-words) — это заметно улучшает релевантность для отраслевого жаргона и брендов, которые движок сам не распознает как синонимичные.

Бэкапы, обновление и мониторинг

Meilisearch хранит данные в одном каталоге (data.ms), но простое копирование файлов «на живую» не гарантирует консистентность — используйте встроенный механизм снапшотов или дампов.

Снапшоты — быстрый бинарный бэкап, включаются флагом при старте:

# добавить в ExecStart юнита
--schedule-snapshot 3600 --snapshot-dir /var/backups/meilisearch

Дампы — более переносимый формат (JSON), полезен при миграции на новую версию или между серверами:

curl -X POST 'https://search.example.com/dumps' \
  -H "Authorization: Bearer $MASTER_KEY"
# следите за статусом задачи через /tasks

Для регулярного копирования файлов снапшотов на внешнее хранилище подойдёт связка с уже настроенным бэкап-инструментом — например, если на сервере есть BorgBackup, просто добавьте /var/backups/meilisearch в список путей для архивации по расписанию.

Перед обновлением версии всегда делайте дамп — формат data.ms между мажорными версиями иногда меняется несовместимо, и штатный путь обновления — снять дамп на старой версии, поставить новый бинарник, импортировать дамп заново:

sudo systemctl stop meilisearch
sudo install -m 755 ./meilisearch-new /usr/local/bin/meilisearch
# добавить --import-dump /path/to/dump.dump в ExecStart на один запуск
sudo systemctl start meilisearch

Из мониторинга минимально достаточно: systemctl status meilisearch в связке с алертом на падение сервиса, отслеживание свободного места на диске (индекс растёт быстрее, чем кажется) и периодический curl на /health из внешнего скрипта — сам эндпоинт не требует авторизации и годится для простого uptime-чека.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Meilisearch подходит для логов и метрик как Elasticsearch?

Нет. Он заточен под пользовательский полнотекстовый поиск (сайт, каталог, документация), а не под агрегацию временных рядов и логов — для этого возьмите OpenSearch или связку Loki/Prometheus.

Можно ли обойтись без reverse proxy и SSL?

Да, если Meilisearch общается только с бэкендом на том же сервере по 127.0.0.1. Но если к поиску напрямую обращается браузер пользователя, HTTPS обязателен — иначе ключ API уйдёт в открытом виде.

Что будет, если забыть про MEILI_MASTER_KEY в production-режиме?

Сервис откажется стартовать и явно напишет в логе, что ключ обязателен — это защита по умолчанию, а не баг.

Сколько памяти нужно на 500 тысяч документов?

Точная цифра зависит от размера документов и числа searchable-полей. Стартуйте с 4 ГБ RAM, смотрите на потребление через htop под реальной нагрузкой и увеличивайте объём, если видите постоянный своп.

Нужен ли отдельный сервер под Meilisearch?

Для небольших проектов можно держать на одном VPS с приложением, но переиндексация большого каталога грузит CPU и диск — если сайт при этом тормозит, выносите поиск отдельно.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →