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

Отримати VPS arrow_forward
eco Початковий Туторіал

Розгортання NATS JetStream на VPS: Docker, TLS, авторизація та збереження даних

calendar_month Oct 16, 2026 schedule 22 хв. читання visibility 6 переглядів
Развёртывание 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 потрібна для цього завдання

Ресурси залежать не стільки від кількості повідомлень, скільки від розміру 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. Підготовка сервера

Нижче передбачається чистий 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. Встановлення ПЗ — покроково

У 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. Конфігурація

Конфігурація 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. Резервні копії та обслуговування

Що необхідно зберігати

Резервна копія має включати конфігурацію 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. Висновки та наступні кроки

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

Далі варто налаштувати моніторинг заповнення диска та lag consumer, регулярно перевіряти відновлення з резервної копії та зафіксувати версії Docker-образів. Зі зростанням навантаження переходьте до кількох NATS-вузлів із JetStream-реплікацією, окремими failure domains і планом rolling update.

  • Визначте retention для кожного stream на основі реального обсягу повідомлень.
  • Додайте Prometheus/Grafana або інший контрольований збір метрик.
  • Протестуйте відновлення на тимчасовому сервері до того, як воно знадобиться в аварійній ситуації.

Чи був цей гайд корисним?

Ваш відгук допомагає нам покращувати гайди.

Share this post:

Надішліть гайд тому, кому він може стати в пригоді.

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.