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

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

MAATRIX

Когда поиск по каталогу или базе статей через LIKE '%...%' в PostgreSQL начинает тормозить и не прощает ни одной опечатки, а поднимать Elasticsearch ради одного индекса из полумиллиона документов откровенно избыточно, разумная середина — Typesense. Это открытый поисковый движок на C++, который ставится одной командой, требует явной типизированной схемы вместо угадывания полей «на лету» и отвечает на запросы с опечатками из коробки. Ниже — установка с нуля на VPS: от выбора сервера до первой коллекции, поиска и бэкапов.

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

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

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

Что такое Typesense и чем он отличается от альтернатив

Typesense решает ту же задачу, что Meilisearch и Elasticsearch — быстрый полнотекстовый поиск с ранжированием по релевантности — но с двумя принципиальными отличиями от соседей по нише.

Во-первых, схема коллекции здесь строгая: перед загрузкой документов вы явно описываете каждое поле и его тип (string, int32, float, bool, string[], geopoint, object, auto). Это чуть больше кода на старте по сравнению с Meilisearch, который выводит схему из первого же загруженного документа, зато меньше сюрпризов в проде: опечатка в названии поля или неожиданный тип значения отлетает ошибкой при загрузке, а не тихо ломает индекс.

Во-вторых, Typesense держит рабочие структуры индекса в оперативной памяти ради скорости отклика, а на диск (через RocksDB) пишет для персистентности и восстановления после перезапуска. Из этого следует практический вывод для sizing: памяти нужно закладывать примерно вровень с объёмом проиндексированных данных, а не с расчётом «в среднем хватит немного» — в отличие от решений с диск-ориентированным индексом вроде LMDB у Meilisearch.

Если задача — не пользовательский поиск по сайту или каталогу, а агрегации по логам и метрикам в духе ELK, там уместнее OpenSearch. Если хочется максимально нулевой конфигурации и автоматической схемы — присмотритесь к Meilisearch. Typesense — золотая середина: чуть больше явности при описании данных в обмен на предсказуемость и скорость.

Выбор VPS под Typesense

Поскольку индекс живёт в памяти, RAM — главный параметр при выборе конфигурации, а не диск, как для многих других СУБД:

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

Точный коэффициент «памяти на документ» сильно зависит от числа и длины индексируемых полей, поэтому ориентируйтесь на собственные замеры после загрузки реального датасета, а не на универсальную формулу. Для прод-нагрузки лучше держать Typesense на отдельном VPS: при массовой переиндексации он активно грузит и CPU, и диск, и вы не хотите, чтобы в этот момент тормозило основное приложение.

Для отказоустойчивости Typesense умеет работать кластером из нечётного числа узлов (обычно 3) через протокол Raft, но настройка кластера — отдельная большая тема за пределами этой статьи. Для типового проекта на старте вполне достаточно одного узла с регулярными бэкапами.

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

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

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

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

Официальный способ — deb-пакет, который сам разворачивает systemd-юнит и конфиг. Актуальную версию и ссылку на нужный пакет смотрите на странице релизов dl.typesense.org/releases — она обновляется регулярно, поэтому не полагайтесь на цифру версии из чужих статей:

TYPESENSE_VERSION=$(curl -s https://api.github.com/repos/typesense/typesense/releases/latest | grep -oP '"tag_name":\s*"v\K[^"]+')
curl -O "https://dl.typesense.org/releases/${TYPESENSE_VERSION}/typesense-server-${TYPESENSE_VERSION}-amd64.deb"
sudo apt install ./typesense-server-${TYPESENSE_VERSION}-amd64.deb

Пакет создаёт пользователя typesense, каталог данных /var/lib/typesense, конфиг /etc/typesense/typesense-server.ini и systemd-сервис typesense-server. Если предпочитаете контейнеры — тот же результат даёт официальный образ:

docker run -d --name typesense \
  -p 127.0.0.1:8108:8108 \
  -v /var/lib/typesense:/data \
  typesense/typesense:latest \
  --data-dir /data --api-key=ВАШ_КЛЮЧ --enable-cors

Разница только в способе управления процессом — общий разбор подходов есть в статье про Docker Compose для продакшена.

Конфигурация, API-ключ и запуск

Отредактируйте /etc/typesense/typesense-server.ini:

[server]
api-key = сгенерируйте_длинный_случайный_ключ
data-dir = /var/lib/typesense
api-port = 8108
listen-address = 127.0.0.1
enable-cors = true

Сгенерировать ключ можно так же, как для любого другого сервиса:

openssl rand -hex 32

Обратите внимание на listen-address = 127.0.0.1 — сервис не должен торчать в интернет напрямую, доступ пойдёт только через reverse proxy. Запускаем и проверяем:

sudo systemctl daemon-reload
sudo systemctl enable --now typesense-server
sudo systemctl status typesense-server

curl http://127.0.0.1:8108/health

Эндпоинт /health не требует авторизации и отдаёт {"ok":true} — удобно для внешнего uptime-мониторинга. Все остальные запросы без заголовка X-TYPESENSE-API-KEY получат 401.

Nginx как reverse proxy и SSL

Если Nginx на сервере ещё не настроен, сначала пройдите установку Nginx как reverse proxy на VPS — здесь только специфика Typesense. Конфиг /etc/nginx/sites-available/search.example.com:

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

    location / {
        proxy_pass http://127.0.0.1:8108;
        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;

        # массовый импорт документов шлёт крупные тела
        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. Порт 8108 при этом слушает только localhost, но не помешает явно закрыть его на фаерволе — если UFW ещё не настроен, вот пошаговая установка и настройка UFW. Сам мастер-ключ из конфига держите отдельно от клиентского кода: для фронтенда генерируются отдельные ограниченные ключи через /keys — с указанием конкретных actions (например, только documents:search) и списка коллекций, к которым ключ имеет доступ.

Типизированные схемы: коллекция, документы, поиск

Создаём коллекцию — тип каждого поля указывается явно, а default_sorting_field задаёт поле, по которому Typesense сортирует результаты при равной релевантности:

curl -X POST 'https://search.example.com/collections' \
  -H "X-TYPESENSE-API-KEY: $API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
    "name": "products",
    "fields": [
      {"name": "name", "type": "string"},
      {"name": "category", "type": "string", "facet": true},
      {"name": "price", "type": "float"},
      {"name": "in_stock", "type": "bool"}
    ],
    "default_sorting_field": "price"
  }'

Загрузка документов — форматом JSONL через bulk-import (пригодится и для первичной заливки, и для регулярного обновления через action=upsert):

cat > products.jsonl << 'EOF'
{"id": "1", "name": "Клавиатура механическая", "category": "periferiya", "price": 4990, "in_stock": true}
{"id": "2", "name": "Мышь беспроводная", "category": "periferiya", "price": 1490, "in_stock": true}
EOF

curl -X POST 'https://search.example.com/collections/products/documents/import?action=upsert' \
  -H "X-TYPESENSE-API-KEY: $API_KEY" \
  -H 'Content-Type: text/plain' \
  --data-binary @products.jsonl

Поиск с опечаткой — параметр query_by обязателен и указывает, по каким полям искать:

curl -G 'https://search.example.com/collections/products/documents/search' \
  -H "X-TYPESENSE-API-KEY: $SEARCH_KEY" \
  --data-urlencode 'q=клавиотура' \
  --data-urlencode 'query_by=name' \
  --data-urlencode 'filter_by=category:=periferiya' \
  --data-urlencode 'sort_by=price:asc' \
  --data-urlencode 'facet_by=category'

Запрос со словом «клавиотура» всё равно найдёт «Клавиатура механическая» — движок допускает опечатки по умолчанию (параметр num_typos, по умолчанию до двух ошибок на слово, настраивается на лету в самом запросе). В ответе вместе с найденными документами придёт блок facet_counts по полю category — готовый материал для фильтров в интерфейсе каталога.

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

Данные Typesense живут в каталоге data-dir, но копировать его «на живую» рискованно — консистентность не гарантирована. Используйте встроенный снапшот через API:

curl -X POST "http://127.0.0.1:8108/operations/snapshot?snapshot_path=/var/backups/typesense/$(date +%F)" \
  -H "X-TYPESENSE-API-KEY: $API_KEY"

Команда создаёт консистентный снимок RocksDB прямо на диске по указанному пути — дальше эту папку можно спокойно копировать штатным бэкап-инструментом на внешнее хранилище, например связкой с уже настроенным BorgBackup, добавив путь снапшота в список архивируемых директорий по расписанию.

Перед обновлением версии всегда снимайте свежий снапшот и сверяйтесь с release notes на GitHub — формат хранения между мажорными версиями иногда меняется несовместимо. Штатный путь обновления:

sudo systemctl stop typesense-server
sudo apt install ./typesense-server-НОВАЯ_ВЕРСИЯ-amd64.deb
sudo systemctl start typesense-server
sudo systemctl status typesense-server

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

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

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

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

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

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

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

Чем Typesense принципиально отличается от Meilisearch, если задачи похожие?

Главное — строгая типизированная схема вместо автоматического вывода полей и хранение рабочего индекса в памяти для скорости. Это делает поведение предсказуемее на старте, но требует чуть больше explicit-конфигурации и больше RAM на тот же объём данных.

Можно ли обойтись без Nginx и SSL, если Typesense используется только бэкендом того же сервера?

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

Что будет, если загрузить документ с полем неправильного типа?

Import вернёт ошибку по конкретной строке JSONL, а не молча испортит индекс — это осознанный компромисс строгой схемы: чуть больше кода на обработку ошибок при загрузке взамен предсказуемости данных в проде.

Обязательно ли указывать default_sorting_field при создании коллекции?

Технически нет, если вы всегда сортируете по релевантности (_text_match) в самом запросе. Но для многих сценариев (например, сортировка каталога по цене по умолчанию) поле нужно, и лучше решить это на этапе проектирования схемы, а не переделывать коллекцию с нуля.

Сколько памяти реально нужно на миллион документов?

Зависит от числа и длины индексируемых полей и от использования facet-полей — универсальной цифры нет. Стартуйте с оценки из таблицы выше, смотрите фактическое потребление через systemctl status или htop под реальными данными и увеличивайте объём VPS по факту, а не заранее с большим запасом.

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

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

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