# Despliegue de Kanban en un servidor cPanel/WHM

Esta version utiliza el Exim que ya administra cPanel. Docker no publica ni
ocupa los puertos 25, 465 o 587 del servidor.

## 1. Preparar el correo en cPanel

1. Ingrese a la cuenta cPanel que administra el dominio.
2. Abra **Email > Email Accounts**.
3. Utilice la cuenta `notificaciones@cidti.com.co`.
4. Abra **Connect Devices** para esa cuenta.
5. El **Outgoing Server** seguro configurado es `mail.cidti.com.co`.
6. Use el puerto SMTP `465` con SSL/TLS implicito. La aplicacion no utiliza
   STARTTLS para esta conexion.

En **cPanel > Email > Email Deliverability**, compruebe que SPF y DKIM aparezcan
como validos. Si cPanel administra la zona DNS, utilice **Repair** cuando lo
ofrezca. Configure tambien DMARC desde **Zone Editor**.

### Estado DNS observado para CIDTI

Al preparar este paquete se observo:

- `cidti.com.co` recibe correo mediante los MX de Google. No cambie esos MX.
- El SPF publico autoriza actualmente a Google. Si Exim enviara desde la IP del
  servidor cPanel, agregue esa IP al mismo registro SPF sin eliminar
  `include:_spf.google.com`.
- Existe un registro DKIM `default._domainkey.cidti.com.co`.
- Existe DMARC con politica `quarantine`.
- `mail.cidti.com.co` no resolvia publicamente. Docker no depende de esa
  resolucion porque lo mapea con `host-gateway`, pero el certificado presentado
  por Exim debe incluir `mail.cidti.com.co`.

Compruebe el certificado directamente en el servidor:

```bash
openssl s_client -connect 127.0.0.1:465 \
  -servername mail.cidti.com.co </dev/null 2>/dev/null |
  openssl x509 -noout -subject -issuer -checkhost mail.cidti.com.co
```

El resultado debe indicar que el certificado coincide con
`mail.cidti.com.co`. Si aparece `does NOT match`, repare el certificado de
servicio de Exim en WHM o use en `CPANEL_SMTP_HOST` el hostname seguro exacto
que aparezca en **Connect Devices** y coincida con el certificado.

Para mostrar los nombres alternativos con versiones antiguas de OpenSSL:

```bash
openssl s_client -connect 127.0.0.1:465 \
  -servername mail.cidti.com.co </dev/null 2>/dev/null |
  openssl x509 -noout -text |
  grep -A1 "Subject Alternative Name"
```

## 2. Revisiones en WHM

Estas revisiones requieren acceso root a WHM:

1. En **WHM > Service Configuration > Service Manager**, confirme que
   **Exim Mail Server** este habilitado y monitorizado.
2. Puede mantener activado **WHM > Security Center > SMTP Restrictions**. La
   aplicacion no intenta saltarse Exim; se autentica contra el Exim local.
3. Confirme que el firewall permite conexiones desde la red bridge de Docker
   hacia el puerto TCP/465 del anfitrion.
4. Confirme que Exim puede realizar conexiones salientes TCP/25. No publique el
   puerto 25 de Docker.
5. Verifique que el PTR/rDNS de la IP de salida coincida con el hostname del
   servidor.

Prueba opcional de salida desde el anfitrion:

```bash
nc -vz gmail-smtp-in.l.google.com 25
```

Si falla por timeout, solicite al proveedor del servidor habilitar el puerto 25
saliente. El puerto 465 se utiliza entre la aplicacion y Exim; Exim utiliza el
25 para entregar a otros servidores.

## 3. Subir o actualizar la aplicacion

Suba `kanban-docker-cpanel-cidti-20260810.zip` al servidor. Extraigalo en el mismo
directorio de la instalacion actual para conservar la identidad del proyecto y
sus volumenes:

```bash
cd /ruta/de/la/instalacion/actual
unzip -o /ruta/kanban-docker-cpanel-cidti-20260810.zip
```

El ZIP no contiene `.env` y no reemplaza los secretos existentes.

Si es una instalacion nueva:

```bash
cp .env.example .env
```

Edite `.env`:

```env
APP_PORT=8000
MYSQL_PASSWORD='cambie-esta-clave'
MYSQL_ROOT_PASSWORD='cambie-esta-clave-root'
SECRET_KEY='valor-largo-y-aleatorio'
APP_UTC_OFFSET_HOURS=-5
OVERDUE_NOTIFICATION_HOUR=8
OVERDUE_CHECK_INTERVAL_SECONDS=3600

CPANEL_SMTP_HOST=mail.cidti.com.co
CPANEL_SMTP_PORT=465
CPANEL_SMTP_USER=notificaciones@cidti.com.co
CPANEL_SMTP_PASSWORD='contrasena-de-la-cuenta-cpanel'
CPANEL_SMTP_FROM=notificaciones@cidti.com.co
CPANEL_SMTP_USE_SSL=true
CPANEL_SMTP_USE_TLS=false
```

Las comillas simples ayudan a conservar caracteres especiales en las
contrasenas. `CPANEL_SMTP_HOST` debe ser el hostname mostrado por
**Connect Devices**, no `localhost`.

Para actualizar conservando la informacion:

```bash
bash scripts/update-kanban.sh
```

El script:

- crea un backup en `migration-backups/`;
- reconstruye la imagen;
- reemplaza los contenedores;
- conserva los volumenes de MySQL y fotos;
- elimina el antiguo contenedor de correo si existia.

No ejecute `docker compose down -v`.

## 4. Validar la conexion con Exim

Compruebe los contenedores y el mapeo del hostname:

```bash
docker compose ps
docker compose exec app getent hosts mail.cidti.com.co
docker compose exec app python -c \
  "import socket,ssl; c=ssl.create_default_context(); s=c.wrap_socket(socket.create_connection(('mail.cidti.com.co',465),10),server_hostname='mail.cidti.com.co'); print(s.recv(200).decode()); s.close()"
```

El hostname debe resolver a la direccion gateway del anfitrion y la segunda
prueba debe mostrar un saludo SMTP de Exim.

Envie un mensaje real:

```bash
docker compose exec app \
  python -m app.scripts.test_email destino@dominio.com
```

Revise el resultado en **WHM > Email > Mail Delivery Reports** o mediante:

```bash
tail -f /var/log/exim_mainlog
exim -bp
```

## 5. Diagnostico rapido

- `Connection refused`: Exim no escucha en 465 o el firewall bloquea la red de
  Docker.
- `Authentication failed`: usuario o contrasena incorrectos.
- Error de certificado: `CPANEL_SMTP_HOST` no coincide con el certificado.
- El mensaje queda en cola: revise `/var/log/exim_mainlog`, DNS, PTR y la salida
  TCP/25.
- El correo llega a spam: revise SPF, DKIM, DMARC, PTR y reputacion de la IP.
