SSD Nodes Learn Hosting plans →
Guías Matt ConnorPor Matt Connor · Actualizado 2026-08-27

Autohospedar ntfy con Docker para alertas del servidor

Ejecuta ntfy en tu VPS con Docker Compose y TLS. Protege topics con usuarios y ACLs, y envía alertas desde cron y unidades systemd OnFailure.

Qué hace un servidor ntfy autohospedado

Un servidor ntfy autohospedado convierte una solicitud HTTP POST en una notificación push en el teléfono. Publique con curl y el mensaje llegará a la aplicación de Android, la aplicación de iOS, una pestaña del navegador o cualquier otro cliente que pueda mantener abierta una conexión HTTP. No es necesario instalar una biblioteca cliente ni ejecutar un message broker.

ntfy direcciona los mensajes mediante topics. Un topic es un nombre en la ruta URL, como https://ntfy.example.com/alerts, y existe desde el momento en que alguien publica en él. En una instalación predeterminada, cualquiera que conozca ese nombre puede leer el topic y escribir en él. Por eso la documentación del proyecto compara el nombre del topic con una contraseña. Este modelo es adecuado para el servicio público ntfy.sh. No es adecuado para un servidor que transporta los fallos de las copias de seguridad. Por eso esta guía activa la autenticación antes de enviar el primer mensaje.

Qué necesita antes de empezar

Necesita un VPS con Ubuntu 24.04 o Debian 13, Docker Engine y el complemento Compose, un nombre de dominio y muy poca RAM. Cree un registro A de DNS (sistema de nombres de dominio) que apunte ntfy.example.com a la dirección IP pública del servidor. Después, confirme que resuelve correctamente antes de continuar.

dig +short ntfy.example.com
sudo ufw allow 80,443/tcp
sudo ufw status

dig debe mostrar la IP de su servidor. La emisión del certificado falla si no muestra nada, porque la autoridad de certificación comprueba el nombre desde el exterior. El puerto 80 permanece abierto porque ACME (entorno de gestión automática de certificados), el protocolo que utiliza Let's Encrypt, lo necesita para el desafío HTTP. El contenedor de ntfy no expone ningún puerto público.

Escriba el archivo de configuración de ntfy

La imagen de Docker no incluye un archivo de configuración, por lo que debe crearlo. Todos los comandos posteriores de esta guía lo leen. Primero, busque el ID de usuario y el ID de grupo con los que se ejecutará el contenedor.

id -u
id -g
sudo install -d -o "$(id -u)" -g "$(id -g)" /etc/ntfy /var/cache/ntfy /var/lib/ntfy
sudo nano /etc/ntfy/server.yml
base-url: "https://ntfy.example.com"
listen-http: ":2586"
behind-proxy: true
cache-file: "/var/cache/ntfy/cache.db"
cache-duration: "12h"
auth-file: "/var/lib/ntfy/user.db"
auth-default-access: "deny-all"
enable-login: true
enable-signup: false

Cuatro de esas líneas son fundamentales. base-url debe ser la dirección HTTPS pública exacta, porque ntfy genera a partir de ella los enlaces de los archivos adjuntos y las peticiones de la propia aplicación web. Un valor incorrecto hace que la aplicación web se cargue y después falle en todas las operaciones. listen-http: ":2586" se enlaza a todas las interfaces dentro del contenedor. Esto parece poco cuidadoso, pero es correcto: el contenedor tiene su propio espacio de nombres de red, por lo que enlazarse a 127.0.0.1 allí haría que el puerto no fuera accesible desde el host y el puerto publicado por Docker no podría conectarse. auth-default-access: "deny-all" define toda la postura de seguridad, porque deniega las operaciones de lectura y escritura a cualquiera que no tenga una autorización explícita. behind-proxy: true indica a ntfy que tome la dirección del cliente de la cabecera X-Forwarded-For, de modo que los límites de tasa cuenten a los visitantes reales en lugar de contar el reverse proxy como un único cliente con mucha actividad.

enable-login: true permite que la aplicación web y las aplicaciones móviles inicien sesión con una contraseña. enable-signup permanece en false, porque permitir que los usuarios creen cuentas por sí mismos en un servidor privado deja una vía de acceso innecesaria.

sudo chown "$(id -u):$(id -g)" /etc/ntfy/server.yml
sudo chmod 600 /etc/ntfy/server.yml

Ejecutar ntfy con Docker Compose

Coloque esto en /opt/ntfy/compose.yaml y sustituya 1000:1000 por los dos números id -u y id -g mostrados anteriormente.

services:
  ntfy:
    image: binwiederhier/ntfy:v2.27.0
    container_name: ntfy
    command: serve
    user: "1000:1000"
    environment:
      - TZ=UTC
    volumes:
      - /etc/ntfy:/etc/ntfy
      - /var/cache/ntfy:/var/cache/ntfy
      - /var/lib/ntfy:/var/lib/ntfy
    ports:
      - "127.0.0.1:2586:2586"
    restart: unless-stopped
cd /opt/ntfy
sudo docker compose up -d
sudo docker compose logs ntfy
curl -s http://127.0.0.1:2586/v1/health

Un servidor operativo responde en {"healthy":true}. Hay dos detalles deliberados en ese archivo de Compose. La imagen está fijada en v2.27.0, la versión actual en agosto de 2026, en lugar de latest, porque con latest el siguiente docker compose pull cambia la versión del servidor y usted se entera después al revisar el registro de cambios. El puerto se publica como 127.0.0.1:2586:2586, por lo que el contenedor sólo es accesible desde la dirección de loopback del host. Escriba 2586:2586 y Docker insertará sus propias reglas de firewall antes que las suyas. Como resultado, el puerto responderá desde Internet aunque ufw status indique que está cerrado. Estas dos prácticas también se aplican al siguiente contenedor que añada: un relay RustDesk autohospedado fija la etiqueta de su imagen del mismo modo, pero no puede ocultarse detrás de loopback porque sus puertos de señalización y relay deben responder desde Internet.

Si curl muestra Connection refused, lea el registro del contenedor. Un error de permisos en /var/lib/ntfy/user.db significa que la línea user: no coincide con el propietario de esos directorios. Por eso, el proceso no puede crear su propia base de datos y termina. La guía básica de Docker Compose para un VPS explica con más detalle la propiedad de los volúmenes y las políticas de reinicio.

Configurar TLS delante con Caddy

Caddy solicita y renueva el certificado por su cuenta. Es la forma más directa de disponer de TLS (seguridad de la capa de transporte) operativo.

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 chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy

Sustituya el contenido de /etc/caddy/Caddyfile por estas tres líneas.

ntfy.example.com {
    reverse_proxy 127.0.0.1:2586
}
sudo systemctl reload caddy
curl -s https://ntfy.example.com/v1/health

La misma {"healthy":true} mediante HTTPS confirma que todo el recorrido funciona. Un 502 de Caddy indica que ntfy no está escuchando. Compruébelo con sudo ss -lntp | grep 2586. Un error de certificado suele indicar que el registro DNS es incorrecto o que el puerto 80 está bloqueado. sudo journalctl -u caddy -n 50 indica cuál de los dos problemas existe. Para añadir otro servicio más adelante, basta con incorporar otro bloque de hostname en el mismo Caddyfile. Así, algo como Halcyon, una interfaz de videoclub de los años 90 para su biblioteca de Jellyfin puede quedar disponible en un segundo subdominio del mismo servidor.

Si ya ejecuta nginx, copie la configuración de proxy que documenta ntfy: proxy_http_version 1.1, proxy_buffering off, proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for y establezca tiempos de espera de lectura y envío de al menos tres minutos. Un suscriptor mantiene abierta una conexión HTTP mientras está escuchando. nginx cierra de forma predeterminada una conexión upstream inactiva después de 60 segundos. Por eso, los suscriptores se reconectan continuamente y se pierden los mensajes enviados durante el intervalo.

Cree usuarios y restrinja el acceso a los temas

La autenticación está activada y todavía nadie tiene acceso a nada. Ese es el objetivo. Cree una cuenta de administrador para usted y una cuenta de máquina para los scripts. Estos comandos leen /etc/ntfy/server.yml desde dentro del contenedor. Por eso el archivo de configuración está montado como volumen.

sudo docker compose exec ntfy ntfy user add --role=admin admin
sudo docker compose exec ntfy ntfy user add robot
sudo docker compose exec ntfy ntfy user list

Cada comando solicita una contraseña. Un administrador ignora la lista de control de acceso y puede leer y publicar en todos los temas. Reserve esa cuenta para usted y para la aplicación del teléfono. robot es un usuario normal sin ningún acceso hasta que le conceda permisos.

sudo docker compose exec ntfy ntfy access robot alerts write
sudo docker compose exec ntfy ntfy access robot "alerts_*" write
sudo docker compose exec ntfy ntfy access

Una ACL (lista de control de acceso) contiene un usuario, un tema y un permiso. El tema puede ser un nombre literal o un patrón en el que * coincide con cualquier texto. Así, alerts_* cubre alerts_backup y alerts_db sin ejecutar un comando por cada host. El permiso write significa que sólo puede publicar. De este modo, un token robado de un trabajo de cron no puede suscribirse ni leer lo que publicó. El nombre de usuario especial everyone define lo que puede hacer un visitante no autenticado. Úselo sólo para abrir algo de forma deliberada al público, como ntfy access everyone status read.

Los scripts deben llevar un token, no su contraseña.

sudo docker compose exec ntfy ntfy token add robot

El comando muestra un token que comienza por tk_. Un token hereda exactamente los permisos del usuario al que pertenece. Por tanto, este token puede publicar en los temas alerts y no puede hacer nada más. ntfy token list muestra los elementos existentes y ntfy token remove revoca uno sin modificar la contraseña del usuario.

Envía tu primer mensaje y comprueba que el bloqueo funciona

Empieza comprobando que la puerta está cerrada.

curl -s -o /dev/null -w '%{http_code}\n' -d "hello" https://ntfy.example.com/alerts

Esto muestra 403, y 403 es la respuesta correcta: auth-default-access: "deny-all" rechaza una publicación anónima. Ahora envía un mensaje real.

curl -H "Authorization: Bearer tk_REPLACE_WITH_YOUR_TOKEN" \
  -H "Title: Nightly backup finished" \
  -H "Priority: default" \
  -H "Tags: white_check_mark" \
  -d "42 GB copied in 11 minutes" \
  https://ntfy.example.com/alerts

El servidor responde con el mensaje almacenado en formato JSON. Así sabes que lo aceptó y no lo descartó. Title es la primera línea en negrita. Priority acepta valores del 1 al 5 o nombres desde min hasta urgent, y determina si el teléfono emite un sonido. Tags se convierten en emoji en la notificación cuando el nombre coincide con un código corto de emoji conocido, y permanecen como texto sin formato cuando no coincide.

Para supervisar un topic desde un terminal, transmite su contenido:

curl -s -u admin https://ntfy.example.com/alerts/raw

curl solicita la contraseña. Cada mensaje llega en una sola línea. Las líneas vacías que aparecen de vez en cuando son mensajes keepalive. Si abres https://ntfy.example.com en un navegador e inicias sesión con la misma cuenta, obtienes la versión web del mismo flujo.

Establezca límites de tasa para que un script no pueda saturar el servidor

De forma predeterminada, cada visitante recibe un depósito de 60 solicitudes, que se repone a razón de una solicitud cada 5 segundos. Este límite es generoso para un servidor privado, y un script atascado en un bucle de reintentos lo consumirá por completo. Añada límites a server.yml.

visitor-request-limit-burst: 30
visitor-request-limit-replenish: "10s"
visitor-message-daily-limit: 500
sudo docker compose restart ntfy

Un visitante que supera el límite recibe HTTP 429 en lugar de un mensaje entregado. El límite se cuenta por dirección del visitante, por eso behind-proxy: true es tan importante: sin esta configuración, ntfy sólo ve la dirección de Caddy, todos los clientes cuentan como el mismo visitante y un script ruidoso agota el depósito que comparten el teléfono y los demás servidores.

Alerta de un trabajo de cron que falla

No incluya el token en la línea de comandos. ps aux muestra la línea de comandos completa de todos los procesos en ejecución a todos los usuarios del sistema, por lo que un token pasado con -H puede ser leído por cualquier cuenta local mientras curl esté en ejecución. Un archivo de configuración de curl evita este problema.

sudo install -d -m 700 /etc/ntfy-alert
printf 'header = "Authorization: Bearer tk_REPLACE_WITH_YOUR_TOKEN"\n' | sudo tee /etc/ntfy-alert/curlrc
sudo chmod 600 /etc/ntfy-alert/curlrc

Ahora envuelva el trabajo. Guarde esto como /usr/local/bin/backup-with-alert.sh y haga chmod 750 ejecutable.

#!/bin/bash
out=$(/usr/local/bin/backup.sh 2>&1)
code=$?
if [ "$code" -ne 0 ]; then
  printf '%s' "$out" | tail -c 1000 | curl -K /etc/ntfy-alert/curlrc \
    -H "Title: backup.sh failed with exit $code" \
    -H "Priority: high" \
    -H "Tags: warning" \
    --data-binary @- \
    https://ntfy.example.com/alerts
fi
exit "$code"
17 3 * * * /usr/local/bin/backup-with-alert.sh >> /var/log/backup-alert.log 2>&1

$? se captura en la línea inmediatamente posterior al comando, porque la ejecución del siguiente comando lo sobrescribiría. La salida pasa por tail -c 1000 porque ntfy impone un tamaño máximo para los mensajes y una notificación no sustituye a un visor de registros. El exit "$code" de cierre conserva el estado original, por lo que cualquier otro componente que supervise este trabajo seguirá viendo un fallo. Pruebe todo el proceso haciendo que el script apunte a /bin/false durante una ejecución.

Una rama de error que nunca se ejecuta es peor que no tener alertas, porque da la impresión de que el silencio significa que todo funciona. Cron proporciona al trabajo un entorno casi vacío y un PATH mucho más corto que el de su shell de inicio de sesión, por lo que un script que funciona al ejecutarlo manualmente puede terminar antes de llegar a la línea de curl. La guía sobre por qué no se ejecuta un trabajo de cron explica estos problemas del entorno. Use rutas absolutas en todo el script y lea el archivo de registro después de la primera ejecución programada en lugar de dar por hecho que todo funciona.

Alertar cuando una unidad de systemd falla

Cron se ocupa de las tareas programadas. Los servicios de larga duración necesitan OnFailure=, que systemd ejecuta cada vez que una unidad entra en el estado failed. Cree una unidad de plantilla y reutilícela para todos los servicios del servidor. Guárdela como /etc/systemd/system/ntfy-unit-failed@.service.

[Unit]
Description=Send an ntfy alert because %i failed

[Service]
Type=oneshot
ExecStart=/usr/local/bin/ntfy-unit-failed %i

Después, /usr/local/bin/ntfy-unit-failed, con permisos 750:

#!/bin/bash
unit="$1"
journalctl -u "$unit" -n 15 --no-pager -o cat | tail -c 1000 | curl -K /etc/ntfy-alert/curlrc \
  -H "Title: $unit failed on $(hostname -s)" \
  -H "Priority: urgent" \
  -H "Tags: rotating_light" \
  --data-binary @- \
  https://ntfy.example.com/alerts

Asóciela a un servicio mediante un drop-in para que una actualización del paquete no sobrescriba sus cambios.

sudo systemctl edit myapp.service
[Unit]
OnFailure=ntfy-unit-failed@%n.service

%n se expande al nombre completo de la unidad. Por tanto, la instancia se convierte en ntfy-unit-failed@myapp.service. Dentro de la plantilla, %i entrega myapp.service al script como primer argumento. Así, una sola plantilla puede servir para cualquier unidad. Compruebe que funciona con una unidad que falle intencionadamente. Guárdela como /etc/systemd/system/ntfy-selftest.service.

[Unit]
Description=Deliberately failing unit
OnFailure=ntfy-unit-failed@%n.service

[Service]
Type=oneshot
ExecStart=/bin/false
sudo systemctl daemon-reload
sudo systemctl start ntfy-selftest.service

El comando de inicio termina con un código distinto de cero y muestra Job for ntfy-selftest.service failed because the control process exited with error code. El teléfono debería emitir una alerta aproximadamente un segundo después. Elimine la unidad de prueba al terminar.

Hay un detalle importante. OnFailure= sólo se ejecuta cuando una unidad alcanza el estado failed. Un servicio con Restart=always puede no alcanzarlo, porque systemd lo reinicia continuamente. La unidad sólo falla después de superar StartLimitBurst reinicios dentro de StartLimitIntervalSec. Establezca esos dos valores en cualquier servicio del que quiera recibir alertas. De lo contrario, un bucle de fallos puede ejecutarse silenciosamente durante días. Los temporizadores son un reemplazo más adecuado para el patrón de cron anterior, porque la unidad de servicio de un temporizador obtiene OnFailure= automáticamente. La guía sobre servicios y temporizadores de systemd en un VPS explica cómo convertir uno.

Conecte un monitor de disponibilidad al mismo topic

Uptime Kuma, el monitor de estado autohospedado, incluye un tipo de notificación para ntfy. Abra Settings, después Notifications y luego Setup Notification. Seleccione Ntfy, establezca la URL del servidor en https://ntfy.example.com y el topic en alerts, elija una prioridad y pegue el token de acceso robot. Envíe la notificación de prueba antes de guardar, porque un nombre de topic incorrecto falla de forma silenciosa con un permiso write que no lo incluye.

El límite real de esta configuración es el siguiente: un monitor que se ejecuta en el mismo VPS no puede avisarle de que el VPS está caído, y ntfy no puede entregar el aviso de que ntfy está caído. Ejecute el monitor en otra máquina y asígnele un segundo canal de notificación, como el correo electrónico, para el monitor que supervisa el propio ntfy. El tipo de monitor Push de Uptime Kuma cubre el otro punto ciego: el trabajo de cron llama a una URL push después de una ejecución correcta y Kuma genera una alerta cuando esas llamadas dejan de llegar. Una rama de error sólo se activa cuando se ejecuta el trabajo, por lo que no informa de un trabajo que nunca se inició.

¿Funciona ntfy autoalojado en Android y iPhone?

En Android, sí, sin limitaciones. Instale la aplicación desde Google Play o F-Droid, abra Settings, establezca el servidor predeterminado en https://ntfy.example.com, añada su cuenta en la pantalla de gestión de usuarios y suscríbase a alerts. La entrega instantánea mantiene un servicio en primer plano para que los mensajes lleguen incluso cuando el teléfono está en modo doze. La notificación permanente que la acompaña es un requisito de Android para los servicios en primer plano, no un error. La compilación de F-Droid no contiene código de Firebase, por lo que todas las suscripciones usan la entrega instantánea. ntfy también puede actuar como distribuidor de UnifiedPush, una alternativa abierta al servicio de notificaciones push de Google. Así, otras aplicaciones compatibles con UnifiedPush también pueden entregar notificaciones a través de su servidor.

En iOS, funciona con una dependencia que no puede eliminar. Apple sólo activa una aplicación en segundo plano mediante APNs (Apple push notification service), y sólo la entidad que posee las credenciales de firma de la aplicación puede enviarle notificaciones. Por tanto, su servidor no puede llegar directamente a la aplicación. ntfy resuelve esto mediante un relay: su servidor envía un poll_request que contiene el ID del mensaje a ntfy.sh. ntfy.sh lo reenvía mediante Firebase y APNs para activar la aplicación. Después, la aplicación obtiene el cuerpo del mensaje desde su servidor.

upstream-base-url: "https://ntfy.sh"

Tenga claro el coste de este mecanismo. El contenido del mensaje permanece en su servidor, pero el hecho de que haya llegado un mensaje y su ID pasan por una infraestructura que usted no administra. Sin este ajuste, las notificaciones de un servidor autoalojado en iPhone llegan tarde o no llegan, porque nada activa la aplicación. La única forma de eliminar el relay es compilar y distribuir usted mismo la aplicación de iOS con su propia cuenta de desarrollador de Apple y sus propias claves de APNs. Esto implica pagar una cuota anual y recompilar la aplicación para cada actualización. Si el relay no es aceptable en su caso, mantenga las alertas en Android o en la aplicación web de escritorio.

Copias de seguridad, actualizaciones y fijación de la imagen

Hay dos rutas que no se pueden regenerar: /etc/ntfy/server.yml y /var/lib/ntfy/user.db. La segunda contiene todos los usuarios, hashes de contraseñas, entradas de ACL y tokens, por lo que debe tratarse como una clave privada.

sudo tar czf ntfy-backup.tgz -C / etc/ntfy var/lib/ntfy
sudo chmod 600 ntfy-backup.tgz

Copie ese archivo fuera del servidor. cache.db sólo contiene mensajes recientes, correspondientes a 12 horas junto con el cache-duration anterior, por lo que perderlo no supone ningún coste relevante. Para actualizar, edite la etiqueta en el archivo compose y ejecute pull.

sudo docker compose pull
sudo docker compose up -d
curl -s https://ntfy.example.com/v1/health

Lea primero las notas de la versión. Las bases de datos SQLite se migran durante el arranque, por lo que no es seguro volver a una etiqueta anterior después de un cambio de esquema. Conserve la copia de seguridad que acaba de crear hasta que la nueva versión haya funcionado durante un día. Cada servicio del servidor tiene su propia lista breve de rutas que no se pueden regenerar, y la comparación de PhotoPrism e Immich determina esa lista y los comandos de copia de seguridad correspondientes para una biblioteca de fotos en un VPS del mismo tipo.

Gotify y Apprise

Gotify es la opción más pequeña: un solo binario con una interfaz web y una aplicación para Android. No admite comodines en los temas y no tiene cliente oficial para iOS. Esto encaja con un servidor privado cuyo único destino es Android. Apprise es una biblioteca de Python y una herramienta de línea de comandos, no un servidor. Distribuye un solo mensaje entre más de cien servicios, incluido ntfy. Esto resulta adecuado para un script que debe llegar a varios destinos al mismo tiempo. ntfy es el que proporciona un servidor, una API HTTP y aplicaciones para ambas plataformas móviles. Por eso suele ser la opción habitual para enviar alertas desde un servidor alquilado.

FAQ

¿Por qué la publicación en mi servidor ntfy devuelve 403?

Con auth-default-access: "deny-all" en server.yml, se rechaza la publicación anónima. Ese es el comportamiento previsto. Envíe las credenciales con -u user:pass o -H "Authorization: Bearer tk_...". Si ya envía un token y sigue obteniendo 403, el usuario asociado a ese token no tiene una entrada ACL que coincida con el topic. Ejecute ntfy access para mostrar la lista completa. Recuerde que una concesión write no permite suscribirse. Por tanto, una cuenta que publica correctamente seguirá siendo rechazada cuando intente leer el mismo topic.

¿Funcionan las notificaciones en iPhone con un servidor ntfy autohospedado?

Funcionan mediante un relay que no se puede evitar. Apple activa las aplicaciones sólo mediante APNs (Apple push notification service), y sólo el publicador de la aplicación puede enviarle datos. Por eso, ntfy reenvía a ntfy.sh un poll_request que contiene el ID del mensaje, y ntfy.sh lo retransmite al dispositivo. Configure upstream-base-url: "https://ntfy.sh" en server.yml y reinicie el contenedor. El cuerpo del mensaje se sigue obteniendo de su servidor. Sin esa configuración, las notificaciones de iOS se retrasan o no aparecen.

¿Por qué nunca llegó la alerta de ntfy de mi trabajo de cron?

Ejecute primero la línea de curl de forma independiente para confirmar que el token y el topic son correctos. Si funciona manualmente pero no desde cron, el fallo está antes de la alerta: cron ejecuta los trabajos con un entorno mínimo y un PATH corto. Por tanto, un script que llama a un comando por su nombre sin ruta puede terminar antes de llegar a la línea de curl. Use rutas absolutas, redirija la salida del trabajo a un archivo de registro y lea ese archivo después de la siguiente ejecución. Una respuesta 429 en lugar de una entrega indica que el límite de tasa funciona y que el script reintenta demasiado rápido.

¿Debería exponer ntfy en Internet público?

Las aplicaciones del teléfono deben acceder al servidor desde redes móviles. Por eso, un endpoint HTTPS público con auth-default-access: "deny-all" y ACL por topic es la configuración habitual. Es segura siempre que ningún topic pueda ser leído por everyone. Una instancia accesible sólo mediante VPN es adecuada cuando todos los suscriptores son máquinas que usted controla. No es una buena opción para teléfonos, porque la aplicación sólo recibe mensajes mientras el túnel está activo. Las alertas quedan en cola hasta que el teléfono vuelve a conectarse.