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

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

MAATRIX

Elasticsearch по умолчанию ведёт себя так, будто у него в распоряжении весь дата-центр: пытается забрать половину оперативной памяти под heap, требует нестандартные лимиты ядра и падает с невнятной ошибкой, если что-то из этого не сошлось. На небольшом VPS это превращается в цикл «запустил — упало — погуглил — поправил один параметр — упало на другом». Разберём по шагам, как поставить Elasticsearch на чистый сервер, настроить его под реальные ресурсы и не оставить наружу открытый порт без пароля.

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

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

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

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

Elasticsearch — не самый лёгкий сервис. Для одного узла с тестовой или небольшой продакшн-нагрузкой закладывайте:

  • RAM: от 4 ГБ, комфортно — от 8 ГБ. Половина памяти уходит под JVM heap, вторая половина — под файловый кэш ОС, на котором реально держится скорость поиска.
  • Диск: SSD/NVMe обязательно. Индексы Elasticsearch — это множество мелких файлов сегментов, на HDD просадка по IOPS будет заметна сразу.
  • CPU: 2 ядра для старта достаточно, но индексация под нагрузкой упирается именно в CPU.
  • ОС: Ubuntu 24.04 или Debian 12 — обе поддерживаются официальным репозиторием Elastic.

Перед установкой поправьте два системных параметра, без которых Elasticsearch либо не стартует, либо предупреждает при каждом запуске:

# постоянный лимит для mmap-сегментов
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# лимиты на файловые дескрипторы и процессы для пользователя elasticsearch
sudo tee /etc/security/limits.d/elasticsearch.conf <<'EOF'
elasticsearch soft nofile 65536
elasticsearch hard nofile 65536
elasticsearch soft nproc 4096
elasticsearch hard nproc 4096
EOF

Если на сервере включён swap, его лучше либо отключить полностью (sudo swapoff -a), либо явно запретить Elasticsearch его использовать — об этом ниже, в разделе про JVM. Если сомневаетесь, нужен ли swap вообще на вашем тарифе, почитайте про правильный размер swap для VPS.

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

Ставить лучше не из snap и не через сторонние сборки, а из репозитория Elastic — так проще получать обновления безопасности. Импортируем GPG-ключ и добавляем репозиторий:

sudo apt update
sudo apt install -y apt-transport-https gnupg curl

curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | \
  sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] \
https://artifacts.elastic.co/packages/8.x/apt stable main" | \
  sudo tee /etc/apt/sources.list.d/elastic-8.x.list

sudo apt update
sudo apt install -y elasticsearch

Ветка 8.x в адресе репозитория — не конкретный релиз, а канал, из которого apt всегда подтянет актуальную минорную версию 8-й линейки. Проверить, что реально встало:

/usr/share/elasticsearch/bin/elasticsearch --version

При первой установке пакет сам сгенерирует TLS-сертификаты для внутреннего трафика узла и включит security по умолчанию — это избавляет от ручной настройки X-Pack, которая в старых версиях отнимала немало времени. Сразу после установки Elasticsearch ещё не запущен — это отдельный шаг ниже.

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

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

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

Базовая настройка elasticsearch.yml

Основной конфиг лежит в /etc/elasticsearch/elasticsearch.yml. На одном VPS без кластера правки минимальны:

cluster.name: my-app-cluster
node.name: node-1

# каталоги данных и логов (по умолчанию и так эти пути,
# но полезно явно понимать, где что лежит)
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

# слушать только локальный интерфейс, наружу не торчим
network.host: 127.0.0.1
http.port: 9200

# однонодовый кластер — без этого при старте
# узел будет ждать соседей и не поднимется как master
discovery.type: single-node

Ключевой момент для одиночного VPS — network.host: 127.0.0.1. Открывать 9200 порт напрямую в интернет не нужно почти никогда: даже с включённой аутентификацией это лишняя поверхность атаки. Доступ извне (для Kibana, для внешних клиентов) организуйте через обратный прокси с TLS — например, через nginx как reverse proxy, который дополнительно прикроет сервис базовой аутентификацией и ограничением по IP.

Если позже понадобится кластер из нескольких узлов, discovery.type: single-node меняется на discovery.seed_hosts со списком адресов остальных нод — но для одного сервера текущей настройки достаточно.

JVM heap и лимиты системы

Размер heap задаётся не в основном конфиге, а в отдельном файле — начиная с 7-й ветки Elasticsearch рекомендует класть свои настройки в /etc/elasticsearch/jvm.options.d/, не трогая системный jvm.options, чтобы не потерять правки при обновлении пакета:

sudo tee /etc/elasticsearch/jvm.options.d/heap.options <<'EOF'
-Xms2g
-Xmx2g
EOF

Базовое правило — heap не больше 50% физической RAM сервера и не больше ~31 ГБ (выше этого порога JVM теряет оптимизацию compressed oops на указателях, и рост heap перестаёт окупаться). Для VPS на 4 ГБ RAM ставьте -Xms1g -Xmx2g, для 8 ГБ — -Xms4g -Xmx4g. Значения Xms и Xmx всегда делайте одинаковыми — это исключает паузы на изменение размера heap во время работы.

Второе правило — heap не должен уходить в swap. Проверьте, что в основном elasticsearch.yml включена блокировка памяти:

bootstrap.memory_lock: true

И что systemd-юнит не режет это ограничение. В /etc/systemd/system/elasticsearch.service.d/override.conf (создайте через sudo systemctl edit elasticsearch):

[Service]
LimitMEMLOCK=infinity

После правки конфигов и юнита выполните sudo systemctl daemon-reload. Если bootstrap.memory_lock не сработал, в логе (/var/log/elasticsearch/<cluster-name>.log) появится предупреждение — стоит проверить это сразу: heap, ушедший в swap — источник многосекундных пауз при поиске под нагрузкой.

Безопасность: пароли, TLS и firewall

С 8-й ветки Elasticsearch включает security и генерирует самоподписанные сертификаты для транспортного слоя автоматически. Пароль суперпользователя elastic печатается в консоль один раз при установке — если пропустили, сбросьте его вручную:

sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic

Проверка, что аутентификация действительно требуется:

curl -k -u elastic:ВАШ_ПАРОЛЬ https://localhost:9200

Дальше — сетевой периметр. Даже при network.host: 127.0.0.1 не полагайтесь только на это: включите firewall и явно заблокируйте 9200/9300 для внешних адресов. Если ещё не настраивали firewall на сервере — см. настройку UFW на Ubuntu:

sudo ufw deny 9200/tcp
sudo ufw deny 9300/tcp
sudo ufw allow 443/tcp   # доступ только через reverse proxy с TLS

Если Elasticsearch нужно открыть наружу (для Kibana на другом сервере, для внешних интеграций), проксируйте трафик через nginx с реальным сертификатом от Let's Encrypt, а не самоподписанным. Как поднять автоматический выпуск и продление сертификата — в статье про Let's Encrypt SSL на VPS. Дополнительно ограничьте доступ по IP на уровне nginx или firewall — Elasticsearch API отдаёт достаточно данных, чтобы не выставлять его на весь интернет даже с паролем.

Проверка работы, systemd и первые запросы

Сервис управляется стандартно через systemd:

sudo systemctl enable --now elasticsearch   # автозапуск + старт сейчас
sudo systemctl status elasticsearch
sudo journalctl -u elasticsearch -f          # системные логи запуска
tail -f /var/log/elasticsearch/*.log         # логи самого Elasticsearch

Дадим кластеру подняться (на слабом VPS это может занять 20–40 секунд из-за инициализации JVM и security) и проверим статус:

curl -k -u elastic:ВАШ_ПАРОЛЬ https://localhost:9200/_cluster/health?pretty

В ответе интересует поле status: green или yellow — норма для одного узла (yellow означает, что реплики шардов негде разместить — это ожидаемо при одной ноде и не является проблемой). red — сигнал, что что-то пошло не так с уже существующими индексами.

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

curl -k -u elastic:ВАШ_ПАРОЛЬ -X PUT "https://localhost:9200/test-index" \
  -H 'Content-Type: application/json' -d '{
    "settings": { "number_of_shards": 1, "number_of_replicas": 0 }
  }'

curl -k -u elastic:ВАШ_ПАРОЛЬ -X POST "https://localhost:9200/test-index/_doc" \
  -H 'Content-Type: application/json' -d '{
    "title": "проверочный документ",
    "created": "2026-08-30"
  }'

curl -k -u elastic:ВАШ_ПАРОЛЬ "https://localhost:9200/test-index/_search?pretty"

Для одного узла number_of_replicas: 0 не косметика, а необходимость — с репликами по умолчанию (обычно 1) индекс так и останется в статусе yellow, ожидая вторую ноду, которой нет.

На этом этапе у вас поднят рабочий Elasticsearch. Дальше обычно добавляют Kibana для визуализации (отдельная установка, тот же репозиторий Elastic) и Logstash или Beats для сбора логов — вместе это и есть ELK/Elastic Stack, но каждый компонент разворачивается и настраивается отдельно.

Обслуживание: диск, мониторинг, снапшоты

Индексы Elasticsearch растут, и без присмотра сервер быстро упрётся в диск. У Elasticsearch есть встроенные пороги — watermark'и, после которых он сам начинает защищаться:

  • 85% заполнения диска — новые шарды перестают размещаться на этом узле;
  • 90% — существующие шарды с узла начинают переезжать;
  • 95% (flood-stage) — индексы принудительно переводятся в read-only, запись останавливается полностью.

Проверить текущее состояние:

curl -k -u elastic:ВАШ_ПАРОЛЬ "https://localhost:9200/_cat/allocation?v&pretty"

Если индекс неожиданно перестал принимать записи — в 9 случаях из 10 дело именно в этом флаге read-only от flood-stage watermark, а не в правах доступа. Снять его после освобождения места:

curl -k -u elastic:ВАШ_ПАРОЛЬ -X PUT "https://localhost:9200/_all/_settings" \
  -H 'Content-Type: application/json' -d '{"index.blocks.read_only_allow_delete": null}'

Чтобы не доводить до этого, настройте отдельный мониторинг заполнения диска на уровне ОС — например, по инструкции про мониторинг диска на VPS с алертом задолго до 85%. Для регулярной ротации старых индексов (логи, метрики) используйте Index Lifecycle Management (ILM) — политику, которая сама переносит старые индексы в холодный tier или удаляет их по возрасту без ручных cron-скриптов.

Для резервных копий Elasticsearch использует не архивацию файлов «на горячую» (это ломает целостность), а собственный механизм снапшотов в отдельный репозиторий — файловую систему, S3-совместимое хранилище и так далее:

curl -k -u elastic:ВАШ_ПАРОЛЬ -X PUT "https://localhost:9200/_snapshot/my_backup" \
  -H 'Content-Type: application/json' -d '{
    "type": "fs",
    "settings": { "location": "/mnt/backup/es-snapshots" }
  }'

curl -k -u elastic:ВАШ_ПАРОЛЬ -X PUT \
  "https://localhost:9200/_snapshot/my_backup/snapshot_$(date +%F)?wait_for_completion=true"

Путь в location должен быть заранее прописан в elasticsearch.yml через path.repo, иначе Elasticsearch откажется его использовать из соображений безопасности.

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

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

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

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

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

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

Elasticsearch не стартует и в логе ошибка про max virtual memory areas.

Не применился vm.max_map_count=262144 — проверьте sysctl vm.max_map_count, если значение не изменилось, убедитесь, что правка попала в /etc/sysctl.conf, а не в отдельный файл, который перезаписывается при обновлении ОС.

Сколько RAM реально нужно для продакшена, а не для теста?

Зависит от объёма данных и частоты запросов, но ориентир — не меньше 8 ГБ на узел для сколько-нибудь заметной нагрузки, из которых половина уйдёт под heap. Для больших объёмов логов лучше несколько узлов среднего размера, чем один гигантский.

Можно ли обойтись без security, если сервис доступен только с localhost?

Технически да, но не рекомендуется — если на сервере когда-нибудь появится ещё один сервис или контейнер с доступом к localhost, он получит Elasticsearch без пароля. Оставлять security включённым дешевле, чем потом разбираться, что утекло.

Kibana не может подключиться к Elasticsearch после установки.

Чаще всего дело в enrollment-токене — при security по умолчанию Kibana должна быть привязана к кластеру через elasticsearch-create-enrollment-token, а не просто указывать URL и пароль в конфиге вручную.

Elasticsearch — единственный вариант для поиска на своём сервере?

Нет, для более простых задач иногда достаточно лёгких альтернатив вроде Meilisearch или Typesense — они проще в настройке и заметно менее требовательны к ресурсам, но и возможностей аналитики у них меньше. Для смежного выбора между инструментами анализа логов см. сравнение Grafana и Kibana.

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

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

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