Как установить и настроить Typesense на VPS
Когда поиск по каталогу или базе статей через 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 ГБ SSD | 1-2 vCPU |
| 100 тыс. - 1 млн | 4 ГБ | 20-30 ГБ SSD | 2 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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →