Как установить и настроить NATS на VPS
Когда микросервисам нужно обмениваться сообщениями, первая мысль — поставить Kafka или RabbitMQ. Но для 3-10 сервисов это избыточно: Kafka требует ZooKeeper (или KRaft-кластер), RabbitMQ тянет Erlang VM и Management-плагин, и оба съедают гигабайты памяти на VPS, где каждый мегабайт на счету. NATS решает ту же задачу — pub/sub, request/reply, очереди — одним статическим бинарником на Go, который стартует за секунду и держит десятки тысяч сообщений в секунду на самом скромном тарифе. Ниже — рабочая установка на чистый VPS: от бинарника до JetStream с персистентностью и TLS.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Установка NATS Server на VPS
NATS не входит в стандартные репозитории Ubuntu/Debian, поэтому ставим бинарник напрямую — это официальный и самый предсказуемый способ. Понадобится VPS с 1 vCPU / 1-2 ГБ RAM для старта — этого достаточно для нескольких тысяч сообщений в секунду при небольшой нагрузке.
Установочный скрипт NATS Inc. ставит nats-server в /usr/local/bin:
curl -sf https://binaries.nats.dev/nats-io/nats-server/v2@latest | sh
sudo mv nats-server /usr/local/bin/
nats-server --version
Если скрипт недоступен (иногда блокируется на VPS в РФ), скачайте релиз вручную с GitHub-страницы проекта nats-io/nats-server под свою архитектуру (amd64/arm64), распакуйте tar.gz и положите бинарник в /usr/local/bin.
Отдельно ставим CLI-клиент nats — им будем проверять публикацию и подписку:
curl -sf https://binaries.nats.dev/nats-io/natscli/nats@latest | sh
sudo mv nats /usr/local/bin/
Создаём пользователя и каталоги, чтобы сервер не работал под root:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin nats
sudo mkdir -p /etc/nats /var/lib/nats/jetstream /var/log/nats
sudo chown -R nats:nats /var/lib/nats /var/log/nats
Для теста хватит и Docker-варианта (docker run -p 4222:4222 nats:2.10-alpine), но в проде systemd-сервис с нативным бинарником проще диагностировать и обновлять — покажу оба пути ниже.
Настройка nats-server.conf
Вся конфигурация NATS — один файл. Начнём с рабочего минимума под одиночный узел с аутентификацией и лимитами:
# /etc/nats/nats-server.conf
server_name: nats-vps-01
listen: 0.0.0.0:4222
http_port: 8222
max_connections: 5000
max_payload: 4MB
max_pending: 64MB
authorization {
user: app
password: "$2a$11$XyZ...сгенерированный_bcrypt_хэш"
timeout: 2
}
logfile: "/var/log/nats/nats-server.log"
log_size_limit: 100MB
max_traced_msg_len: 0
Пароль не храните в открытом виде — генерируйте bcrypt-хэш самим сервером:
nats-server --bcrypt 'my-strong-password'
Результат подставьте в password. Порт 8222 — это HTTP-эндпоинт мониторинга (/varz, /connz, /subz), он не для клиентских подключений, но по умолчанию отвечает всем — закрываем его файрволом позже.
Если сервисов несколько и им не нужно видеть чужой трафик, используйте accounts — встроенную мультитенантность NATS:
accounts {
ORDERS: {
users: [ { user: orders_svc, password: "$2a$11$..." } ]
}
BILLING: {
users: [ { user: billing_svc, password: "$2a$11$..." } ]
}
}
Каждый аккаунт получает изолированное пространство subject'ов — сервис из ORDERS физически не сможет подписаться на темы BILLING, даже если знает их имена.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверЗапуск через systemd
Юнит для нативного бинарника:
# /etc/systemd/system/nats.service
[Unit]
Description=NATS Server
After=network.target
[Service]
Type=simple
User=nats
Group=nats
ExecStart=/usr/local/bin/nats-server -c /etc/nats/nats-server.conf
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
LimitNOFILE важен: под нагрузкой каждое подключение — это файловый дескриптор, а дефолтные 1024 в Ubuntu кончатся быстрее, чем вы ожидаете.
sudo systemctl daemon-reload
sudo systemctl enable --now nats
sudo systemctl status nats
Проверить, что процесс слушает порт:
ss -tlnp | grep 4222
Если хотите поднять NATS в связке с остальным стеком через Docker Compose, конфиг тот же файл монтируется как volume — общий подход к продакшен-compose разбирал в статье про docker compose для продакшена.
Проверка: publish и subscribe через NATS CLI
Сохраняем контекст подключения, чтобы не передавать креды в каждой команде:
nats context save vps \
--server nats://app:my-strong-password@127.0.0.1:4222 \
--select
Подписываемся на subject в одном терминале:
nats sub "orders.created"
И публикуем сообщение из другого:
nats pub "orders.created" '{"order_id": 4821, "sum": 1500}'
Подписчик мгновенно получает сообщение — задержка на локальной сети обычно укладывается в единицы миллисекунд, но точную цифру для вашего VPS и нагрузки надёжнее измерить самостоятельно через nats bench, готовые бенчмарки из интернета для вашей конфигурации не показательны.
Проверить request/reply (для RPC-паттерна между сервисами):
# сервис-обработчик
nats reply "billing.charge" "OK, processed"
# клиент
nats request "billing.charge" '{"amount": 500}'
Queue-группы — способ распределить нагрузку между несколькими инстансами одного сервиса без дублирования обработки:
nats sub "orders.created" --queue workers
Если запустить эту команду в двух терминалах одновременно, каждое сообщение получит только один из подписчиков — ровно то поведение, которое нужно для горизонтального масштабирования воркеров.
Аутентификация и TLS
Пароль в конфиге — минимум. Если сервисы обмениваются данными не только внутри одного VPS (например, между дата-центрами RU и US), трафик должен идти в TLS. Получаем сертификат (Let's Encrypt через certbot, если у вас есть домен, привязанный к IP сервера) и добавляем блок:
tls {
cert_file: "/etc/nats/certs/fullchain.pem"
key_file: "/etc/nats/certs/privkey.pem"
verify: false
timeout: 3
}
Клиенты подключаются уже через tls:// вместо nats://. Для внутренней связи микросервисов в пределах одного VPS через 127.0.0.1 или приватную сеть TLS избыточен — там достаточно пароля и firewall, но между узлами разных провайдеров или дата-центров не экономьте на шифровании.
Отдельно — сетевой доступ. Порт 4222 должен быть открыт только для тех IP, которым реально нужно подключаться к брокеру:
sudo ufw allow from 10.0.0.0/24 to any port 4222 proto tcp
sudo ufw deny 4222
sudo ufw deny 8222
Порт мониторинга 8222 наружу лучше вообще не открывать — доступ к нему берите через SSH-туннель (ssh -L 8222:localhost:8222 user@vps) или проксируйте локально для Prometheus-экспортёра. Общие принципы настройки правил разобраны в статье про firewall ufw на VPS.
JetStream: персистентность вместо fire-and-forget
Голый NATS — это at-most-once доставка: если подписчика не было онлайн в момент публикации, сообщение потеряно. Для событий, которые нельзя терять (платежи, заказы, аудит-лог), включаем JetStream — встроенный слой персистентности поверх того же брокера, без отдельного сервиса.
Добавляем в конфиг:
jetstream {
store_dir: "/var/lib/nats/jetstream"
max_memory_store: 512MB
max_file_store: 10GB
}
После перезапуска сервера создаём стрим — по сути, персистентный лог сообщений по маске subject'ов:
nats stream add ORDERS \
--subjects "orders.>" \
--storage file \
--retention limits \
--max-age 168h \
--max-bytes 5GB \
--replicas 1
--replicas 1 — для одиночного узла. Если позже добавите ещё два VPS в кластер, поднимите --replicas 3 и получите репликацию с автоматическим failover — но это отдельная тема, кластеризация на старте обычно не нужна.
Consumer с подтверждением обработки (durable, чтобы позиция сохранялась между перезапусками сервиса):
nats consumer add ORDERS billing-worker \
--filter "orders.created" \
--ack explicit \
--pull \
--max-deliver 5
Теперь, если сервис-подписчик упал на 10 минут, после рестарта он получит все пропущенные сообщения из стрима — вместо того чтобы они молча исчезли, как в обычном pub/sub.
Мониторинг и типичные проблемы
Эндпоинт /varz на порту 8222 отдаёт JSON со всей телеметрией: подключения, память, медленные потребители, ошибки. Быстрая проверка:
curl -s http://127.0.0.1:8222/varz | jq '.mem, .connections, .slow_consumers'
Растущий slow_consumers — сигнал, что какой-то подписчик не успевает вычитывать очередь и NATS начинает его дропать (это осознанное поведение сервера — он не будет копить сообщения в памяти ради одного медленного клиента). Решение — либо ускорить обработчик, либо перевести subject на JetStream с pull-consumer, где скорость чтения контролирует сам клиент.
Для постоянного мониторинга проще всего прометеевский nats-exporter (отдельный маленький бинарник от NATS Inc.), который транслирует /varz в формат Prometheus:
nats-exporter -varz -connz -subz \
-addr 0.0.0.0:7777 \
http://localhost:8222
Дальше — стандартный Grafana-дашборд поверх этого экспортёра; общая настройка связки разобрана в статье про Grafana и Prometheus на VPS.
Частая проблема после установки — сервис не может подключиться, хотя порт открыт локально. Обычно причина одна из трёх: файрвол режет входящий трафик именно на 4222 (проверьте ufw status numbered), в конфиге listen смотрит на 127.0.0.1 вместо 0.0.0.0, либо клиент подключается без пароля к серверу с authorization — тогда в логе будет Authorization Violation, а не таймаут. Смотрите journalctl -u nats -f — NATS логирует причину отказа в подключении явно, гадать не приходится.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем NATS отличается от Redis Pub/Sub?
Redis Pub/Sub тоже быстрый, но не хранит сообщения и не имеет очередей с подтверждением — это чистый broadcast. NATS с JetStream добавляет персистентность, replay и consumer groups, оставаясь легче Kafka. Если брокер вам нужен заодно с кэшем — посмотрите на установку Redis на VPS, но для message-очередей это разные инструменты.
Сколько RAM реально нужно NATS?
Сам процесс на простое ест 15-20 МБ. Основной расход памяти — буферы подключений и, при включённом JetStream, max_memory_store из конфига. Для старта достаточно VPS с 1-2 ГБ RAM; точную нагрузку под ваш профиль сообщений замерьте через nats bench.
Нужен ли кластер из нескольких узлов?
Только если критична отказоустойчивость самого брокера. Для одного проекта на старте одного VPS с JetStream и регулярным бэкапом /var/lib/nats/jetstream обычно достаточно — кластеризация добавляет сложность эксплуатации, которая окупается на масштабе.
Как обновить NATS без потери сообщений?
JetStream пишет данные на диск в store_dir, поэтому systemctl restart nats после замены бинарника не теряет данные стримов — сервер перечитывает состояние при старте. Для голого pub/sub без JetStream любой рестарт роняет неподтверждённые сообщения, это ожидаемо.
Можно ли подключаться из другого дата-центра?
Да, но только через TLS и с ограничением по IP на файрволе — открывать 4222 в интернет без шифрования и списка разрешённых адресов не стоит, даже с паролем.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →