MAATRIX / Блог / Typesense на Ubuntu 24.04: пошаговая установка

Typesense на Ubuntu 24.04: пошаговая установка

MAATRIX

Когда нужен поиск «как в Алгольи», но без подписки в долларах и без желания разбираться в JVM-настройках Elasticsearch, чаще всего выбор падает между Meilisearch и Typesense. Typesense выигрывает там, где важна строгая схема данных: у него типизированные поля, понятная работа с фасетами и геопоиском, и он честно говорит, если вы попытались отправить документ не по схеме. Здесь — установка с нуля на чистом VPS с Ubuntu 24.04: бинарник, systemd, первая коллекция, бэкап и вынос наружу через reverse proxy.

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

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

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

Что такое Typesense и когда он уместен

Typesense — это поисковый движок с открытым кодом (GPL-3.0), написанный на C++, ориентированный на низкую задержку и простоту эксплуатации. В отличие от Elasticsearch, он не требует Java и кластерной философии «сначала разберитесь с шардами» — для старта достаточно одного бинарника и одного конфига.

Ключевая особенность — типизированные схемы: перед тем как загружать документы, вы описываете коллекцию с полями и их типами (string, int32, float, bool, string[] и так далее). Это отличает его от Meilisearch, который проще настраивается «на автомате», но менее строг к структуре данных. Если у вас каталог товаров, объявления или документация с чёткими атрибутами — типизация скорее помогает, чем мешает: ошибки в данных всплывают на этапе индексации, а не в проде.

Из коробки Typesense умеет: полнотекстовый поиск с опечатко-устойчивостью (typo tolerance), фасетный поиск и фильтрацию по числовым/строковым полям, геопоиск по координатам, сортировку по нескольким полям и векторный поиск для гибридных сценариев.

Для небольшого и среднего проекта — интернет-магазина, справочника, блога с полнотекстовым поиском — хватит одного узла. Кластерная (highly-available) конфигурация с несколькими нодами существует, но в этой статье разбираем именно one-node установку, которая закрывает 90% реальных задач.

Требования к серверу и подготовка

Официальный бинарник Typesense — это один статически собранный исполняемый файл, поэтому требования к системе минимальны. Ориентируйтесь на объём данных, а не на «магические» цифры:

ПараметрМинимум для тестаКомфортно для прод-нагрузки
CPU1 vCPU2-4 vCPU
RAM1 ГБ4-8 ГБ
Диск10 ГБ SSDот 20 ГБ SSD, с запасом под рост индекса
ОСUbuntu 24.04 LTSUbuntu 24.04 LTS

Typesense держит индекс в оперативной памяти (с диском для персистентности через RocksDB), поэтому RAM — главный ограничитель, как и для Elasticsearch с OpenSearch. Точных цифр «сколько ГБ на миллион документов» не даю — сильно зависит от размера и числа полей, лучше замерить на реальных данных после первой загрузки.

Перед установкой обновите систему и создайте отдельного пользователя — Typesense не должен работать от root:

apt update && apt upgrade -y
adduser --system --group --home /var/lib/typesense typesense
mkdir -p /var/lib/typesense/data
chown -R typesense:typesense /var/lib/typesense

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

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

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

Установка Typesense из официального репозитория

Самый предсказуемый способ — установка через apt-репозиторий Typesense, а не сборка вручную. Так вы получаете обновления через штатный apt upgrade.

apt install -y curl gnupg apt-transport-https
curl -o /usr/share/keyrings/typesense-keyring.gpg https://apt.typesense.org/typesense.gpg
echo "deb [signed-by=/usr/share/keyrings/typesense-keyring.gpg] https://apt.typesense.org stable main" \
  | tee /etc/apt/sources.list.d/typesense.list
apt update
apt install -y typesense-server

Проверьте, что установилось:

typesense-server --version

Точную версию, которая встанет через apt install, специально не называю — на момент вашей установки в репозитории будет актуальный на тот день релиз, ориентируйтесь на вывод команды выше, а не на цифру из статьи. Если репозиторий недоступен, альтернатива — скачать .deb-пакет вручную со страницы релизов на GitHub проекта и поставить через dpkg -i, либо взять tar.gz-архив с бинарником для нужной архитектуры (amd64/arm64).

Конфигурация и первый запуск

Typesense конфигурируется через ini-файл или переменные окружения. Создайте конфиг:

mkdir -p /etc/typesense
nano /etc/typesense/typesense-server.ini

Содержимое:

[server]
api-address = 0.0.0.0
api-port = 8108
data-dir = /var/lib/typesense/data
api-key = замените-на-длинный-случайный-ключ
enable-cors = true
log-dir = /var/log/typesense

Сгенерировать случайный ключ можно так:

openssl rand -hex 32

api-key — это master-ключ с полными правами, храните его как секрет (в переменных окружения приложения, в менеджере паролей — не в git). Позже для клиентских приложений создадите отдельные ограниченные ключи через API, master-ключ в браузер отдавать нельзя.

Создайте директорию логов и systemd-юнит:

mkdir -p /var/log/typesense
chown -R typesense:typesense /var/log/typesense /etc/typesense

Пакет из репозитория обычно уже ставит unit-файл /lib/systemd/system/typesense-server.service, но проверьте, что он ссылается на ваш конфиг и корректного пользователя:

[Unit]
Description=Typesense
After=network.target

[Service]
Type=simple
User=typesense
Group=typesense
ExecStart=/opt/typesense-server/typesense-server --config=/etc/typesense/typesense-server.ini
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Запуск и автозагрузка:

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

Проверьте health-check:

curl http://localhost:8108/health

Ответ {"ok":true} означает, что сервис поднялся и слушает порт.

Firewall и защита порта

По умолчанию Typesense слушает на всех интерфейсах (0.0.0.0:8108) без TLS — нормально для внутреннего трафика, но открывать 8108 наружу нельзя: даже с api-key лучше не давать порт поисковой базы в публичный доступ напрямую.

Если у вас уже настроен ufw, закройте 8108 снаружи и разрешите доступ только с локального хоста и, при необходимости, с IP вашего бэкенда:

ufw deny 8108/tcp
ufw allow from 10.0.0.5 to any port 8108 proto tcp
ufw status verbose

Если firewall ещё не настроен — сделайте это отдельным шагом, здесь описана только часть, специфичная для Typesense: базовую настройку ufw на Ubuntu 24.04 разбирали в статье про ufw на Ubuntu 24.04.

Для публичного доступа к поиску (например, из фронтенда SPA) правильный путь — не открывать порт БД напрямую, а поставить перед ней reverse proxy с TLS и лимитом запросов, и отдавать клиенту не master-ключ, а ограниченный поисковый ключ (только на чтение, только по нужным коллекциям).

Reverse proxy и HTTPS

Чтобы обращаться к Typesense по https://search.example.com вместо голого IP:порт, поставьте nginx как reverse proxy перед сервисом. Общий алгоритм настройки nginx как reverse proxy с получением сертификата разобран в статье nginx как reverse proxy на Ubuntu 24.04 — здесь только специфика для Typesense.

Минимальный серверный блок:

server {
    listen 443 ssl http2;
    server_name search.example.com;

    ssl_certificate     /etc/letsencrypt/live/search.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/search.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8108;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 60s;
    }
}

Отдельно стоит добавить limit_req на уровне nginx, чтобы поисковый эндпоинт не стал вектором для DDoS через дорогие запросы — особенно если ключ, который вы отдаёте фронтенду, имеет права на поиск по всем коллекциям.

Создание коллекции и первые документы

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

curl -X POST 'http://localhost:8108/collections' \
  -H "X-TYPESENSE-API-KEY: ваш-api-key" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "products",
    "fields": [
      {"name": "title", "type": "string"},
      {"name": "description", "type": "string", "optional": true},
      {"name": "category", "type": "string", "facet": true},
      {"name": "price", "type": "float", "facet": true},
      {"name": "in_stock", "type": "bool", "facet": true},
      {"name": "tags", "type": "string[]", "facet": true, "optional": true}
    ],
    "default_sorting_field": "price"
  }'

Обратите внимание на facet: true — так вы сразу говорите движку, что по этому полю понадобится агрегация (фильтр «покажи все категории с количеством товаров»). default_sorting_field задаёт поле, по которому сортируются результаты, если запрос не указал сортировку явно — обязательно должно быть числовым.

Добавление документа:

curl -X POST 'http://localhost:8108/collections/products/documents' \
  -H "X-TYPESENSE-API-KEY: ваш-api-key" \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Механическая клавиатура TKL",
    "description": "Хот-своп, RGB, PBT-кейкапы",
    "category": "Периферия",
    "price": 89.99,
    "in_stock": true,
    "tags": ["клавиатура", "хот-своп"]
  }'

Если поле не соответствует объявленному типу, Typesense вернёт ошибку валидации сразу при индексации — это и есть та строгость, ради которой многие выбирают его вместо Meilisearch. Для массовой загрузки используется тот же эндпоинт с построчным JSON (.jsonl) через import.

Поиск:

curl -G 'http://localhost:8108/collections/products/documents/search' \
  -H "X-TYPESENSE-API-KEY: ваш-api-key" \
  --data-urlencode 'q=клавиатура' \
  --data-urlencode 'query_by=title,description' \
  --data-urlencode 'filter_by=in_stock:true' \
  --data-urlencode 'sort_by=price:asc'

Ключи доступа, бэкапы и обновление

Ограниченные ключи. Не отдавайте master-ключ во фронтенд. Создайте ключ только на поиск по нужной коллекции:

curl -X POST 'http://localhost:8108/keys' \
  -H "X-TYPESENSE-API-KEY: ваш-master-key" \
  -H 'Content-Type: application/json' \
  -d '{
    "description": "Search-only key for frontend",
    "actions": ["documents:search"],
    "collections": ["products"]
  }'

Такой ключ безопасен для браузера — он не может ни изменить схему, ни удалить документы.

Бэкап. Данные лежат в data-dir (у нас — /var/lib/typesense/data), там же snapshot-механизм:

curl -X POST "http://localhost:8108/operations/snapshot?snapshot_path=/var/lib/typesense/snapshots/$(date +%F)" \
  -H "X-TYPESENSE-API-KEY: ваш-api-key"

Папку со снапшотом дальше копируйте на удалённое хранилище любым инструментом бэкапа, который уже используете — rsync, restic и так далее. Восстановление — это запуск сервиса с data-dir, указывающим на распакованный снапшот.

Обновление. Раз это apt-пакет — обновление штатное:

apt update && apt upgrade -y typesense-server
systemctl restart typesense-server

Перед мажорным апгрейдом на проде всё же стоит сначала сделать снапшот и проверить apply на копии данных — так, как вы поступили бы с любой базой.

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

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

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

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

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

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

Чем Typesense принципиально отличается от Meilisearch?

Главное — типизированные схемы: Typesense требует явно описать поля и их типы перед индексацией и ругается на несоответствия, тогда как Meilisearch чаще определяет типы автоматически. Обе базы быстрые и просты в установке; выбор — вопрос того, нужна ли вам строгость схемы. Подробный разбор установки альтернативы — в статье про Meilisearch на Ubuntu 24.04.

Нужен ли Typesense вместо Elasticsearch/OpenSearch?

Если вам не нужны сложные аналитические агрегации, ELK-стек логов или огромные многошардовые кластеры — Typesense и OpenSearch решают разные по масштабу задачи. Для полнотекстового поиска на сайте или в приложении Typesense обычно проще в эксплуатации и требует меньше памяти на старте; для логов и аналитики уместнее OpenSearch.

Сколько памяти закладывать под рост индекса?

Единой формулы нет — зависит от числа документов, длины текстовых полей и количества фасетных полей. Практический подход: загрузите репрезентативную выборку данных, посмотрите фактическое потребление RAM процессом typesense-server, и закладывайте запас минимум в 1.5-2 раза от этого значения на рост.

Можно ли обойтись без reverse proxy и TLS, если Typesense используется только с бэкенда?

Да, если Typesense никогда не вызывается напрямую из браузера, а только с вашего backend-сервера в той же приватной сети — можно ограничиться firewall-правилом, разрешающим доступ только с IP бэкенда, без внешнего HTTPS-эндпоинта.

Как перенести Typesense на более мощный сервер без потери данных?

Сделайте snapshot, скопируйте директорию снапшота на новый сервер, установите тот же (или более новый) Typesense, укажите data-dir на скопированные данные и запустите сервис — репликация версии данных обратно совместима в пределах актуальных релизов.

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

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

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