bolt Valebyte VPS desde $4/mes — NVMe, despliegue en 60s.

Obtener VPS arrow_forward
eco Principiante Tutorial/Cómo hacer

Despliegue de NATS JetStream en un VPS: Docker, TLS, autorización y persistencia de datos

calendar_month Oct 16, 2026 schedule 22 min de lectura visibility 25 vistas
Развёртывание NATS JetStream на VPS: Docker, TLS, авторизация и сохранение данных
info

¿Necesitas un servidor para esta guía? Ofrecemos servidores dedicados y VPS en más de 50 países con configuración instantánea.

¿Necesitas un VPS para esta guía?

Explore otras opciones de servidores dedicados en

Despliegue de NATS JetStream en un VPS: Docker, TLS, autorización y persistencia de datos

TL;DR

NATS JetStream se puede ejecutar de forma fiable en un VPS con Docker: el servidor NATS recibirá mensajes mediante TLS, restringirá el acceso mediante nombre de usuario y contraseña, y conservará los datos de los streams en el disco entre los reinicios del contenedor.

  • Utilizamos Ubuntu Server 24.04 LTS, Docker Engine y la imagen oficial nats:2.11-alpine.
  • JetStream almacena los mensajes en un Docker volume permanente ubicado en un disco independiente.
  • El certificado TLS para NATS se emite mediante Certbot y Let’s Encrypt.
  • Abrimos públicamente el puerto de NATS 4222, mientras que el monitoreo permanece en localhost y se publica mediante Caddy a través de HTTPS.
  • El acceso a NATS se protege mediante variables de entorno, y la configuración y los datos se copian periódicamente con Restic a un almacenamiento compatible con S3.
  • Antes de actualizar, comprobamos el estado de JetStream, realizamos una copia de seguridad y utilizamos una ventana de mantenimiento.

1. TL;DR

NATS es un broker de mensajes rápido y con un bajo consumo de recursos. JetStream le añade mensajes persistentes, confirmaciones de entrega, reprocesamiento y grupos de consumer. Como resultado, un VPS se puede utilizar como bus de eventos independiente para microservicios, tareas en segundo plano, integraciones y aplicaciones en tiempo real.

En el artículo se utiliza un único servidor con Docker Compose. Es una buena opción para desarrollo, un proyecto de producción pequeño o una infraestructura interna, pero no una configuración de clúster con alta disponibilidad completa. Para los datos críticos, a continuación también se incluyen copias de seguridad y recomendaciones para migrar a un clúster.

2. Contenido

La instalación se divide en etapas consecutivas: elección de recursos, refuerzo básico de la seguridad, instalación de Docker, emisión del certificado, ejecución de NATS, comprobación de JetStream, configuración de las copias de seguridad y mantenimiento. Los comandos están pensados para un servidor limpio con Ubuntu Server 24.04 LTS y un nombre de dominio.

3. Qué configuramos y por qué

NATS y JetStream

NATS utiliza un protocolo sencillo de intercambio de mensajes basado en el modelo publish/subscribe. El cliente publica un mensaje en un subject y los suscriptores lo reciben casi sin latencia. El NATS básico está orientado a la memoria y no está diseñado para almacenar eventos durante mucho tiempo después de que el suscriptor se desconecte.

JetStream añade almacenamiento persistente. Un stream, o flujo, recibe mensajes de uno o varios subject y los escribe en el disco. El consumer determina cómo lee el flujo la aplicación: desde qué punto comenzar, si se requiere confirmación, cuántas veces repetir la entrega y cómo procesar los mensajes después de un fallo.

Componente Propósito Ejemplo
NATS server Enrutamiento de mensajes entre clientes Publicación de eventos de pedidos
JetStream Almacenamiento de mensajes y reenvío Cola de tareas en segundo plano
Stream Registro de mensajes asociado a un subject events.orders
Consumer Estado de lectura y confirmaciones Worker de procesamiento de pagos
Monitoring endpoint Métricas y endpoints JSON de diagnóstico /jsz, /varz

Qué estará listo al final

Después de completar las instrucciones, funcionará un contenedor de NATS con JetStream y almacenamiento basado en archivos. Los clientes podrán conectarse a una dirección del tipo tls://nats.example.com:4222. Para conectarse se necesitarán un nombre de usuario y una contraseña, y el servidor comprobará el certificado del dominio.

El monitoreo de NATS no debe exponerse a todo Internet: contiene información sobre las conexiones, los subject, los consumer y el estado del servidor. Por ello, el puerto 8222 escuchará únicamente en la interfaz loopback. Si se necesita acceso remoto, Caddy lo publicará mediante HTTPS con un dominio independiente y autenticación HTTP básica.

Self-hosted o NATS en la nube

Un NATS en la nube normalmente ofrece clústeres listos para usar, actualizaciones automáticas, redundancia y gestión de certificados. Esto reduce la carga operativa, pero el coste aumenta junto con el tráfico, el número de conexiones y el volumen de almacenamiento. Además, los datos y la ruta de red quedan bajo el control de un operador externo.

El NATS Self-hosted en un VPS proporciona control total sobre la configuración, la región, el disco, las reglas de red y las copias de seguridad. El precio de esta libertad es el mantenimiento por cuenta propia: actualizar el sistema operativo, supervisar el disco, comprobar los certificados, probar la recuperación y responder a los fallos.

Criterio Self-hosted en un VPS Cloud-managed
Control Acceso total al sistema operativo y a los datos Depende del proveedor
Tolerancia a fallos Debe diseñarse por cuenta propia A menudo está incluida en la tarifa
Coste Precio predecible del VPS y del disco Depende del tráfico y del almacenamiento
Mantenimiento Es su responsabilidad El operador realiza parte de las tareas

Un único VPS no sustituye a un clúster. Si la pérdida del servidor es inadmisible, se necesitan como mínimo tres nodos NATS con replicación de JetStream, zonas de fallo independientes y copias de seguridad. Para un primer despliegue en producción con una carga moderada, un solo nodo es aceptable si se ha validado el procedimiento de recuperación.

4. Qué configuración de VPS se necesita para esta tarea

Los recursos dependen no tanto del número de mensajes como del tamaño del payload, la duración del almacenamiento, el número de conexiones, la cantidad de consumer y el patrón de escritura en el disco. NATS es ligero por sí mismo, pero JetStream utiliza activamente el disco y la page cache del kernel.

Configuración mínima

  • CPU: 2 núcleos virtuales.
  • RAM: 2 GB para un servicio de pruebas pequeño o un servicio interno.
  • Disco: SSD/NVMe de 40–60 GB, preferiblemente con IOPS garantizados.
  • Red: puerto de 1 Gbit/s o superior; es más importante una latencia estable que la velocidad máxima.
  • SO: Ubuntu Server 24.04 LTS u otra distribución de Linux compatible.
  • IPv4: se recomienda una IPv4 pública dedicada para DNS y los clientes.
  • IPv6: es útil, pero no obligatoria si los clientes utilizan IPv4.

La opción mínima es adecuada para varias decenas de conexiones, mensajes pequeños y un almacenamiento de unos pocos gigabytes. No se debe llenar el disco por encima del 80%. JetStream necesita espacio libre para nuevos segmentos, archivos temporales y un mantenimiento seguro.

Configuración práctica para una producción pequeña

Para un equipo o una aplicación SaaS, es razonable comenzar con 4 vCPU, 8 GB de RAM y un NVMe de 100–160 GB. Este servidor deja margen para Docker, el monitoreo, el archivo de copias de seguridad y los picos temporales. Elija el tamaño del disco según la fórmula: volumen diario de mensajes multiplicado por el periodo de retención, más un 30–50% de espacio libre.

Por ejemplo, si la aplicación publica 15 GB de mensajes al día y los conserva durante siete días, solo el stream ocupará unos 105 GB, sin contar los datos de servicio. Para este escenario, un disco de 160 GB es demasiado pequeño: es mejor elegir 250–300 GB o limitar el retention y trasladar el archivo a un almacenamiento de objetos.

Como una de las opciones, puede contratar un VPS con estas características: desde 4 vCPU, 8 GB de RAM, un disco NVMe de al menos 100 GB y una IPv4 pública. La tarifa concreta debe compararse con el volumen real de mensajes, los IOPS y el tráfico de red.

Cuándo se necesita un dedicated

Un servidor dedicado tiene sentido cuando existe una escritura constante elevada en el disco, un gran número de conexiones, requisitos estrictos de latencia o la necesidad de controlar completamente la CPU y la E/S. En un VPS con noisy neighbor, el rendimiento del disco puede variar, algo que se nota con fsync frecuente y streams grandes de JetStream.

Un Dedicated también resulta más cómodo para un clúster de varios nodos NATS si cada nodo debe disponer de un NVMe local rápido. Sin embargo, un único dedicated potente no proporciona alta disponibilidad por sí solo. Para la tolerancia a fallos, es más importante contar con varios nodos independientes que con un servidor que tenga un mayor número de núcleos.

Elección de la ubicación

Coloque NATS cerca de las aplicaciones que publican y consumen mensajes. La latencia entre el servicio y el broker influye en el tiempo de confirmación, el funcionamiento de request/reply y la velocidad de procesamiento de la cola. Si los principales clientes se encuentran en una misma región, elija esa región o una adyacente con un RTT bajo.

Para clientes internacionales, un único nodo en una región remota puede provocar una latencia inestable. En ese caso, utilice clústeres NATS regionales, leaf nodes o brokers independientes para distintas zonas. Compruebe no solo el ping, sino también el handshake TCP/TLS real y el tiempo de publicación de un mensaje.

5. Preparación del servidor

A continuación se presupone un Ubuntu Server 24.04 LTS limpio. Ejecute los comandos con un usuario que tenga privilegios temporales de root. No cierre la sesión SSH actual hasta comprobar el acceso con el nuevo usuario desde otra ventana.

Creación del administrador y de la clave SSH

Primero cree un usuario independiente. El ejemplo utiliza el nombre deploy; sustitúyalo por el suyo. Posteriormente se deshabilitará el acceso SSH mediante contraseña.

# Creamos un usuario para la administración
sudo adduser deploy

# Añadimos el usuario al grupo sudo
sudo usermod -aG sudo deploy

# Creamos el directorio para la clave SSH pública
sudo install -d -m 700 -o deploy -g deploy /home/deploy/.ssh

# Copie la clave pública del usuario actual al directorio deploy
sudo cp ~/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys

# Corregimos el propietario y los permisos del archivo de claves
sudo chown deploy:deploy /home/deploy/.ssh/authorized_keys
sudo chmod 600 /home/deploy/.ssh/authorized_keys

Si la clave aún no se ha creado en el equipo de trabajo, ejecútelo localmente:

# Creamos un par de claves moderno Ed25519
ssh-keygen -t ed25519 -a 100 -C "nats-admin"

# Copiamos la clave pública al servidor
ssh-copy-id deploy@SERVER_IP

Compruebe el acceso:

# Abra una nueva sesión SSH y compruebe que sudo funciona
ssh deploy@SERVER_IP
sudo -v

Configuración básica de SSH

Cree un archivo drop-in independiente en lugar de editar el archivo de configuración principal sin necesidad. El número de puerto 2222 indicado a continuación es un ejemplo. Si cambia el puerto SSH, permítalo primero en el firewall.

# Creamos la configuración de SSH para prohibir root y las contraseñas
sudo tee /etc/ssh/sshd_config.d/ hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF

# Comprobamos la sintaxis de la configuración de SSH
sudo sshd -t

# Aplicamos la configuración sin interrumpir las sesiones activas
sudo systemctl reload ssh

En un entorno real, el archivo debe llamarse sin un espacio después del directorio. Comando correcto de creación:

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

Actualización del sistema y paquetes básicos

# Actualizamos los índices de paquetes e instalamos las actualizaciones de seguridad
sudo apt update && sudo apt full-upgrade -y

# Instalamos herramientas de administración y actualizaciones automáticas
sudo apt install -y \
  ca-certificates curl gnupg jq unzip vim htop lsof \
  ufw fail2ban unattended-upgrades apt-transport-https

# Activamos la instalación automática de actualizaciones de seguridad
sudo dpkg-reconfigure -plow unattended-upgrades

Firewall y fail2ban

Antes de activar UFW, permita SSH; de lo contrario, podría perder el acceso. El puerto 80 es necesario para que Certbot realice la comprobación HTTP y renueve el certificado, el 443 para la monitorización HTTPS mediante Caddy y el 4222 para los clientes de NATS.

# Permitimos SSH, HTTP, HTTPS y el puerto TLS de NATS
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 4222/tcp

# Activamos el firewall con una política de denegación de conexiones entrantes
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw --force enable

# Comprobamos las reglas activas
sudo ufw status verbose

El puerto de monitorización 8222 no se abre deliberadamente. En la configuración de NATS se vinculará a 127.0.0.1. Puede activar Fail2ban para proteger SSH:

# Iniciamos fail2ban y lo añadimos al arranque automático
sudo systemctl enable --now fail2ban

# Comprobamos el estado de la protección SSH
sudo fail2ban-client status sshd

6. Instalación del software — paso a paso

En 2026, para este escenario utilizamos Docker Engine desde el repositorio oficial de Docker, Compose Plugin y la imagen de NATS 2.11.x. La versión exacta del parche puede cambiar, por lo que en production es recomendable fijar un digest concreto después de realizar las pruebas.

Paso 1. Instalación de Docker Engine

# Eliminamos los paquetes antiguos potencialmente conflictivos
sudo apt remove -y docker.io docker-doc docker-compose podman-docker containerd runc || true

# Creamos el directorio para las claves de los repositorios
sudo install -m 0755 -d /etc/apt/keyrings

# Descargamos la clave oficial de Docker
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc

# Hacemos que la clave esté disponible para su lectura por el gestor de paquetes
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Añadimos el repositorio oficial de Docker para 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

# Actualizamos el índice e instalamos Docker Engine y Compose Plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

Para no utilizar sudo antes de cada comando de Docker, añada el usuario al grupo. El grupo proporciona prácticamente acceso root, por lo que solo debe añadir a administradores de confianza.

# Permitimos que el usuario deploy administre Docker
sudo usermod -aG docker deploy

# Reinicie la sesión SSH y, a continuación, compruebe Docker
docker run --rm hello-world

# Comprobamos las versiones del software instalado
docker version
docker compose version

Paso 2. Creación de los directorios del proyecto

# Creamos los directorios de configuración, certificados y copias de seguridad
sudo install -d -m 750 /opt/nats/{config,certs,backups,caddy}

# Transferimos el directorio del proyecto al usuario deploy
sudo chown -R deploy:deploy /opt/nats

# Accedemos al directorio de trabajo
cd /opt/nats

Paso 3. Instalación de Certbot y emisión del certificado

Las conexiones TLS de NATS requieren un certificado de dominio. Supongamos que el dominio es nats.example.com y que el registro DNS A ya apunta a la dirección IPv4 del servidor. Sustituya el dominio y el email por sus propios valores.

# Instalamos Certbot desde el repositorio de Ubuntu
sudo apt install -y certbot

# Detenemos temporalmente el servicio que podría ocupar el puerto 80
sudo systemctl stop caddy 2>/dev/null || true

# Emitimos el certificado mediante el desafío HTTP-01
sudo certbot certonly --standalone \
  --preferred-challenges http \
  -d nats.example.com \
  --email [email protected] \
  --agree-tos \
  --no-eff-email

Los certificados de Let’s Encrypt se renuevan cada 90 días. Certbot normalmente instala un systemd timer. Puede comprobarlo así:

# Comprobamos la renovación automática del certificado
sudo systemctl list-timers 'certbot'

# Realizamos una prueba dry-run sin emitir un certificado nuevo
sudo certbot renew --dry-run

Paso 4. Creación del usuario de NATS y de los secretos

Las contraseñas no deben escribirse directamente en la configuración, el repositorio ni en la línea de comandos que quedará registrada en el historial del shell. Genere valores URL-safe y guárdelos en un archivo con permisos 600.

# Generamos contraseñas aleatorias sin caracteres problemáticos para YAML y 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)

# Escribimos los secretos en un archivo env local
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

# Impedimos que otros usuarios lean el archivo
chmod 600 /opt/nats/.env

# Mostramos solo los nombres de las variables, no los secretos
cut -d= -f1 /opt/nats/.env

Paso 5. Obtención de la imagen oficial de NATS

# Descargamos la imagen oficial de NATS de la rama 2.11 Alpine
docker pull nats:2.11-alpine

# Comprobamos que la imagen esté disponible localmente
docker image ls nats

Para production, después de realizar las pruebas, puede sustituir la etiqueta flotante por una etiqueta de parche o un digest concretos. Esto evita cambios inesperados de comportamiento en el siguiente docker compose pull.

7. Configuración

Configuración de NATS

Cree el archivo /opt/nats/config/nats.conf. Los valores entre comillas que contienen construcciones como $NATS_APP_PASSWORD se sustituirán desde el entorno del contenedor. JetStream almacena los datos en el directorio /data/jetstream, que se conectará a un volume persistente.

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

El parámetro max_file_store es el límite superior del almacenamiento de archivos de JetStream, no el tamaño de un disco asignado automáticamente. El valor debe ser inferior al espacio libre en el VPS. Si el disco se llena, la publicación y el mantenimiento de los streams comenzarán a finalizar con errores.

En production, es mejor utilizar usuarios separados con los permisos mínimos para cada aplicación. El administrador no debe utilizarse en el código de la aplicación. En el ejemplo, el usuario app solo puede trabajar con los subjects events.>, jobs.> y las direcciones inbox.

Permisos de los certificados

Docker debe poder ver los certificados de Let’s Encrypt. La carpeta /etc/letsencrypt/live contiene enlaces simbólicos, por lo que se debe montar el directorio completo /etc/letsencrypt en modo read-only.

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

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

Docker Compose

Cree el archivo /opt/nats/compose.yaml. El contenedor no publica externamente el puerto de monitorización: la entrada 127.0.0.1:8222:8222 limita el acceso a la dirección loopback del servidor.

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

Después del inicio, compruebe los logs. Un error que indique la imposibilidad de leer privkey.pem suele significar un problema con el montaje del certificado o con los permisos de acceso. Un error sobre un parámetro de configuración desconocido indica una incompatibilidad de sintaxis con la versión de 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 para la monitorización mediante Caddy

Los clientes de NATS utilizan TLS directamente en el puerto 4222. Caddy no se necesita para hacer proxy del protocolo NATS, sino para publicar de forma segura la monitorización HTTP. Para ello, instale Caddy desde el repositorio oficial o el paquete de su SO y, a continuación, cree la configuración.

# Устанавливаем 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

Cree el registro DNS nats-monitor.example.com en el mismo servidor y el archivo /etc/caddy/Caddyfile. El hash de la contraseña se puede obtener con el comando 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 obtiene automáticamente un certificado HTTPS para el dominio de monitorización. No mezcle este certificado con el certificado de NATS si no ha comprobado que los clientes se conectan al nombre correcto. Para NATS, el certificado debe contener el nombre indicado en la URL del cliente, por ejemplo nats.example.com.

Comprobación de TLS y conexión del cliente

Puede comprobar el certificado con OpenSSL. El comando debe finalizar sin errores de comprobación de la cadena si el DNS y el certificado están configurados correctamente.

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

Para realizar una prueba funcional, instale la CLI de NATS desde la versión oficial de NATS CLI. Es preferible fijar la versión según las release notes del proyecto; a continuación se muestra la comprobación del comando ya instalado.

# Проверяем, что 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

Si las variables no se han cargado en la sesión de shell actual, léalas desde el archivo únicamente en una sesión administrativa interactiva:

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

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

Creación de un stream y un consumer

El ejemplo crea un stream de eventos de pedidos con almacenamiento en archivos y un periodo de retención de siete días. Para la cola de tareas, utilice un stream separado y otra retention policy. No incluya en un mismo stream tipos de mensajes no relacionados sin necesidad: esto complica los límites y la limpieza.

# Создаём поток для событий заказов с хранением на диске
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

En production, establezca el tamaño máximo del mensaje tanto en la aplicación como en el servidor. Es preferible almacenar los payload grandes en un almacenamiento de objetos y transmitir mediante NATS el identificador del archivo, el tipo de evento y los metadatos. Esto reduce la carga del disco y acelera la replicación.

8. Copias de seguridad y mantenimiento

Qué es necesario guardar

La copia de seguridad debe incluir la configuración de NATS, el archivo Compose, los secretos, la estrategia de certificados y los datos de JetStream. Una sola copia del contenedor no es suficiente: el contenedor se puede recrear, pero no se debe perder el volume con los mensajes ni el estado del consumer.

  • /opt/nats/config/nats.conf — configuración del servidor.
  • /opt/nats/compose.yaml — método de lanzamiento.
  • /opt/nats/.env — secretos almacenados de forma cifrada en la copia de seguridad.
  • Docker volume nats_jetstream_data — datos de JetStream almacenados en archivos.
  • Configuraciones de stream y consumer — conviene exportarlas por separado mediante CLI.
  • Información sobre DNS, dominios y el procedimiento de emisión de certificados.

No copie los archivos live de JetStream con un simple rsync durante una escritura intensiva ni considere que dicha instantánea sea coherente de forma garantizada. Para un nodo pequeño, es más fiable detener NATS durante una breve ventana, copiar los datos y volver a iniciarlo. Para minimizar el tiempo de inactividad, utilice instantáneas del disco del proveedor, si se crean de forma atómica.

Exportación de la configuración de 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 y almacenamiento compatible con S3

Es mejor almacenar la copia de seguridad fuera del VPS: en un almacenamiento de objetos compatible con S3 o en un servidor independiente situado en otra zona. Restic cifra los datos antes de enviarlos, por lo que el proveedor de almacenamiento no puede ver el contenido del archivo. Las contraseñas de Restic y S3 solo deben estar disponibles para 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'

Cree un script. Detiene el contenedor, archiva el Docker volume y la configuración, y luego inicia NATS. Durante la operación, el broker no estará disponible, por lo que debe elegir una ventana con el menor tráfico posible.

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'

El script anterior guarda el archivo del volume después de detener NATS. Compruebe que el contenedor realmente haya vuelto al estado Up y que el healthcheck se haya ejecutado correctamente:

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

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

Programador 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

La copia de seguridad solo se considera operativa después de una restauración de prueba. Cree periódicamente un directorio temporal, descargue el último snapshot y compruebe que la configuración y los datos se puedan extraer del archivo. Para sistemas críticos, pruebe por separado el inicio de NATS en un VPS nuevo.

Actualizaciones de NATS y del sistema operativo

Actualizar un único nodo de NATS no es un rolling update: el contenedor se reiniciará y los clientes perderán las conexiones. Antes de actualizar, haga una copia de seguridad, revise las release notes, asegúrese de la compatibilidad de las bibliotecas cliente y prepare una 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

En un clúster de tres o más nodos, la actualización se puede realizar nodo por nodo, controlando el quorum y el estado de JetStream. Para un servidor único, es más seguro utilizar una ventana planificada. No elimine el Docker volume antiguo ni ejecute docker compose down -v si no pretende eliminar los datos.

Observabilidad y control del disco

# Проверяем свободное место на файловой системе
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

Configure una alerta cuando el disco alcance el 70–80 %, aumenten los mensajes pendientes o crezca el número de entregas repetidas. Para una explotación más seria, conecte el endpoint de Prometheus y Grafana, pero no exponga los endpoints de diagnóstico sin autenticación ni restricciones de red.

9. Troubleshooting y FAQ

¿Por qué el cliente recibe el error TLS handshake o certificate verify failed?

Compruebe que el cliente se conecte al nombre de dominio presente en el certificado y no a una dirección IP. Ejecute openssl s_client -connect domain:4222 -servername domain y compruebe el registro DNS A, la validez del certificado y la cadena fullchain.pem. Asegúrese de que Certbot no haya emitido un certificado para otro dominio. En el cliente, indique la URL TLS y el almacén del sistema de CA de confianza; no se debe desactivar la verificación del certificado en production.

El contenedor NATS se detiene inmediatamente después del inicio. ¿Qué se debe comprobar?

Comience con docker compose logs nats. Las causas frecuentes son una ruta incorrecta a nats.conf, un error de sintaxis, la ausencia del certificado o la imposibilidad de leer una variable de entorno. Ejecute docker compose config para ver la configuración final y compruebe la existencia de los archivos en /etc/letsencrypt/live/домен/. Después de corregirlo, ejecute docker compose up -d y vuelva a revisar los logs.

¿Por qué JetStream no conserva los datos después de recrear el contenedor?

Compruebe que se utilice exactamente el volume nats_jetstream_data y no un bind mount temporal dentro del contenedor. El comando docker volume inspect nats_jetstream_data mostrará su ubicación y nombre. No se debe ejecutar docker compose down -v: el indicador -v elimina el volume. Compruebe también que la configuración incluya store_dir: /data/jetstream y que el directorio /data esté conectado a un volume permanente.

Aparece el error “permissions violation” al publicar un mensaje. ¿Qué se debe hacer?

Esto significa que el usuario no tiene permiso para publicar o suscribirse al subject seleccionado. Compare el subject de la aplicación con las reglas del usuario en la sección authorization. El usuario app del ejemplo solo tiene permisos para events.>, jobs.> y _INBOX.>. Después de modificar la configuración, recree el contenedor y vuelva a conectarse: los permisos se aplican al establecer la sesión del cliente.

¿Qué configuración mínima de VPS es adecuada?

Para pruebas y un sistema interno pequeño, bastan 2 vCPU, 2 GB de RAM y un SSD de 40–60 GB. Para una pequeña instalación production, es mejor elegir 4 vCPU, 8 GB de RAM y NVMe de 100 GB o más, especialmente si los mensajes se almacenan durante varios días. Son importantes unos IOPS estables, espacio libre y una IPv4 pública. Si el volumen de datos crece rápidamente, aumente primero el disco y configure la retención, en lugar de limitarse a añadir CPU.

¿Qué elegir: VPS o dedicated para esta tarea?

El VPS es adecuado para la mayoría de las instalaciones pequeñas de NATS JetStream: es más económico, se escala verticalmente con mayor facilidad y es suficiente con una escritura moderada. Dedicated está justificado cuando existe una carga constante y elevada sobre el disco, grandes flujos, requisitos estrictos de latencia o la necesidad de excluir la influencia de otras máquinas virtuales. Sin embargo, dedicated no resuelve automáticamente el problema de la alta disponibilidad. Para ello se necesitan varios nodos, replicación y copias de seguridad.

¿Por qué aumenta la cantidad de mensajes pendientes del consumer?

El consumer recibe los mensajes más lentamente de lo que se publican. Compruebe la CPU y la memoria de los workers, las latencias de las API externas, el número de procesadores paralelos y el parámetro max_ack_pending. Consulte la información con el comando nats consumer info ORDERS order-workers. Aumentar el límite sin analizar la causa es peligroso: puede provocar un aumento del uso de memoria y de las entregas repetidas. Normalmente, la solución correcta es añadir workers, utilizar un procesamiento similar a una cola y configurar backoff.

¿Qué ocurrirá si se acaba el espacio en disco?

JetStream dejará de aceptar correctamente nuevos mensajes, y Docker y el propio sistema operativo pueden empezar a funcionar de forma inestable. Compruebe inmediatamente df -h, los tamaños de los stream y los logs de NATS. Elimine las imágenes de Docker y los logs innecesarios, pero no elimine manualmente el volume de JetStream. Después, reduzca la retención, el tamaño máximo del stream o amplíe el disco. Tras la recuperación, compruebe el consumer y la publicación repetida de un mensaje de prueba.

¿Se puede abrir el puerto 8222 para la monitorización remota?

No se debe abrir para todo Internet: la monitoring API expone información de diagnóstico y no es un sistema completo de control de acceso. Mantenga el puerto en 127.0.0.1 y, para el acceso remoto, utilice Caddy con HTTPS y basic authentication, una VPN o un túnel SSH. Para una consulta temporal, puede ejecutar ssh -L 8222:127.0.0.1:8222 deploy@server y abrir después http://127.0.0.1:8222 localmente.

10. Conclusiones y próximos pasos

En el VPS se ha desplegado NATS JetStream con Docker, TLS en el puerto del cliente, autorización, almacenamiento persistente y monitorización HTTPS. La configuración separa el acceso de las aplicaciones y del administrador, mientras que Restic permite almacenar las copias de seguridad cifradas fuera del servidor.

A continuación, conviene configurar la monitorización del uso del disco y del lag del consumer, comprobar periódicamente la restauración desde la copia de seguridad y fijar las versiones de las imágenes de Docker. A medida que aumente la carga, pase a varios nodos de NATS con replicación de JetStream, failure domains independientes y un plan de rolling update.

  • Defina la retención de cada stream basándose en el volumen real de mensajes.
  • Añada Prometheus/Grafana u otro sistema controlado de recopilación de métricas.
  • Pruebe la restauración en un servidor temporal antes de necesitarla durante una emergencia.

¿Te fue útil esta guía?

Tus comentarios nos ayudan a mejorar nuestras guías.

Compartir esta publicación:

Envía esta guía a alguien a quien pueda resultarle útil.

Telegram VKVK WhatsApp Facebook LinkedIn XX

Despliegue de NATS JetStream en un VPS: Docker, TLS, autorización y persistencia de datos
support_agent
Valebyte Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.