Evolution API Desconexión de Redis y Errores de Iptables en Configuración YunoHost/Docker

Describe el problema/error/pregunta

Entorno:

  • OS: Debian 12 (vía YunoHost)

  • Configuración: Evolution API ejecutándose en Docker junto con servicios de YunoHost (n8n, etc.)

  • Infraestructura: Alojado en un VPS propio

El problema: Estoy ejecutando Evolution API vía Docker Compose. A pesar de tener un servicio Redis definido en mi docker-compose.yml, los logs de la API están inundados con: [Redis] redis disconnected

Además, cuando intento reiniciar la pila con docker compose up -d, ocasionalmente me encuentro este error de red: Failed to Setup IP tables: Unable to enable ACCEPT OUTGOING rule: (iptables: No chain/target/match by that name)

Mi fragmento actual de docker-compose.yml:

  evolution_api:
    image: atendai/evolution-api:latest
    environment:
      - CACHE_REDIS_ENABLED=true
      - CACHE_REDIS_HOST=redis
      - CACHE_REDIS_PORT=6379
    depends_on:
      - redis

  redis:
    image: redis:7-alpine

Lo que he intentado:

  1. Cambiar CACHE_REDIS_HOST a redis://redis:6379.

  2. Ejecutar yunohost firewall reload.

  3. Intentar eludir el SSO nativo de YunoHost para n8n estableciendo el acceso como ‘Visitor’.

Preguntas:

  1. ¿Se sabe que el servicio Redis nativo de YunoHost o su gestión de iptables (AFW) entra en conflicto con la red interna de Docker?

  2. ¿Cómo puedo asegurar que el contenedor de Docker elude las reglas de firewall de YunoHost para mantener una conexión estable con su propio contenedor de Redis?

  3. ¿Hay reglas específicas de cadena DOCKER-USER que debería inyectar manualmente para detener los fallos de ACCEPT OUTGOING?

¿Cuál es el mensaje de error (si lo hay)?

Información sobre tu configuración de n8n

  • versión de n8n: 2.15.1
  • Base de datos (predeterminado: SQLite): predeterminado
  • Configuración de n8n EXECUTIONS_PROCESS (predeterminado: own, main): predeterminado
  • Ejecutando n8n vía (Docker, npm, n8n cloud, aplicación de escritorio): servicio systemd (YunoHost)
  • Sistema operativo: Debian 12

Mira si esto te ayuda.

Esto es muy probablemente un conflicto clásico entre el motor de networking de Docker y el firewall de YunoHost (AFW) en Debian 12.

La causa raíz es que YunoHost gestiona el firewall usando nftables (y anteriormente iptables), y cuando recarga o aplica reglas, a menudo vacía las cadenas de iptables. Docker crea sus propias cadenas personalizadas (como la cadena DOCKER) para manejar el enrutamiento de contenedores. Cuando YunoHost las vacía, Docker intenta agregar reglas a una cadena que ya no existe, resultando en el error: iptables: No chain/target/match by that name.

Como las reglas de networking están rotas, tu contenedor evolution_api no puede “ver” el contenedor redis, aunque estén en el mismo archivo compose. Esto lleva a la inundación de redis disconnected.

Aquí te presento la solución paso a paso para solucionar ambos problemas.

1. Corregir la Configuración (Evolution API)

La API de Evolution espera una URI de Conexión, no variables separadas de Host y Puerto. Estás usando CACHE_REDIS_HOST, que la API probablemente ignora en favor de CACHE_REDIS_URI.

Actualiza tu sección de entorno en docker-compose.yml: Elimina CACHE_REDIS_HOST y CACHE_REDIS_PORT y reemplázalos con CACHE_REDIS_URI.

# Cambia esto:
- CACHE_REDIS_ENABLED=true
- CACHE_REDIS_HOST=redis
- CACHE_REDIS_PORT=6379

# A esto:
- CACHE_REDIS_ENABLED=true
- CACHE_REDIS_URI=redis://redis:6379

(Nota: Si estás usando una contraseña para Redis, el formato es redis://:contraseña@redis:6379).

2. Resolver el Conflicto entre iptables y YunoHost

Para corregir el error Unable to enable ACCEPT OUTGOING rule y restaurar la conectividad entre contenedores, debes asegurar que Docker recree sus cadenas de networking después de que YunoHost haya inicializado el firewall.

La Solución Inmediata (Manual)

Ejecutar estos comandos en orden para limpiar el conflicto y forzar que Docker reconstruya sus reglas:

# 1. Recarga el firewall de YunoHost primero
yunohost firewall reload

# 2. Reinicia el demonio de Docker para forzar que reinecte sus cadenas en iptables
sudo systemctl restart docker

# 3. Levanta tu stack nuevamente
docker compose up -d

La Solución Permanente (Automatización)

Como YunoHost puede recargar el firewall durante actualizaciones o a través de la WebUI, las reglas de Docker se romperán nuevamente. Para prevenir esto, puedes crear un override de systemd simple para asegurar que Docker se reinicie cada vez que el firewall cambie, o más simplemente, agregar un trabajo cron/hook.

Sin embargo, la forma más estable en YunoHost es asegurar que Docker sea lo último que se inicie. Si encuentras que esto sucede frecuentemente después de reinicios, ejecuta:

sudo systemctl enable docker

Y si recargas manualmente el firewall, siempre seguido por sudo systemctl restart docker.

Respuestas a tus preguntas específicas:

1. ¿Se sabe que la gestión nativa de Redis o iptables de YunoHost entra en conflicto?

Sí. La gestión del firewall de YunoHost es agresiva. No “conoce” las cadenas de iptables personalizadas de Docker. Cuando YunoHost recarga sus reglas, borra la cadena DOCKER. Por eso ves el error “No chain/target/match”—Docker está intentando comunicarse con una cadena que YunoHost acaba de eliminar.

2. ¿Cómo puedo asegurar que el contenedor de Docker omita el firewall de YunoHost?

La comunicación entre contenedores (Evolution API →→ Redis) ocurre en la Red Bridge de Docker a través de la cadena FORWARD. El firewall de YunoHost gestiona principalmente la cadena INPUT (tráfico que viene del mundo exterior). Los contenedores no necesitan “omitir” el firewall; simplemente necesitan que existan las reglas gestionadas por Docker. Reiniciar el demonio de Docker después de que el firewall esté activo es la única manera de restaurar esas reglas.

3. ¿Hay reglas específicas de la cadena DOCKER-USER que deba inyectar?

No. La cadena DOCKER-USER es para tus reglas personalizadas (por ejemplo, bloquear una IP específica de acceder a tu API). El error que estás viendo no es sobre una regla de seguridad faltante, sino sobre una cadena de infraestructura faltante. Inyectar reglas en DOCKER-USER no solucionará el fallo ACCEPT OUTGOING porque ese fallo ocurre en el proceso de configuración principal de Docker.

Hola,

Gracias por la respuesta.

He intentado tus configuraciones de docker compose pero no pude tener éxito. El error “Redis disconnected” continúa. Aquí está mi archivo docker-compose.yml más reciente:

version: '3.8'

services:
  evolution_api:
    image: atendai/evolution-api:latest
    container_name: evolution_api
    restart: always
    network_mode: "host"
    ports:
      - "8080:8080"
    environment:
      - SERVER_TYPE=http
      - SERVER_PORT=8080
      - SERVER_URL=http://my-server-ip:8080
      - CORS_ORIGIN=*
      - CORS_METHODS=GET,POST,PUT,DELETE,PATCH
      - AUTHENTICATION_TYPE=apikey
      - WA_PHONE_VERSION=2.3000.10125062854
      - CONFIG_SESSION_PHONE_CLIENT=Chrome
      - AUTHENTICATION_API_KEY=my-auth-api-key

      # Connecting to YunoHost database
      - DATABASE_ENABLED=true
      - DATABASE_PROVIDER=postgresql
      - DATABASE_CONNECTION_URI=postgresql://evolution:password@localhost:5432/evolution?schema=public

      # Connecting to YunoHost's Redis
      - CACHE_REDIS_ENABLED=true
      - CACHE_REDIS_URI=redis://redis:6379

Además, tengo una pregunta más ¿crees que por qué el código QR no aparece? Cuando miré las solicitudes en mi navegador no hay nada que parezca mal. Todo parece estar en 200 OK. Gracias.

La razón por la que aún ves “Redis disconnected” se debe a una incompatibilidad de red en tu nuevo docker-compose.yml.

El problema: network_mode: "host" vs. redis://redis

Has cambiado a network_mode: "host". En este modo, el contenedor no tiene su propia red interna de Docker; comparte la red de tu VPS directamente.

  • Cómo funciona ahora: Dentro de tu contenedor, localhost es lo mismo que el localhost del VPS.

  • El error: Le dijiste al API que busque Redis en el nombre de host redis (redis://redis:6379). Sin embargo, como no estás usando una red bridge de Docker, no hay una entrada DNS para “redis”. El contenedor está buscando una máquina llamada “redis” en tu red y no puede encontrarla.

Porque estás intentando conectarte a Redis nativo de YunoHost (que se ejecuta directamente en el OS del host), debes referirte a él como localhost.

El problema: network_mode: "host" vs. redis://redis

Has cambiado a network_mode: "host". En este modo, el contenedor no tiene su propia red interna de Docker; comparte la red de tu VPS directamente.

  • Cómo funciona ahora: Dentro de tu contenedor, localhost es lo mismo que el localhost del VPS.

  • El error: Le dijiste al API que busque Redis en el nombre de host redis (redis://redis:6379). Sin embargo, como no estás usando una red bridge de Docker, no hay una entrada DNS para “redis”. El contenedor está buscando una máquina llamada “redis” en tu red y no puede encontrarla.

Porque estás intentando conectarte a Redis nativo de YunoHost (que se ejecuta directamente en el OS del host), debes referirte a él como localhost.

La solución: docker-compose.yml actualizado

Cambia tu CACHE_REDIS_URI para usar localhost.

services:
  evolution_api:
    image: atendai/evolution-api:latest
    container_name: evolution_api
    restart: always
    network_mode: "host" 
    # Nota: 'ports' se ignora cuando se usa network_mode: host, 
    # la aplicación se vinculará automáticamente a 8080 en tu IP de VPS.
    environment:
      - SERVER_TYPE=http
      - SERVER_PORT=8080
      - SERVER_URL=http://my-server-ip:8080
      - CORS_ORIGIN=*
      - CORS_METHODS=GET,POST,PUT,DELETE,PATCH
      - AUTHENTICATION_TYPE=apikey
      - WA_PHONE_VERSION=2.3000.10125062854
      - CONFIG_SESSION_PHONE_CLIENT=Chrome
      - AUTHENTICATION_API_KEY=my-auth-api-key

      # Conectando a la base de datos de YunoHost (Correcto)
      - DATABASE_ENABLED=true
      - DATABASE_PROVIDER=postgresql
      - DATABASE_CONNECTION_URI=postgresql://evolution:password@localhost:5432/evolution?schema=public

      # Conectando a Redis de YunoHost (FIJO)
      - CACHE_REDIS_ENABLED=true
      - CACHE_REDIS_URI=redis://localhost:6379 

Paso importante: Después de guardar el archivo, ejecuta:

docker compose up -d

Por qué el código QR no aparece

Mencionaste que las solicitudes del navegador devuelven 200 OK, pero no aparece ningún código QR. Esto está directamente causado por la desconexión de Redis.

Aquí está la razón técnica:

  1. La solicitud (200 OK): Cuando pides el código QR, el servidor API se está ejecutando, así que acepta la solicitud y devuelve una respuesta HTTP válida. El “200 OK” solo significa “El servidor está vivo y te escuchó”.

  2. El proceso (fallo): Para generar un código QR, Evolution API debe inicializar una sesión de WhatsApp usando la biblioteca Baileys. Esta biblioteca necesita almacenar el estado de la sesión y los datos temporales de conexión.

  3. El colapso: Evolution API usa Redis para gestionar este estado. Porque Redis está desconectado, el API falla al crear la sesión en segundo plano. Devuelve una respuesta de éxito al navegador, pero la carga útil (los datos reales del código QR) está vacía o no es válida porque el proceso backend colapsó mientras intentaba escribir en Redis.

Una vez que corrijas el CACHE_REDIS_URI a localhost y los registros “Redis disconnected” se detengan, el código QR aparecerá inmediatamente.

Consejo final para usuarios de YunoHost

Si aún ves “Redis disconnected” incluso después de cambiar a localhost, significa que Redis de YunoHost está configurado para permitir conexiones solo desde usuarios específicos o tiene una contraseña.

Verifica si Redis de YunoHost tiene una contraseña ejecutando esto en la terminal de tu VPS:

redis-cli ping

  • Si devuelve PONG, está abierto.

  • Si devuelve (error) NOAUTH Authentication required, debes agregar la contraseña a tu URI: redis://:yourpassword@localhost:6379.

Gracias por la respuesta.

Actualmente he resuelto ambos problemas: el de Redis y el de la visualización del código QR.

Con respecto al primer problema de Redis, tu solución funcionó para mí. Los cambios que indicaste en el archivo compose fueron suficientes, y también reinicié el firewall de YunoHost (AFW) y Docker.

Para el segundo problema, descubrí que la imagen de Evolution API ya no es compatible debido a protocolos antiguos de WhatsApp. Cambié la imagen y funcionó inmediatamente, sin necesidad ni siquiera de modificar mi archivo compose. He compartido mis configuraciones a continuación:

version: '3.8'

services:
  evolution_api:
    image: evoapicloud/evolution-api:latest # Esta es la estable
    container_name: evolution_api
    restart: always
    network_mode: "host"

    environment:
      - SERVER_TYPE=http
      - SERVER_PORT=8080
      - SERVER_URL=http://your-server-ip:8080
      - CORS_ORIGIN=*
      - CORS_METHODS=GET,POST,PUT,DELETE,PATCH
      - AUTHENTICATION_TYPE=apikey
      - AUTHENTICATION_API_KEY=your-api-key
      # Mencionando por separado la versión del teléfono de WhatsApp y el navegador.
      - WA_PHONE_VERSION=2.3000.1030415680
      - CONFIG_SESSION_PHONE_CLIENT=Chrome

      # Vamos a usar la base de datos de YunoHost.
      - DATABASE_ENABLED=true
      - DATABASE_PROVIDER=postgresql
      - DATABASE_CONNECTION_URI=postgresql://evolution:password@localhost:5432/evolution?schema=public
      - CACHE_REDIS_ENABLED=true
      - CACHE_REDIS_URI=redis://localhost:6379

      # Opcional: configuraciones para mayor estabilidad.
      - DELAY_MESSAGE=1000
      - QR_CODE_EXPIRATION=600

    volumes:
      - ./evolution_instances:/evolution/instances

Aún después de resolver esos problemas, hay una cuestión pendiente: he configurado el nodo de disparo de Evolution API, pero cuando n8n recibe una respuesta, se queda atrapado en “Cargando datos.” Sin embargo, no hay ningún problema cuando ejecuto nodos normales. Solo ocurre cuando ejecuto el nodo de disparo. Ya he abierto un problema en GitHub para esto, pero aún no he encontrado recursos para solucionarlo. ¿Tienes información al respecto? Gracias.

¡Es excelente escuchar que los problemas de Redis y códigos QR se han resuelto! Cambiar a la imagen evoapicloud fue la decisión correcta—las imágenes atendai están efectivamente desactualizadas y a menudo fallan con los protocolos actuales de WhatsApp Web.

Regarding el nodo trigger de n8n que se queda atascado en “Loading data,” este es un problema conocido cuando ejecutas n8n y Evolution API en el mismo servidor YunoHost.

Ya que tus nodos normales funcionan, el “plumbing” (API —>-> n8n) está funcionando para las solicitudes. Sin embargo, un Trigger Node funciona de manera inversa: la API envía un Webhook a n8n. Cuando n8n está en modo “Listen” y dice “Loading data”, está esperando una solicitud HTTP válida que llegue a su endpoint de webhook.

Aquí hay tres razones más probables de que esto esté sucediendo en tu configuración específica de YunoHost:

1. El problema de networking “Hairpin” (Lo más probable)

Probablemente estés usando la URL pública de tu instancia de n8n (por ejemplo, https://n8n.tudominio.com/webhook/…) en la configuración de webhook de Evolution API.

El problema: Cuando Evolution API (en el mismo servidor) intenta enviar datos a tu URL pública, la solicitud sale hacia la IP de tu VPS e intenta volver a entrar. Muchos firewalls (incluyendo el AFW/iptables de YunoHost) y algunos proveedores de VPS bloquean este “loopback” (Hairpin NAT) por razones de seguridad. La solicitud nunca llega realmente a n8n, así que el nodo se queda en “Loading data” indefinidamente.

La solución: En tu configuración de webhook de Evolution API, intenta usar la dirección interna de n8n en lugar de la pública.

  • Cambiar: https://n8n.tudominio.com/webhook/...

  • Por: http://localhost:5678/webhook/... (o el puerto que uses internamente para n8n).

2. Variable de entorno WEBHOOK_URL de n8n

Si n8n no conoce su propia URL pública, a veces puede generar URLs de webhook de “Test” que usan localhost o una IP interna, que la API de Evolution podría no ser capaz de enrutar correctamente dependiendo de cómo la red de Docker esté interactuando con el servicio systemd de YunoHost.

La solución: Asegúrate de que tu servicio de n8n (a través de YunoHost o variables de entorno) tenga WEBHOOK_URL configurado explícitamente:

WEBHOOK_URL=https://n8n.tudominio.com/

Si esto no está configurado, n8n podría estar dándole a la API una URL que se vea correcta en la interfaz pero que sea funcionalmente rota para la solicitud entrante.

3. Falta de coincidencia en la carga de datos (El “cuelgue de la interfaz”)

Ya que cambió a la imagen evoapicloud, la estructura JSON de los eventos que se envían a n8n podría haber cambiado ligeramente en comparación con lo que el nodo Evolution API de n8n espera.

Cuando el nodo trigger de n8n recibe una solicitud que no puede analizar en el esquema esperado, la interfaz a veces se cuelga en “Loading data” en lugar de mostrar un error porque está atrapada en un bucle intentando mapear el JSON entrante a los campos internos del nodo.

Cómo probar esto:

  1. Crea un nodo Webhook estándar en n8n (no el nodo trigger de Evolution API).

  2. Copia esa URL de Webhook y colócala en la configuración de webhook de Evolution API.

  3. Dispara un evento (envía un mensaje al bot).

  4. Si el nodo Webhook estándar recibe los datos, entonces el problema es una falta de coincidencia de esquema en el nodo trigger de Evolution API. En este caso, puedes construir realmente tu flujo completo usando el nodo Webhook estándar y un nodo “Set” o “Code” para limpiar los datos—esto es a menudo más estable que usar el nodo trigger dedicado.

Lista de verificación de resumen para ti:

  1. Prueba con un nodo Webhook estándar. Si funciona, el problema es el código del Trigger Node (falta de coincidencia de esquema).

  2. Cambia la URL de Webhook en Evolution API a http://localhost:5678/... para evitar el problema de firewall/loopback de YunoHost.

  3. Revisa los logs de n8n (sudo journalctl -u n8n o similar) mientras el nodo está en “Loading data” para ver si aparecen errores 403 Forbidden o Connection Refused.

Mágicamente, resolví el problema actualizando n8n de la versión 1.15.1 a la 1.19.2, aunque no comprendo realmente cómo se solucionó.