commit 7e3af4a7d6d230d50c51e34e879bea96b838845f Author: Alejandro Robles Date: Tue Jul 8 10:18:07 2025 -0600 instalador de Evolution API diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..056dee8 --- /dev/null +++ b/.env.example @@ -0,0 +1,314 @@ +############################################ +# Evolution API +############################################ + +# ------------------------------------------ +AUTHENTICATION_API_KEY=api_key # Clave de autenticación para Evolution API (Contraseña de administrador) +# ------------------------------------------ +EVOLUTION_API_PORT=8080 # Puerto de escucha para Evolution API +# ------------------------------------------ +CONFIG_SESSION_PHONE_VERSION=2.3000.1023204200 # Whatsapp Web version for baileys channel: https://web.whatsapp.com/check-update?version=0&platform=web +# ------------------------------------------ + +############################################ +# PostgreSQL +############################################ + +# ------------------------------------------ +POSTGRESS_USER=user # Usuario de PostgreSQL (POR SEGURIDAD MODIFICA ESTE VALOR) +# ------------------------------------------ +POSTGRESS_PASS=123456 # Contraseña de PostgreSQL (POR SEGURIDAD MODIFICA ESTE VALOR) +# ------------------------------------------ +POSTGRESS_PORT=5432 # Puerto de PostgreSQL (Se sugiere no modificar) +# ------------------------------------------ + +############################################ +# Redis +############################################ + +REDIS_PORT=6379 # Puerto de Redis (Se sugiere no modificar) + +# ------------------------------------ EVOLUTION API OTHER CONFIGURATIONS ----------------------------- +SERVER_TYPE=http +SERVER_URL=${SERVER_TYPE}://localhost:${EVOLUTION_API_PORT} +SERVER_PORT=8080 + +SENTRY_DSN= + +# Cors - * for all or set separate by commas - ex.: 'yourdomain1.com, yourdomain2.com' +CORS_ORIGIN=* +CORS_METHODS=GET,POST,PUT,DELETE +CORS_CREDENTIALS=true + +# Determine the logs to be displayed +LOG_LEVEL=ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK,WEBHOOKS,WEBSOCKET +LOG_COLOR=true +# Log Baileys - "fatal" | "error" | "warn" | "info" | "debug" | "trace" +LOG_BAILEYS=error + +# Set the maximum number of listeners that can be registered for an event +EVENT_EMITTER_MAX_LISTENERS=50 + +# Determine how long the instance should be deleted from memory in case of no connection. +# Default time: 5 minutes +# If you don't even want an expiration, enter the value false +DEL_INSTANCE=false + +# Provider: postgresql | mysql +DATABASE_PROVIDER=postgresql +DATABASE_CONNECTION_URI='postgresql://${POSTGRESS_USER}:${POSTGRESS_PASS}@postgres:${POSTGRESS_PORT}/evolution?schema=public' + +# Client name for the database connection +# It is used to separate an API installation from another that uses the same database. +DATABASE_CONNECTION_CLIENT_NAME=evolution_exchange + +# Choose the data you want to save in the application's database +DATABASE_SAVE_DATA_INSTANCE=true +DATABASE_SAVE_DATA_NEW_MESSAGE=true +DATABASE_SAVE_MESSAGE_UPDATE=true +DATABASE_SAVE_DATA_CONTACTS=true +DATABASE_SAVE_DATA_CHATS=true +DATABASE_SAVE_DATA_LABELS=true +DATABASE_SAVE_DATA_HISTORIC=true +DATABASE_SAVE_IS_ON_WHATSAPP=true +DATABASE_SAVE_IS_ON_WHATSAPP_DAYS=7 +DATABASE_DELETE_MESSAGE=true + +# RabbitMQ - Environment variables +RABBITMQ_ENABLED=false +RABBITMQ_URI=amqp://localhost +RABBITMQ_EXCHANGE_NAME=evolution +RABBITMQ_FRAME_MAX=8192 +# Global events - By enabling this variable, events from all instances are sent in the same event queue. +RABBITMQ_GLOBAL_ENABLED=false +# Prefix key to queue name +RABBITMQ_PREFIX_KEY=evolution +# Choose the events you want to send to RabbitMQ +RABBITMQ_EVENTS_APPLICATION_STARTUP=false +RABBITMQ_EVENTS_INSTANCE_CREATE=false +RABBITMQ_EVENTS_INSTANCE_DELETE=false +RABBITMQ_EVENTS_QRCODE_UPDATED=false +RABBITMQ_EVENTS_MESSAGES_SET=false +RABBITMQ_EVENTS_MESSAGES_UPSERT=false +RABBITMQ_EVENTS_MESSAGES_EDITED=false +RABBITMQ_EVENTS_MESSAGES_UPDATE=false +RABBITMQ_EVENTS_MESSAGES_DELETE=false +RABBITMQ_EVENTS_SEND_MESSAGE=false +RABBITMQ_EVENTS_SEND_MESSAGE_UPDATE=false +RABBITMQ_EVENTS_CONTACTS_SET=false +RABBITMQ_EVENTS_CONTACTS_UPSERT=false +RABBITMQ_EVENTS_CONTACTS_UPDATE=false +RABBITMQ_EVENTS_PRESENCE_UPDATE=false +RABBITMQ_EVENTS_CHATS_SET=false +RABBITMQ_EVENTS_CHATS_UPSERT=false +RABBITMQ_EVENTS_CHATS_UPDATE=false +RABBITMQ_EVENTS_CHATS_DELETE=false +RABBITMQ_EVENTS_GROUPS_UPSERT=false +RABBITMQ_EVENTS_GROUP_UPDATE=false +RABBITMQ_EVENTS_GROUP_PARTICIPANTS_UPDATE=false +RABBITMQ_EVENTS_CONNECTION_UPDATE=false +RABBITMQ_EVENTS_REMOVE_INSTANCE=false +RABBITMQ_EVENTS_LOGOUT_INSTANCE=false +RABBITMQ_EVENTS_CALL=false +RABBITMQ_EVENTS_TYPEBOT_START=false +RABBITMQ_EVENTS_TYPEBOT_CHANGE_STATUS=false + +# SQS - Environment variables +SQS_ENABLED=false +SQS_ACCESS_KEY_ID= +SQS_SECRET_ACCESS_KEY= +SQS_ACCOUNT_ID= +SQS_REGION= + +# Websocket - Environment variables +WEBSOCKET_ENABLED=false +WEBSOCKET_GLOBAL_EVENTS=false + +# Pusher - Environment variables +PUSHER_ENABLED=false +PUSHER_GLOBAL_ENABLED=false +PUSHER_GLOBAL_APP_ID= +PUSHER_GLOBAL_KEY= +PUSHER_GLOBAL_SECRET= +PUSHER_GLOBAL_CLUSTER= +PUSHER_GLOBAL_USE_TLS=true +# Choose the events you want to send to Pusher +PUSHER_EVENTS_APPLICATION_STARTUP=true +PUSHER_EVENTS_QRCODE_UPDATED=true +PUSHER_EVENTS_MESSAGES_SET=true +PUSHER_EVENTS_MESSAGES_UPSERT=true +PUSHER_EVENTS_MESSAGES_EDITED=true +PUSHER_EVENTS_MESSAGES_UPDATE=true +PUSHER_EVENTS_MESSAGES_DELETE=true +PUSHER_EVENTS_SEND_MESSAGE=true +PUSHER_EVENTS_SEND_MESSAGE_UPDATE=true +PUSHER_EVENTS_CONTACTS_SET=true +PUSHER_EVENTS_CONTACTS_UPSERT=true +PUSHER_EVENTS_CONTACTS_UPDATE=true +PUSHER_EVENTS_PRESENCE_UPDATE=true +PUSHER_EVENTS_CHATS_SET=true +PUSHER_EVENTS_CHATS_UPSERT=true +PUSHER_EVENTS_CHATS_UPDATE=true +PUSHER_EVENTS_CHATS_DELETE=true +PUSHER_EVENTS_GROUPS_UPSERT=true +PUSHER_EVENTS_GROUPS_UPDATE=true +PUSHER_EVENTS_GROUP_PARTICIPANTS_UPDATE=true +PUSHER_EVENTS_CONNECTION_UPDATE=true +PUSHER_EVENTS_LABELS_EDIT=true +PUSHER_EVENTS_LABELS_ASSOCIATION=true +PUSHER_EVENTS_CALL=true +PUSHER_EVENTS_TYPEBOT_START=false +PUSHER_EVENTS_TYPEBOT_CHANGE_STATUS=false + +# WhatsApp Business API - Environment variables +# Token used to validate the webhook on the Facebook APP +WA_BUSINESS_TOKEN_WEBHOOK=evolution +WA_BUSINESS_URL=https://graph.facebook.com +WA_BUSINESS_VERSION=v20.0 +WA_BUSINESS_LANGUAGE=en_US + +# Global Webhook Settings +# Each instance's Webhook URL and events will be requested at the time it is created +WEBHOOK_GLOBAL_ENABLED=false +# Define a global webhook that will listen for enabled events from all instances +WEBHOOK_GLOBAL_URL='' +# With this option activated, you work with a url per webhook event, respecting the global url and the name of each event +WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false +# Set the events you want to hear +WEBHOOK_EVENTS_APPLICATION_STARTUP=false +WEBHOOK_EVENTS_QRCODE_UPDATED=true +WEBHOOK_EVENTS_MESSAGES_SET=true +WEBHOOK_EVENTS_MESSAGES_UPSERT=true +WEBHOOK_EVENTS_MESSAGES_EDITED=true +WEBHOOK_EVENTS_MESSAGES_UPDATE=true +WEBHOOK_EVENTS_MESSAGES_DELETE=true +WEBHOOK_EVENTS_SEND_MESSAGE=true +WEBHOOK_EVENTS_SEND_MESSAGE_UPDATE=true +WEBHOOK_EVENTS_CONTACTS_SET=true +WEBHOOK_EVENTS_CONTACTS_UPSERT=true +WEBHOOK_EVENTS_CONTACTS_UPDATE=true +WEBHOOK_EVENTS_PRESENCE_UPDATE=true +WEBHOOK_EVENTS_CHATS_SET=true +WEBHOOK_EVENTS_CHATS_UPSERT=true +WEBHOOK_EVENTS_CHATS_UPDATE=true +WEBHOOK_EVENTS_CHATS_DELETE=true +WEBHOOK_EVENTS_GROUPS_UPSERT=true +WEBHOOK_EVENTS_GROUPS_UPDATE=true +WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=true +WEBHOOK_EVENTS_CONNECTION_UPDATE=true +WEBHOOK_EVENTS_REMOVE_INSTANCE=false +WEBHOOK_EVENTS_LOGOUT_INSTANCE=false +WEBHOOK_EVENTS_LABELS_EDIT=true +WEBHOOK_EVENTS_LABELS_ASSOCIATION=true +WEBHOOK_EVENTS_CALL=true +# This events is used with Typebot +WEBHOOK_EVENTS_TYPEBOT_START=false +WEBHOOK_EVENTS_TYPEBOT_CHANGE_STATUS=false +# This event is used to send errors +WEBHOOK_EVENTS_ERRORS=false +WEBHOOK_EVENTS_ERRORS_WEBHOOK= + +WEBHOOK_REQUEST_TIMEOUT_MS=60000 +WEBHOOK_RETRY_MAX_ATTEMPTS=10 +WEBHOOK_RETRY_INITIAL_DELAY_SECONDS=5 +WEBHOOK_RETRY_USE_EXPONENTIAL_BACKOFF=true +WEBHOOK_RETRY_MAX_DELAY_SECONDS=300 +WEBHOOK_RETRY_JITTER_FACTOR=0.2 +# Comma separated list of HTTP status codes that should not trigger retries +WEBHOOK_RETRY_NON_RETRYABLE_STATUS_CODES=400,401,403,404,422 + +# Name that will be displayed on smartphone connection +CONFIG_SESSION_PHONE_CLIENT="Evolution API" +# Browser Name = Chrome | Firefox | Edge | Opera | Safari +CONFIG_SESSION_PHONE_NAME=Chrome + +# Set qrcode display limit +QRCODE_LIMIT=30 +# Color of the QRCode on base64 +QRCODE_COLOR='#175197' + +# Typebot - Environment variables +TYPEBOT_ENABLED=false +# old | latest +TYPEBOT_API_VERSION=latest + +# Chatwoot - Environment variables +CHATWOOT_ENABLED=false +# If you leave this option as false, when deleting the message for everyone on WhatsApp, it will not be deleted on Chatwoot. +CHATWOOT_MESSAGE_READ=true +# If you leave this option as true, when sending a message in Chatwoot, the client's last message will be marked as read on WhatsApp. +CHATWOOT_MESSAGE_DELETE=true +# If you leave this option as true, a contact will be created on Chatwoot to provide the QR Code and update messages about the instance. +CHATWOOT_BOT_CONTACT=true +# This db connection is used to import messages from whatsapp to chatwoot database +CHATWOOT_IMPORT_DATABASE_CONNECTION_URI=${POSTGRESS_USER}:${POSTGRESS_PASS}@postgres:${POSTGRESS_PORT}/chatwoot?sslmode=disable +CHATWOOT_IMPORT_PLACEHOLDER_MEDIA_MESSAGE=true + +# OpenAI - Environment variables +OPENAI_ENABLED=false + +# Dify - Environment variables +DIFY_ENABLED=false + +# n8n - Environment variables +N8N_ENABLED=false + +# EvoAI - Environment variables +EVOAI_ENABLED=false + +# Cache - Environment variables +# Redis Cache enabled +CACHE_REDIS_ENABLED=true +CACHE_REDIS_URI=redis://redis:${REDIS_PORT}/6 +CACHE_REDIS_TTL=604800 +# Prefix serves to differentiate data from one installation to another that are using the same redis +CACHE_REDIS_PREFIX_KEY=evolution +# Enabling this variable will save the connection information in Redis and not in the database. +CACHE_REDIS_SAVE_INSTANCES=false +# Local Cache enabled +CACHE_LOCAL_ENABLED=false + +# Amazon S3 - Environment variables +S3_ENABLED=false +S3_ACCESS_KEY= +S3_SECRET_KEY= +S3_BUCKET=evolution +S3_PORT=443 +S3_ENDPOINT=s3.domain.com +S3_REGION=eu-west-3 +S3_USE_SSL=true + +# AMAZON S3 - Environment variables +# S3_ENABLED=true +# S3_BUCKET=bucket_name +# S3_ACCESS_KEY=access_key_id +# S3_SECRET_KEY=secret_access_key +# S3_ENDPOINT=s3.amazonaws.com # region: s3.eu-west-3.amazonaws.com +# S3_REGION=eu-west-3 + +# MINIO Use SSL - Environment variables +# S3_ENABLED=true +# S3_ACCESS_KEY=access_key_id +# S3_SECRET_KEY=secret_access_key +# S3_BUCKET=bucket_name +# S3_PORT=443 +# S3_ENDPOINT=s3.domain.com +# S3_USE_SSL=true +# S3_REGION=eu-south + +# Evolution Audio Converter - Environment variables - https://github.com/EvolutionAPI/evolution-audio-converter +# API_AUDIO_CONVERTER=http://localhost:4040/process-audio +# API_AUDIO_CONVERTER_KEY=429683C4C977415CAAFCCE10F7D57E11 + +# Define a global apikey to access all instances. +# OBS: This key must be inserted in the request header to create an instance. +# If you leave this option as true, the instances will be exposed in the fetch instances endpoint. +AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true +LANGUAGE=en + +# Define a global proxy to be used if the instance does not have one +# PROXY_HOST= +# PROXY_PORT=80 +# PROXY_PROTOCOL=http +# PROXY_USERNAME= +# PROXY_PASSWORD= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..f539953 --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# Instalación Automática de Docker, Docker Compose, y Evolution API + +Este repositorio proporciona un script Bash (`install.sh`) para instalar y configurar Docker, Docker Compose plugin y Evolution API en servidores basados en Ubuntu. + +## Requisitos previos + +- Sistema operativo: Ubuntu 18.04, 20.04, 22.04, 24.04 (u otra versión compatible con los repositorios oficiales de Docker) +- Acceso con usuario que tenga privilegios de sudo +- Conexión a Internet desde el servidor + +## Contenido del repositorio + +- `install.sh`: script que automatiza la instalación. + +### 1. Descargar o clonar el repositorio + +```bash +git clone https://github.com/devalexcode/shell-evolution-api.git +``` + +### 2. Ingresa a la carpeta del proyecto + +```bash +cd shell-evolution-api +``` + +### 3. Crea el archivo `.env` + +```bash +cp .env.example .env +``` + +**3.1 ⚙️ Configuración del archivo `.env`** + +Antes de levantar los servicios, asegúrate de crear y configurar tu archivo `.env`: + +```bash +nano .env +``` + +Edita el archivo `.env` con tus propios valores: + +```dotenv +############################################ +# Evolution API +############################################ + +# ------------------------------------------ +AUTHENTICATION_API_KEY=api_key # Clave de autenticación para Evolution API (Contraseña de administrador) +# ------------------------------------------ +EVOLUTION_API_PORT=8080 # Puerto de escucha para Evolution API +# ------------------------------------------ +CONFIG_SESSION_PHONE_VERSION=2.3000.1023204200 # Whatsapp Web version for baileys channel: https://web.whatsapp.com/check-update?version=0&platform=web +# ------------------------------------------ + +############################################ +# PostgreSQL +############################################ + +# ------------------------------------------ +POSTGRESS_USER=user # Usuario de PostgreSQL (POR SEGURIDAD MODIFICA ESTE VALOR) +# ------------------------------------------ +POSTGRESS_PASS=123456 # Contraseña de PostgreSQL (POR SEGURIDAD MODIFICA ESTE VALOR) +# ------------------------------------------ +POSTGRESS_PORT=5432 # Puerto de PostgreSQL (Se sugiere no modificar) +# ------------------------------------------ + +############################################ +# Redis +############################################ + +REDIS_PORT=6379 # Puerto de Redis (Se sugiere no modificar) +``` + +### 4. Dar permisos de ejecución al script + +```bash +chmod +x install.sh +``` + +### 5 Ejecutar el script + +```bash +./install.sh +``` + +- El script actualizará el sistema, instalará Docker y sus herramientas, añadirá el usuario al grupo `docker` desplegará n8n, Evolution API y Portainer. + +![Shell instalacion](docs/shell.png) + +## Ingresar a Evolution API + +Al finalizar, verás un mensaje indicando la URL de acceso a Evolution API: + +```bash +¡Instalación completada! Evolution API funcionando y accesible: http://:EVOLUTION_API_PORT/manager +``` + +![Login Evolution API](docs/Evolution-API-login.png) + +¡Listo! Con estos pasos tu servidor quedará con Evolution API instalado. + +## 👨‍💻 Autor + +Desarrollado por [Alejandro Robles | Devalex ](http://devalexcode.com) +¿Necesitas que lo haga por ti? ¡Estoy para apoyarte! 🤝 https://devalexcode.com/soluciones/evolution-api-whatsapp-en-servidor-vps + +¿Dudas o sugerencias? ¡Contribuciones bienvenidas! diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..77519c0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,61 @@ +services: + evolution_api: + container_name: evolution_api + image: atendai/evolution-api:latest + restart: always + depends_on: + - redis + - postgres + ports: + - ${EVOLUTION_API_PORT}:8080 + volumes: + - evolution_instances:/evolution/instances + networks: + - evolution-net + env_file: + - .env + expose: + - 8080 + + redis: + image: redis:latest + restart: always + networks: + - evolution-net + container_name: redis + command: > + redis-server --port 6379 --appendonly yes + volumes: + - evolution_redis:/data + ports: + - ${REDIS_PORT}:6379 + + postgres: + container_name: postgres + image: postgres:15 + networks: + - evolution-net + command: + ["postgres", "-c", "max_connections=1000", "-c", "listen_addresses=*"] + restart: always + ports: + - ${POSTGRESS_PORT}:5432 + environment: + - POSTGRES_USER=${POSTGRESS_USER} + - POSTGRES_PASSWORD=${POSTGRESS_PASS} + - POSTGRES_DB=evolution + - POSTGRES_HOST_AUTH_METHOD=trust + volumes: + - postgres_data:/var/lib/postgresql/data + expose: + - 5432 + +volumes: + evolution_instances: + evolution_redis: + postgres_data: + +networks: + evolution-net: + name: evolution-net + driver: bridge diff --git a/docs/Evolution-API-login.png b/docs/Evolution-API-login.png new file mode 100644 index 0000000..20aa087 Binary files /dev/null and b/docs/Evolution-API-login.png differ diff --git a/docs/shell.png b/docs/shell.png new file mode 100644 index 0000000..dcd352c Binary files /dev/null and b/docs/shell.png differ diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..75ba1e6 --- /dev/null +++ b/install.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Colores ANSI +GREEN='\033[0;32m' +RED='\033[0;31m' +NC='\033[0m' # No Color (reset) + +# ───────────────────────────────────────────────────────────────────────────── +# Cargar variables de entorno del .env (requiere que exista en el mismo directorio) +# ───────────────────────────────────────────────────────────────────────────── +if [[ -f .env ]]; then + set -a && source .env && set +a +else + echo "ERROR: No se encontró el archivo .env. Crea uno." + exit 1 +fi + +# ───────────────────────────────────────────────────────────────────────────── +# Determinar protocolo y configuración de cookie según N8N_HOST +# ───────────────────────────────────────────────────────────────────────────── + +# Obtener IP pública (global) +PUBLIC_IP=$(curl -s http://checkip.amazonaws.com || curl -s https://icanhazip.com) + +# ───────────────────────────────────────────────────────────────────────────── +# Actualizar repositorios y paquetes +# ───────────────────────────────────────────────────────────────────────────── +sudo apt update + +# ───────────────────────────────────────────────────────────────────────────── +# Instalar prerequisitos (si faltan) +# ───────────────────────────────────────────────────────────────────────────── +sudo apt install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg \ + lsb-release + +# ───────────────────────────────────────────────────────────────────────────── +# Instalación de Docker (si no está instalado) +# ───────────────────────────────────────────────────────────────────────────── +if ! command -v docker >/dev/null 2>&1; then + echo "Docker no encontrado. Instalando Docker..." + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | + sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | + sudo tee /etc/apt/sources.list.d/docker.list >/dev/null + sudo apt update && sudo apt install -y docker-ce docker-ce-cli containerd.io + sudo systemctl enable --now docker + sudo usermod -aG docker "$USER" + echo -e "${GREEN}Docker instalado: $(docker --version)${NC}" +else + echo "Docker ya está instalado: $(docker --version)" +fi + +# ───────────────────────────────────────────────────────────────────────────── +# Instalación de Docker Compose CLI plugin (si no está instalado) +# ───────────────────────────────────────────────────────────────────────────── +if ! docker compose version >/dev/null 2>&1; then + echo "Docker Compose CLI plugin no encontrado. Instalando..." + sudo apt-get install -y docker-compose-plugin + echo -e "${GREEN}Docker Compose instalado: $(docker compose version)${NC}" +else + echo "Docker Compose ya está instalado: $(docker compose version)" +fi + +# ───────────────────────────────────────────────────────────────────────────── +# Instalación de Evolution API (si no está instalado) +# ───────────────────────────────────────────────────────────────────────────── +if sudo docker container evolution_api >/dev/null 2>&1; then + echo "Evolution API ya está instalado y configurado." +else + echo "Instalando Evolution API y servicios (corriendo docker-compose.yml) ..." + sudo docker compose up -d + + echo -e "${GREEN} Evolution API y servicios instalados${NC}" +fi + +CHECK_APP_MAX_ATTEMPTS=5 +CHECK_APP_DELAY_SECONDS=5 + +# Función para validar que un puerto esté accesible externamente para una aplicación +# Recibe Puerto y Nombre de la Aplicación +# Realiza hasta CHECK_APP_MAX_ATTEMPTS intentos con CHECK_APP_DELAY_SECONDS segundos de delay. Si tras CHECK_APP_MAX_ATTEMPTS fallos, muestra error y termina. +check_port_open() { + local PORT=$1 + local APP_NAME=$2 + local attempt=1 + + while ((attempt <= CHECK_APP_MAX_ATTEMPTS)); do + + echo -e "Verificando acceso a ${APP_NAME} . . . " + + sleep ${CHECK_APP_DELAY_SECONDS} + # Verificar respuesta del VPS + if nc -z -w5 "${PUBLIC_IP}" "${PORT}"; then + echo -e "${GREEN}¡Instalación completada! ${APP_NAME} funcionando y accesible: http://${PUBLIC_IP}:${PORT}${NC}/manager" + return 0 + fi + attempt=$((attempt + 1)) + done + + # Si llegamos aquí, todos los intentos fallaron + echo -e "${RED}Error: El puerto ${PORT} para ${APP_NAME} no es accesible externamente en ${PUBLIC_IP}:${PORT}. Verifica las reglas de entrada / firewall de tu servidor VPS.${NC}" +} + +check_port_open "${EVOLUTION_API_PORT}" "Evolution API" + +# Refrescar grupos para la sesión actual +newgrp docker