bolt Valebyte VPS от $4/мес — NVMe, запуск за 60 секунд.

Получить VPS arrow_forward
eco Начальный Туториал

Развёртывание NATS JetStream на VPS: Docker, TLS, авторизация и сохранение данных

calendar_month Oct 16, 2026 schedule 22 мин. чтения visibility 7 просмотров
Развёртывание NATS JetStream на VPS: Docker, TLS, авторизация и сохранение данных
info

Нужен сервер для этого гайда? Мы предлагаем выделенные серверы и VPS в 50+ странах с мгновенной настройкой.

Нужен сервер для этого гайда?

Разверните VPS или выделенный сервер за минуты.

Развёртывание NATS JetStream на VPS: Docker, TLS, авторизация и сохранение данных

TL;DR

NATS JetStream можно надёжно запустить на VPS в Docker: NATS-сервер будет принимать сообщения по TLS, ограничивать доступ по логину и паролю, а данные потоков сохранять на диске между перезапусками контейнера.

  • Используем Ubuntu Server 24.04 LTS, Docker Engine и официальный образ nats:2.11-alpine.
  • JetStream хранит сообщения в постоянном Docker volume на отдельном диске.
  • TLS-сертификат для NATS выпускается через Certbot и Let’s Encrypt.
  • Публично открываем порт NATS 4222, а мониторинг оставляем на localhost и публикуем через Caddy по HTTPS.
  • Доступ к NATS защищается переменными окружения, а конфигурация и данные регулярно копируются с помощью Restic в S3-совместимое хранилище.
  • Перед обновлением проверяем состояние JetStream, делаем резервную копию и используем окно обслуживания.

1. TL;DR

NATS — быстрый брокер сообщений с небольшим потреблением ресурсов. JetStream добавляет к нему сохраняемые сообщения, подтверждения доставки, повторную обработку и consumer-группы. В результате VPS можно использовать как самостоятельную шину событий для микросервисов, фоновых задач, интеграций и realtime-приложений.

В статье используется один сервер с Docker Compose. Это хороший вариант для разработки, небольшого production-проекта или внутренней инфраструктуры, но не полноценная отказоустойчивая кластерная конфигурация. Для критически важных данных ниже также предусмотрены резервные копии и рекомендации по переходу к кластеру.

2. Содержание

Установка разделена на последовательные этапы: выбор ресурсов, базовое усиление безопасности, установка Docker, выпуск сертификата, запуск NATS, проверка JetStream, настройка резервного копирования и обслуживание. Команды рассчитаны на чистый сервер с Ubuntu Server 24.04 LTS и доменным именем.

3. Что мы настраиваем и зачем

NATS и JetStream

NATS использует простой протокол обмена сообщениями по модели publish/subscribe. Клиент публикует сообщение в subject, а подписчики получают его почти без задержки. Базовый NATS ориентирован на память и не предназначен для долгого хранения событий после отключения подписчика.

JetStream добавляет персистентное хранилище. Поток, или stream, принимает сообщения из одного или нескольких subject и записывает их на диск. Consumer определяет, как приложение читает поток: с какого места начинать, нужно ли подтверждение, сколько раз повторять доставку и как обрабатывать сообщения после сбоя.

Компонент Назначение Пример
NATS server Маршрутизация сообщений между клиентами Публикация событий заказа
JetStream Сохранение сообщений и повторная доставка Очередь фоновых заданий
Stream Лог сообщений, сопоставленный с subject events.orders
Consumer Состояние чтения и подтверждения Воркер обработки платежей
Monitoring endpoint Метрики и диагностические JSON-эндпоинты /jsz, /varz

Что будет готово в конце

После выполнения инструкции будет работать контейнер NATS с JetStream и файловым хранилищем. Клиенты смогут подключаться к адресу вида tls://nats.example.com:4222. Для подключения потребуются имя пользователя и пароль, а сервер будет проверять сертификат домена.

Мониторинг NATS не следует открывать всему интернету: в нём присутствуют сведения о соединениях, subject, consumer и состоянии сервера. Поэтому порт 8222 будет слушать только на loopback-интерфейсе. Если нужен удалённый просмотр, Caddy опубликует его через HTTPS с отдельным доменом и базовой HTTP-авторизацией.

Self-hosted или облачный NATS

Облачный NATS обычно предоставляет готовые кластеры, автоматические обновления, резервирование и управление сертификатами. Это снижает операционную нагрузку, но стоимость растёт вместе с трафиком, числом соединений и объёмом хранения. Кроме того, данные и сетевой маршрут находятся под контролем внешнего оператора.

Self-hosted NATS на VPS даёт полный контроль над конфигурацией, регионом, диском, сетевыми правилами и резервными копиями. Цена такой свободы — самостоятельное обслуживание: обновление ОС, мониторинг диска, проверка сертификатов, тестирование восстановления и реакция на сбои.

Критерий Self-hosted на VPS Cloud-managed
Контроль Полный доступ к ОС и данным Зависит от провайдера
Отказоустойчивость Нужно проектировать самостоятельно Часто включена в тариф
Стоимость Предсказуемая цена VPS и диска Зависит от трафика и хранения
Обслуживание Ваша ответственность Часть задач выполняет оператор

Один VPS не заменяет кластер. Если потеря сервера недопустима, необходимы минимум три NATS-узла с JetStream-репликацией, отдельные зоны отказа и резервное копирование. Для первого production-развёртывания с умеренной нагрузкой один узел допустим, если подтверждена процедура восстановления.

4. Какой VPS-конфиг нужен под эту задачу

Схема: 4. Какой VPS-конфиг нужен под эту задачу
Схема: 4. Какой VPS-конфиг нужен под эту задачу

Ресурсы зависят не столько от количества сообщений, сколько от размера payload, длительности хранения, числа подключений, количества consumer и характера записи на диск. NATS сам по себе лёгкий, но JetStream активно использует диск и page cache ядра.

Минимальная конфигурация

  • CPU: 2 виртуальных ядра.
  • RAM: 2 ГБ для небольшого тестового или внутреннего сервиса.
  • Диск: 40–60 ГБ SSD/NVMe, желательно с гарантированными IOPS.
  • Сеть: порт 1 Гбит/с или выше; важнее стабильная задержка, а не пиковая скорость.
  • ОС: Ubuntu Server 24.04 LTS или другой поддерживаемый Linux-дистрибутив.
  • IPv4: желателен выделенный публичный IPv4 для DNS и клиентов.
  • IPv6: полезен, но не обязателен, если клиенты используют IPv4.

Минимальный вариант подходит для нескольких десятков соединений, небольших сообщений и хранения в пределах нескольких гигабайт. Не следует заполнять диск более чем на 80%. JetStream нуждается в свободном месте для новых сегментов, временных файлов и безопасного обслуживания.

Практичная конфигурация для небольшого production

Для команды или SaaS-приложения разумно начать с 4 vCPU, 8 ГБ RAM и 100–160 ГБ NVMe. Такой сервер оставляет запас для Docker, мониторинга, резервного архива и кратковременных пиков. Объём диска выбирайте по формуле: суточный объём сообщений, умноженный на срок хранения, плюс 30–50% свободного пространства.

Например, если приложение публикует 15 ГБ сообщений в сутки и хранит их семь дней, только поток займёт около 105 ГБ без учёта служебных данных. Для такого сценария диск на 160 ГБ слишком мал: лучше выбрать 250–300 ГБ либо ограничить retention и вынести архив в объектное хранилище.

В качестве одного из вариантов можно взять VPS с такими характеристиками: от 4 vCPU, 8 ГБ RAM, NVMe-диск от 100 ГБ и публичный IPv4. Конкретный тариф необходимо сверять с фактическим объёмом сообщений, IOPS и сетевым трафиком.

Когда нужен dedicated

Выделенный сервер имеет смысл при постоянной высокой записи на диск, большом количестве соединений, строгих требованиях к задержке или необходимости полностью контролировать CPU и I/O. На noisy-neighbor VPS производительность диска может меняться, что заметно при частом fsync и больших потоках JetStream.

Dedicated также удобнее для кластера из нескольких NATS-узлов, если каждый узел должен иметь быстрый локальный NVMe. Однако один мощный dedicated не даёт высокой доступности сам по себе. Для отказоустойчивости важнее несколько независимых узлов, чем один сервер с большим числом ядер.

Выбор локации

Размещайте NATS ближе к приложениям, которые публикуют и потребляют сообщения. Задержка между сервисом и брокером влияет на время подтверждения, работу request/reply и скорость обработки очереди. Если основные клиенты находятся в одном регионе, выбирайте тот же регион или соседний с низким RTT.

Для международных клиентов один узел в удалённом регионе может привести к нестабильному latency. В таком случае используйте региональные NATS-кластеры, leaf nodes или отдельные брокеры для разных зон. Проверяйте не только ping, но и реальный TCP/TLS handshake и время публикации сообщения.

5. Подготовка сервера

Схема: 5. Подготовка сервера
Схема: 5. Подготовка сервера

Ниже предполагается чистый Ubuntu Server 24.04 LTS. Выполняйте команды под пользователем с временными правами root. Не отключайте текущую SSH-сессию, пока не проверите вход новым пользователем через отдельное окно.

Создание администратора и SSH-ключа

Сначала создайте отдельного пользователя. Пример использует имя deploy; замените его на своё. Вход по паролю для SSH в дальнейшем будет отключён.

# Создаём пользователя для администрирования
sudo adduser deploy

# Добавляем пользователя в группу sudo
sudo usermod -aG sudo deploy

# Создаём каталог для публичного SSH-ключа
sudo install -d -m 700 -o deploy -g deploy /home/deploy/.ssh

# Скопируйте публичный ключ текущего пользователя в каталог deploy
sudo cp ~/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys

# Исправляем владельца и права файла ключей
sudo chown deploy:deploy /home/deploy/.ssh/authorized_keys
sudo chmod 600 /home/deploy/.ssh/authorized_keys

Если ключ ещё не создан на рабочем компьютере, выполните локально:

# Создаём современную пару ключей Ed25519
ssh-keygen -t ed25519 -a 100 -C "nats-admin"

# Копируем публичный ключ на сервер
ssh-copy-id deploy@SERVER_IP

Проверьте вход:

# Откройте новую SSH-сессию и убедитесь, что sudo работает
ssh deploy@SERVER_IP
sudo -v

Базовая настройка SSH

Создайте отдельный drop-in-файл, а не редактируйте основной конфиг без необходимости. Номер порта 2222 ниже является примером. Если вы меняете SSH-порт, сначала разрешите его в firewall.

# Создаём настройки SSH для запрета root и паролей
sudo tee /etc/ssh/sshd_config.d/ hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF

# Проверяем синтаксис конфигурации SSH
sudo sshd -t

# Применяем настройки без разрыва действующих сессий
sudo systemctl reload ssh

В реальной команде файл должен называться без пробела после каталога. Корректная команда создания:

sudo tee /etc/ssh/sshd_config.d/hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF

Обновление системы и базовые пакеты

# Обновляем индексы пакетов и устанавливаем обновления безопасности
sudo apt update && sudo apt full-upgrade -y

# Устанавливаем инструменты администрирования и автоматические обновления
sudo apt install -y \
  ca-certificates curl gnupg jq unzip vim htop lsof \
  ufw fail2ban unattended-upgrades apt-transport-https

# Включаем автоматическую установку обновлений безопасности
sudo dpkg-reconfigure -plow unattended-upgrades

Firewall и fail2ban

До включения UFW разрешите SSH, иначе можно потерять доступ. Порт 80 нужен Certbot для HTTP-проверки и обновления сертификата, 443 — для HTTPS-мониторинга через Caddy, а 4222 — для клиентов NATS.

# Разрешаем SSH, HTTP, HTTPS и TLS-порт NATS
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 4222/tcp

# Включаем firewall с политикой запрета входящих соединений
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw --force enable

# Проверяем активные правила
sudo ufw status verbose

Мониторингный порт 8222 намеренно не открывается. В конфигурации NATS он будет привязан к 127.0.0.1. Fail2ban можно включить для защиты SSH:

# Запускаем fail2ban и добавляем его в автозагрузку
sudo systemctl enable --now fail2ban

# Проверяем состояние защиты SSH
sudo fail2ban-client status sshd

6. Установка ПО — пошагово

Схема: 6. Установка ПО — пошагово
Схема: 6. Установка ПО — пошагово

В 2026 году для этого сценария используем Docker Engine из официального репозитория Docker, Compose Plugin и образ NATS 2.11.x. Точный patch-релиз может меняться, поэтому в production желательно зафиксировать конкретный digest после тестирования.

Шаг 1. Установка Docker Engine

# Удаляем потенциально конфликтующие старые пакеты
sudo apt remove -y docker.io docker-doc docker-compose podman-docker containerd runc || true

# Создаём каталог для ключей репозиториев
sudo install -m 0755 -d /etc/apt/keyrings

# Загружаем официальный ключ Docker
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc

# Делаем ключ доступным для чтения менеджером пакетов
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Добавляем официальный репозиторий Docker для Ubuntu 24.04
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu noble stable" | \
sudo tee /etc/apt/sources.list.d/docker.list >/dev/null

# Обновляем индекс и устанавливаем Docker Engine и Compose Plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

Чтобы не использовать sudo перед каждой командой Docker, добавьте пользователя в группу. Группа даёт практически root-доступ, поэтому добавляйте только доверенных администраторов.

# Разрешаем пользователю deploy управлять Docker
sudo usermod -aG docker deploy

# Перезапустите SSH-сессию, затем проверьте Docker
docker run --rm hello-world

# Проверяем версии установленного ПО
docker version
docker compose version

Шаг 2. Создание каталогов проекта

# Создаём каталоги конфигурации, сертификатов и бэкапов
sudo install -d -m 750 /opt/nats/{config,certs,backups,caddy}

# Передаём каталог проекта пользователю deploy
sudo chown -R deploy:deploy /opt/nats

# Переходим в рабочий каталог
cd /opt/nats

Шаг 3. Установка Certbot и выпуск сертификата

Для TLS-соединений NATS нужен сертификат домена. Пусть доменом будет nats.example.com, а DNS-запись A уже указывает на IPv4 сервера. Замените домен и email на свои значения.

# Устанавливаем Certbot из репозитория Ubuntu
sudo apt install -y certbot

# Временно останавливаем сервис, который может занимать порт 80
sudo systemctl stop caddy 2>/dev/null || true

# Выпускаем сертификат через HTTP-01 challenge
sudo certbot certonly --standalone \
  --preferred-challenges http \
  -d nats.example.com \
  --email [email protected] \
  --agree-tos \
  --no-eff-email

Сертификаты Let’s Encrypt обновляются каждые 90 дней. Certbot обычно устанавливает systemd timer. Проверить его можно так:

# Проверяем автоматическое обновление сертификата
sudo systemctl list-timers 'certbot'

# Делаем тестовый dry-run без выпуска нового сертификата
sudo certbot renew --dry-run

Шаг 4. Создание пользователя NATS и секретов

Пароли не следует писать прямо в конфигурацию, репозиторий или командную строку, которая попадёт в shell history. Сгенерируйте URL-safe значения и сохраните их в файле с правами 600.

# Генерируем случайные пароли без символов, проблемных для YAML и URL
NATS_USER_PASSWORD=$(openssl rand -base64 36 | tr -dc 'A-Za-z0-9' | head -c 32)
NATS_ADMIN_PASSWORD=$(openssl rand -base64 36 | tr -dc 'A-Za-z0-9' | head -c 32)
CADDY_PASSWORD=$(openssl rand -base64 36 | tr -dc 'A-Za-z0-9' | head -c 32)

# Записываем секреты в локальный env-файл
cat > /opt/nats/.env <<EOF
NATS_APP_USER=app
NATS_APP_PASSWORD=${NATS_USER_PASSWORD}
NATS_ADMIN_USER=admin
NATS_ADMIN_PASSWORD=${NATS_ADMIN_PASSWORD}
CADDY_USER=monitor
CADDY_PASSWORD=${CADDY_PASSWORD}
EOF

# Запрещаем чтение файла другим пользователям
chmod 600 /opt/nats/.env

# Показываем только имена переменных, не сами секреты
cut -d= -f1 /opt/nats/.env

Шаг 5. Получение официального образа NATS

# Загружаем официальный образ NATS ветки 2.11 Alpine
docker pull nats:2.11-alpine

# Проверяем наличие образа локально
docker image ls nats

Для production после проверки можно заменить плавающий тег на конкретный patch-тег или digest. Это предотвращает неожиданное изменение поведения при следующем docker compose pull.

7. Конфигурация

Схема: 7. Конфигурация
Схема: 7. Конфигурация

Конфигурация NATS

Создайте файл /opt/nats/config/nats.conf. Значения в кавычках с конструкциями $NATS_APP_PASSWORD будут подставляться из окружения контейнера. JetStream хранит данные в каталоге /data/jetstream, который будет подключён к постоянному volume.

cat > /opt/nats/config/nats.conf <<'EOF'
server_name: nats-vps-1

port: 4222
http: 127.0.0.1:8222

jetstream {
  store_dir: /data/jetstream
  max_mem_store: 512MB
  max_file_store: 80GB
}

tls {
  cert_file: /etc/nats/certs/fullchain.pem
  key_file: /etc/nats/certs/privkey.pem
  verify: false
  timeout: 2
}

authorization {
  users = [
    {
      user: "$NATS_APP_USER"
      password: "$NATS_APP_PASSWORD"
      permissions: {
        publish: {
          allow: ["events.>", "jobs.>"]
        }
        subscribe: {
          allow: ["events.>", "jobs.>", "_INBOX.>"]
        }
      }
    }
    {
      user: "$NATS_ADMIN_USER"
      password: "$NATS_ADMIN_PASSWORD"
      permissions: {
        publish: [">"]
        subscribe: [">"]
      }
    }
  ]
}

max_payload: 1MB
max_pending: 64MB
write_deadline: 2s
EOF

# Ограничиваем чтение конфигурации
chmod 640 /opt/nats/config/nats.conf

Параметр max_file_store — это верхняя граница файлового хранилища JetStream, а не размер автоматически выделенного диска. Значение должно быть меньше свободного места на VPS. Если диск заполнится, публикация и обслуживание потоков начнут завершаться ошибками.

В production лучше использовать отдельные пользователи с минимальными permissions для каждого приложения. Администратора не следует использовать в коде приложения. В примере пользователь app может работать только с subject events.>, jobs.> и inbox-адресами.

Права на сертификаты

Docker должен видеть сертификаты Let’s Encrypt. Папка /etc/letsencrypt/live содержит символьные ссылки, поэтому монтировать нужно каталог /etc/letsencrypt целиком в режиме read-only.

# Проверяем, что сертификат выпущен для нужного домена
sudo certbot certificates

# Убеждаемся, что файлы сертификата доступны root
sudo ls -l /etc/letsencrypt/live/nats.example.com/

Docker Compose

Создайте файл /opt/nats/compose.yaml. Контейнер не публикует порт мониторинга наружу: запись 127.0.0.1:8222:8222 ограничивает доступ loopback-адресом сервера.

cat > /opt/nats/compose.yaml <<'EOF'
services:
  nats:
    image: nats:2.11-alpine
    container_name: nats
    restart: unless-stopped
    command: ["-c", "/etc/nats/nats.conf"]
    env_file:
      - .env
    ports:
      - "4222:4222"
      - "127.0.0.1:8222:8222"
    volumes:
      - nats_data:/data
      - ./config/nats.conf:/etc/nats/nats.conf:ro
      - /etc/letsencrypt:/etc/nats/certs:ro
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8222/healthz"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    stop_grace_period: 30s
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "5"

volumes:
  nats_data:
    name: nats_jetstream_data
EOF

# Проверяем итоговую Compose-конфигурацию с подставленными переменными
docker compose config

# Запускаем NATS в фоне
docker compose up -d

# Проверяем состояние контейнера
docker compose ps

После запуска проверьте логи. Ошибка о невозможности прочитать privkey.pem обычно означает проблему с монтированием сертификата или правами доступа. Ошибка о неизвестном параметре конфигурации означает несовместимость синтаксиса с версией NATS.

# Смотрим последние 100 строк журнала NATS
docker compose logs --tail=100 nats

# Проверяем health endpoint на loopback
curl -fsS http://127.0.0.1:8222/healthz

# Получаем состояние сервера в JSON
curl -fsS http://127.0.0.1:8222/varz | jq '{server_id, server_name, version, jetstream}'

HTTPS для мониторинга через Caddy

NATS-клиенты используют TLS непосредственно на порту 4222. Caddy нужен не для проксирования NATS-протокола, а для безопасной публикации HTTP-мониторинга. Для этого установите Caddy из официального репозитория или пакета вашей ОС, затем создайте конфигурацию.

# Устанавливаем Caddy из официального APT-репозитория
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \
  sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \
  sudo tee /etc/apt/sources.list.d/caddy-stable.list

sudo apt update
sudo apt install -y caddy

Создайте DNS-запись nats-monitor.example.com на тот же сервер и файл /etc/caddy/Caddyfile. Хеш пароля можно получить командой caddy hash-password.

# Генерируем bcrypt-хеш пароля для basic authentication
sudo caddy hash-password --plaintext 'REPLACE_WITH_MONITOR_PASSWORD'
nats-monitor.example.com {
    basicauth {
        monitor REPLACE_WITH_BCRYPT_HASH
    }

    reverse_proxy 127.0.0.1:8222
}
# Проверяем конфигурацию Caddy
sudo caddy validate --config /etc/caddy/Caddyfile

# Запускаем Caddy и включаем автозагрузку
sudo systemctl enable --now caddy

# Проверяем HTTPS-мониторинг
curl -u monitor:'REPLACE_WITH_MONITOR_PASSWORD' \
  https://nats-monitor.example.com/healthz

Caddy автоматически получает HTTPS-сертификат для мониторингового домена. Не смешивайте этот сертификат с сертификатом NATS, если не проверили, что клиенты подключаются к правильному имени. Для NATS сертификат должен содержать имя, указанное в клиентском URL, например nats.example.com.

Проверка TLS и подключения клиента

Проверить сертификат можно с помощью OpenSSL. Команда должна завершиться без ошибки проверки цепочки, если DNS и сертификат настроены корректно.

# Проверяем TLS handshake и имя сертификата NATS
openssl s_client \
  -connect nats.example.com:4222 \
  -servername nats.example.com \
  -verify_return_error </dev/null

Для функционального теста установите CLI NATS из официального релиза NATS CLI. Версию лучше закрепить по release notes проекта; ниже показана проверка уже установленной команды.

# Проверяем, что NATS CLI установлен
nats --version

# Создаём профиль подключения с TLS и логином приложения
nats context add vps \
  --server "tls://nats.example.com:4222" \
  --user "$NATS_APP_USER" \
  --password "$NATS_APP_PASSWORD"

# Выбираем профиль
nats context select vps

# Проверяем соединение с сервером
nats server check connection

# Проверяем состояние JetStream
nats account info

Если переменные не загружены в текущую shell-сессию, прочитайте их из файла только в интерактивной административной сессии:

# Загружаем переменные из защищённого файла в текущую shell-сессию
set -a
. /opt/nats/.env
set +a

# Повторяем проверку подключения
nats account info

Создание stream и consumer

Пример создаёт поток событий заказов с файловым хранением и сроком хранения семь дней. Для очереди задач используйте отдельный stream и другой retention policy. Не помещайте в один поток несвязанные типы сообщений без необходимости: это усложняет лимиты и очистку.

# Создаём поток для событий заказов с хранением на диске
nats stream add ORDERS \
  --subjects "events.orders.>" \
  --storage file \
  --retention limits \
  --max-age 168h \
  --max-bytes 50GB \
  --replicas 1 \
  --discard old \
  --ack

# Показываем конфигурацию потока
nats stream info ORDERS

# Создаём durable consumer с ручным подтверждением
nats consumer add ORDERS order-workers \
  --filter "events.orders.>" \
  --ack explicit \
  --wait 30s \
  --max-deliver 5 \
  --max-pending 1000 \
  --pull

# Публикуем тестовое сообщение
nats pub events.orders.created '{"order_id":"test-001","status":"created"}'

# Читаем одно сообщение через consumer
nats consumer next ORDERS order-workers

В production задавайте максимальный размер сообщения на уровне приложения и сервера. Большие payload лучше хранить в объектном хранилище, а через NATS передавать идентификатор файла, тип события и метаданные. Это снижает нагрузку на диск и ускоряет репликацию.

8. Бэкапы и обслуживание

Схема: 8. Бэкапы и обслуживание
Схема: 8. Бэкапы и обслуживание

Что необходимо сохранять

Резервная копия должна включать конфигурацию NATS, файл Compose, секреты, сертификатную стратегию и данные JetStream. Одной копии контейнера недостаточно: контейнер можно пересоздать, а volume с сообщениями и состояние consumer нельзя потерять.

  • /opt/nats/config/nats.conf — конфигурация сервера.
  • /opt/nats/compose.yaml — способ запуска.
  • /opt/nats/.env — секреты, хранимые зашифрованными в бэкапе.
  • Docker volume nats_jetstream_data — файловые данные JetStream.
  • Конфигурации stream и consumer — их стоит экспортировать отдельно через CLI.
  • Сведения о DNS, доменах и процедуре выпуска сертификатов.

Не копируйте live-файлы JetStream простым rsync во время интенсивной записи и не считайте такой снимок гарантированно согласованным. Для небольшого узла надёжнее остановить NATS на короткое окно, скопировать данные, затем запустить его снова. Для минимизации простоя используйте снапшоты диска провайдера, если они создаются атомарно.

Экспорт конфигурации JetStream

# Создаём каталог для описаний потоков и consumer
mkdir -p /opt/nats/backups/js-config

# Сохраняем список потоков в текстовом виде
nats stream ls > /opt/nats/backups/js-config/streams.txt

# Сохраняем конфигурацию потока в JSON
nats stream info ORDERS --json \
  > /opt/nats/backups/js-config/orders.json

# Сохраняем конфигурацию consumer в JSON
nats consumer info ORDERS order-workers --json \
  > /opt/nats/backups/js-config/order-workers.json

Restic и S3-совместимое хранилище

Резервную копию лучше хранить за пределами VPS: в S3-совместимом объектном хранилище или на отдельном сервере в другой зоне. Restic шифрует данные до отправки, поэтому провайдер хранилища не видит содержимое архива. Пароли Restic и S3 должны быть доступны только root.

# Устанавливаем Restic из репозитория Ubuntu
sudo apt install -y restic

# Создаём файл переменных для резервного копирования
sudo tee /root/.restic-env >/dev/null <<'EOF'
export RESTIC_REPOSITORY="s3:https://s3.example.net/nats-backup"
export AWS_ACCESS_KEY_ID="REPLACE_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="REPLACE_SECRET_KEY"
export RESTIC_PASSWORD="REPLACE_LONG_RANDOM_REPOSITORY_PASSWORD"
EOF

# Ограничиваем доступ к секретам
sudo chmod 600 /root/.restic-env

# Инициализируем зашифрованный Restic-репозиторий
sudo bash -c '. /root/.restic-env; restic init'

Создайте скрипт. Он останавливает контейнер, архивирует Docker volume и конфигурацию, затем запускает NATS. На время операции брокер недоступен, поэтому выберите окно с минимальным трафиком.

sudo tee /usr/local/sbin/backup-nats.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail

. /root/.restic-env

WORKDIR="/var/backups/nats-staging"
mkdir -p "$WORKDIR"
rm -rf "$WORKDIR"/

cd /opt/nats
docker compose stop nats

docker run --rm \
  -v nats_jetstream_data:/source:ro \
  -v "$WORKDIR":/backup \
  alpine:3.21 \
  sh -c 'cd /source && tar czf /backup/jetstream-data.tar.gz .'

tar czf "$WORKDIR/nats-config.tar.gz" \
  /opt/nats/config \
  /opt/nats/compose.yaml \
  /opt/nats/.env

restic backup "$WORKDIR" --tag nats-vps
restic forget --tag nats-vps --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

docker compose up -d
rm -rf "$WORKDIR"
EOF

sudo chmod 700 /usr/local/sbin/backup-nats.sh

# Запускаем резервную копию вручную и проверяем результат
sudo /usr/local/sbin/backup-nats.sh

# Проверяем список снимков Restic
sudo bash -c '. /root/.restic-env; restic snapshots'

Скрипт выше сохраняет архив volume после остановки NATS. Проверьте, что контейнер действительно вернулся в состояние Up, а healthcheck успешен:

# Проверяем контейнер после бэкапа
docker compose -f /opt/nats/compose.yaml ps

# Проверяем JetStream и health endpoint
curl -fsS http://127.0.0.1:8222/healthz
nats account info

Планировщик cron

# Запускаем бэкап каждую ночь в 03:30 по серверному времени
sudo tee /etc/cron.d/nats-backup >/dev/null <<'EOF'
30 3   * root /usr/local/sbin/backup-nats.sh >> /var/log/nats-backup.log 2>&1
EOF

sudo chmod 644 /etc/cron.d/nats-backup

Резервная копия считается рабочей только после тестового восстановления. Периодически создавайте временный каталог, скачивайте последний snapshot и проверяйте, что из архива извлекаются конфигурация и данные. Для критичных систем отдельно тестируйте запуск NATS на новом VPS.

Обновления NATS и ОС

Обновление одного NATS-узла не является rolling update: контейнер будет перезапущен, и клиенты потеряют соединения. Перед обновлением сделайте бэкап, проверьте release notes, убедитесь в совместимости клиентских библиотек и подготовьте maintenance window.

# Сохраняем текущую версию образа и состояние
docker image inspect nats:2.11-alpine --format '{{.RepoDigests}}'
docker compose -f /opt/nats/compose.yaml ps
nats account info

# Загружаем обновлённый образ после проверки release notes
docker compose -f /opt/nats/compose.yaml pull nats

# Пересоздаём только контейнер NATS
docker compose -f /opt/nats/compose.yaml up -d nats

# Проверяем логи и healthcheck после обновления
docker compose -f /opt/nats/compose.yaml logs --tail=100 nats
curl -fsS http://127.0.0.1:8222/healthz

Для кластера из трёх и более узлов обновление можно выполнять по одному узлу, контролируя quorum и состояние JetStream. Для одиночного сервера безопаснее плановое окно. Не удаляйте старый Docker volume и не выполняйте docker compose down -v, если не намерены удалить данные.

Наблюдаемость и контроль диска

# Проверяем свободное место на файловой системе
df -h

# Проверяем размер Docker volumes
docker system df -v

# Проверяем JetStream-метрики и активные consumer
curl -fsS http://127.0.0.1:8222/jsz?consumers=true | jq

# Смотрим использование памяти и CPU контейнером
docker stats --no-stream nats

Настройте предупреждение при заполнении диска на 70–80%, росте pending-сообщений и увеличении числа повторных доставок. Для более серьёзной эксплуатации подключите Prometheus endpoint и Grafana, но не открывайте диагностические endpoints без аутентификации и сетевого ограничения.

9. Troubleshooting и FAQ

Почему клиент получает ошибку TLS handshake или certificate verify failed?

Проверьте, что клиент подключается к доменному имени, присутствующему в сертификате, а не к IP-адресу. Выполните openssl s_client -connect domain:4222 -servername domain и проверьте DNS A-запись, срок действия сертификата и цепочку fullchain.pem. Убедитесь, что Certbot не выпустил сертификат для другого домена. В клиенте укажите TLS URL и системное хранилище доверенных CA; отключать проверку сертификата в production не следует.

Контейнер NATS сразу завершается после запуска. Что проверить?

Начните с docker compose logs nats. Частые причины — неверный путь к nats.conf, ошибка синтаксиса, отсутствие сертификата или невозможность прочитать переменную окружения. Выполните docker compose config, чтобы увидеть итоговую конфигурацию, и проверьте наличие файлов в /etc/letsencrypt/live/домен/. После исправления запустите docker compose up -d и снова изучите логи.

Почему JetStream не сохраняет данные после пересоздания контейнера?

Проверьте, что используется именно volume nats_jetstream_data, а не временный bind mount внутри контейнера. Команда docker volume inspect nats_jetstream_data покажет его расположение и имя. Нельзя выполнять docker compose down -v: флаг -v удаляет volume. Также убедитесь, что в конфигурации задан store_dir: /data/jetstream, а каталог /data подключён к постоянному volume.

Ошибка “permissions violation” возникает при публикации сообщения. Что делать?

Это означает, что пользователь не имеет права публиковать или подписываться на выбранный subject. Сопоставьте subject приложения с правилами пользователя в секции authorization. Пользователь app из примера разрешён только для events.>, jobs.> и _INBOX.>. После изменения конфига пересоздайте контейнер и подключитесь заново: права применяются при установлении клиентской сессии.

Какой VPS-конфиг минимально подойдёт?

Для тестов и небольшой внутренней системы достаточно 2 vCPU, 2 ГБ RAM и SSD от 40–60 ГБ. Для небольшого production лучше взять 4 vCPU, 8 ГБ RAM и NVMe от 100 ГБ, особенно если сообщения хранятся несколько дней. Важны стабильные IOPS, свободное место и публичный IPv4. Если объём данных быстро растёт, сначала увеличьте диск и настройте retention, а не просто добавляйте CPU.

Что выбрать — VPS или dedicated для этой задачи?

VPS подходит большинству небольших установок NATS JetStream: он дешевле, проще масштабируется вертикально и достаточен при умеренной записи. Dedicated оправдан при постоянной высокой нагрузке на диск, больших потоках, строгих требованиях к задержке или необходимости исключить влияние соседних виртуальных машин. Но dedicated не решает проблему отказоустойчивости автоматически. Для неё нужны несколько узлов, репликация и резервные копии.

Почему растёт количество pending-сообщений у consumer?

Consumer получает сообщения медленнее, чем публикуются. Проверьте CPU и память воркеров, задержки внешних API, число параллельных обработчиков и параметр max_ack_pending. Посмотрите информацию командой nats consumer info ORDERS order-workers. Увеличивать лимит без анализа опасно: это может привести к росту памяти и повторным доставкам. Обычно правильное решение — добавить воркеры, использовать queue-подобную обработку и настроить backoff.

Что произойдёт, если закончится место на диске?

JetStream перестанет нормально принимать новые сообщения, а Docker и сама ОС могут начать работать нестабильно. Немедленно проверьте df -h, размеры stream и логи NATS. Удалите ненужные Docker-образы и логи, но не удаляйте volume JetStream вручную. Затем уменьшите retention, максимальный размер потока или расширьте диск. После восстановления проверьте consumer и повторную публикацию тестового сообщения.

Можно ли открыть порт 8222 для удалённого мониторинга?

Открывать его всему интернету не следует: monitoring API раскрывает диагностические сведения и не является полноценной системой управления доступом. Оставьте порт на 127.0.0.1, а для удалённого доступа используйте Caddy с HTTPS и basic authentication, VPN или SSH-туннель. Для временного просмотра можно выполнить ssh -L 8222:127.0.0.1:8222 deploy@server, а затем открыть http://127.0.0.1:8222 локально.

10. Выводы и следующие шаги

Схема: 10. Выводы и следующие шаги
Схема: 10. Выводы и следующие шаги

На VPS развёрнут NATS JetStream с Docker, TLS на клиентском порту, авторизацией, постоянным диском и HTTPS-мониторингом. Конфигурация разделяет доступ приложений и администратора, а Restic позволяет вынести зашифрованные резервные копии за пределы сервера.

Дальше стоит настроить мониторинг заполнения диска и lag consumer, регулярно проверять восстановление из бэкапа и зафиксировать версии Docker-образов. При росте нагрузки переходите к нескольким NATS-узлам с JetStream-репликацией, отдельными failure domains и планом rolling update.

  • Определите retention для каждого stream на основе реального объёма сообщений.
  • Добавьте Prometheus/Grafana или другой контролируемый сбор метрик.
  • Протестируйте восстановление на временном сервере до того, как оно понадобится в аварии.

Был ли этот гайд полезен?

Ваш отзыв помогает нам улучшать гайды.

Поделиться записью:

Отправьте гайд тому, кому он может пригодиться.

Telegram VKVK WhatsApp Facebook LinkedIn XX

развёртывание nats jetstream на vps: docker, tls, авторизация и сохранение данных
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.