Ir al contenido

Instalar el motor

El motor es un solo servicio (API, coordinador de sesiones y workers en un proceso) que se distribuye como una imagen de contenedor. Vive en tu red privada: tus apps le hablan por HTTP y él habla con WhatsApp. Esta página levanta un motor para empezar a probar; para producción, backups y actualizaciones, sigue con Despliegue y backup.

Pieza Para qué Notas
Docker con Compose Correr la imagen y el stack local La imagen trae tres binarios: motor (el servicio), migrate y motorctl.
Postgres Todo lo aceptado: comandos, ledger, entregas, sesiones de WhatsApp Una base y un rol propios del motor. Se probó con Postgres 17.
MinIO La multimedia (opcional) Sin almacenamiento, la multimedia queda deshabilitada (503 multimedia_deshabilitada) y el resto funciona igual.
Salida a internet La conexión con WhatsApp Solo de salida. Un proxy de transporte por instancia es opcional.

La conversión de medios (nota de voz, sticker, GIF) usa ffmpeg y ffprobe, que ya vienen en la imagen. La imagen corre como usuario no root y está pensada para un contenedor de solo lectura, con /tmp en memoria y /respaldos como volumen.

El motor lee solo estas cuatro variables. No hay archivo de configuración: todo lo demás se guarda en la base y se edita en Ajustes.

Variable Obligatoria Qué es
DATABASE_URL Sí La conexión a Postgres, por ejemplo postgres://motor:CLAVE@postgres:5432/motor_whatsapp?sslmode=disable.
APP_MASTER_KEY Sí, para motor De 32 caracteres o más. Sella los secretos de Ajustes y los payloads del ledger, y de ella derivan los HMAC de las API keys, las sesiones y el CSRF.
APP_ENV No produccion (por omisión) o desarrollo. En desarrollo las cookies del panel van sin Secure, para entrar por http local.
PORT No El puerto HTTP. Por omisión, 8080.

Genera la clave maestra una vez y guárdala en el gestor de secretos de tu infraestructura:

Ventana de terminal
openssl rand -base64 48

Si falta una variable o tiene un valor inválido, el motor no arranca y dice cuál, por ejemplo: APP_MASTER_KEY debe tener al menos 32 caracteres o PORT debe ser un número entre 1 y 65535. migrate y motorctl no necesitan APP_MASTER_KEY.

El repositorio trae deploy/compose.local.yml: Postgres, MinIO, el paso de migraciones y el motor, todos publicados solo en 127.0.0.1.

Ventana de terminal
export APP_MASTER_KEY="$(openssl rand -base64 48)"
docker compose -f deploy/compose.local.yml up --build -d
Servicio Qué hace Puerto local
postgres La base del motor 55432 (MOTOR_POSTGRES_PORT)
minio El almacenamiento de la multimedia 59000 (MOTOR_MINIO_PORT)
migrate Corre migrate todo y termina —
motor El servicio, cuando migrate terminó bien 8080 (MOTOR_PORT)

Las variables MOTOR_*_PORT son del compose, no del motor: solo cambian el puerto publicado. Los servicios no se reinician solos (restart: "no"): lo que levantas, lo bajas tú.

El motor tiene dos juegos de tablas, y se migran por separado:

  • Las propias (goose): migrate up. El motor también aplica las pendientes al arrancar, bajo un lock, antes de aceptar conexiones.
  • El store de whatsmeow (las sesiones de WhatsApp): migrate whatsmeow. El motor no lo migra solo: si el store no está al día, el motor atiende la API pero sin transporte, y /health/ready responde 503.

migrate todo hace las dos cosas; es lo que corre el compose antes del motor. Fuera del compose, córrelo con la misma DATABASE_URL antes de arrancar motor:

Ventana de terminal
docker run --rm -e DATABASE_URL="$DATABASE_URL" --entrypoint /app/migrate IMAGEN_DEL_MOTOR todo
Comando Qué hace
migrate up Aplica las migraciones propias pendientes.
migrate status, migrate version Muestran el estado de las propias.
migrate whatsmeow Actualiza el store de whatsmeow, bajo un advisory lock.
migrate todo up y whatsmeow.
migrate verificar La verificación previa a una actualización: lo pendiente, el store, el último backup y el modo.
migrate down Revierte la última propia. Solo con APP_ENV=desarrollo.

No hay down del store de whatsmeow: volver atrás una versión del SDK es restaurar un backup. Si la base es más nueva que el binario (otra versión ya la migró), el motor no arranca y migrate up no toca nada.

Los operadores entran al panel con su correo y su contraseña. El primero se crea con motorctl dentro del contenedor. La contraseña va por la entrada estándar, nunca como argumento ni como variable:

Ventana de terminal
# Con terminal: la pide dos veces sin mostrarla.
docker compose -f deploy/compose.local.yml exec motor \
/app/motorctl operador crear --email tu@correo.com --nombre "Tu nombre"
# Sin terminal (un script): lee la primera línea de la entrada estándar.
printf '%s\n' "$CONTRASENA" | docker compose -f deploy/compose.local.yml exec -T motor \
/app/motorctl operador crear --email tu@correo.com --nombre "Tu nombre"

El rol por omisión es superadmin, el que puede crear apps, emitir keys y guardar Ajustes. Con --rol operador creas uno que opera instancias pero no administra credenciales. Otros comandos útiles:

Comando Qué hace
motorctl operador listar Los operadores, con su rol y su estado.
motorctl operador revocar-sesiones --email … Cierra todas las sesiones abiertas de un operador.
motorctl diagnostico Versión, base, migraciones, conteos y store de whatsmeow, sin secretos ni datos personales.

Abre http://127.0.0.1:8080/admin/ y entra con el correo y la contraseña del operador. En el mismo puerto están la referencia interactiva de la API (/docs) y el contrato (/openapi.json).

  • Con APP_ENV=produccion la cookie de sesión lleva Secure: sirve el panel por HTTPS dentro de tu red (por ejemplo, detrás de un proxy inverso interno).
  • Tras 5 intentos fallidos en 15 minutos (por correo y por IP), el acceso responde 429 con Retry-After. La sesión dura 12 horas. Los dos valores se cambian en Ajustes → Seguridad.

Qué hay en cada pantalla, en Panel de operadores.

Ruta o comando Qué dice
GET /health/live El proceso responde.
GET /health/ready La base responde y el esquema está al día. 503 si falta migrar algo o la base es más nueva que el binario.
motor salud El healthcheck del contenedor: pide /health/ready al propio proceso (la imagen no tiene curl).
motorctl diagnostico El detalle, para un ticket: no muestra secretos ni datos personales.

Con el operador creado, termina de configurar el motor en Ajustes. Los secretos (claves de S3, tokens) se guardan sellados y nunca vuelven a mostrarse: el panel solo dice si hay uno.

Grupo Lo primero que conviene revisar
Almacenamiento (MinIO) Endpoint, bucket (el motor lo crea privado si no existe), clave de acceso y clave secreta. Probar comprueba lo guardado. En el compose local: endpoint http://minio:9000, usuario motor-local y la clave de MOTOR_MINIO_CLAVE del compose.
Webhooks Los destinos permitidos globales: los hosts a los que cualquier app puede entregar. Cada app suma los suyos.
Límites El cupo de instancias por app (3 de fábrica), el ritmo de envío por instancia (1 mensaje por segundo, ráfaga de 2) y la cola de envíos (200).
Retención e historial Cuánto se guarda lo entregado (30 días) y si se importan los mensajes del historial al vincular (apagado de fábrica).
Backups El backup diario cifrado (apagado de fábrica).

Los límites completos están en Cuotas y límites.

Para mirar el panel sin vincular un número real, el motor tiene un proveedor falso que nunca se conecta a WhatsApp. Solo arranca con APP_ENV=desarrollo:

Ventana de terminal
docker compose -f deploy/compose.local.yml -f deploy/compose.falso.yml up --build -d
Ventana de terminal
docker compose -f deploy/compose.local.yml down # conserva la base y la multimedia
docker compose -f deploy/compose.local.yml down -v # borra los volúmenes

Con el panel abierto, crea la app y su key. El recorrido completo, en cinco pasos, está en el Inicio rápido.