# Operación: despliegue, actualización y backups

Aquí no hay credenciales. Los accesos al servidor (usuarios, SSH) están en
`../DOCUMENTACION-TRASPASO.md`, fuera del repo.

## Cómo está montada producción

- Docker Compose con el perfil `prod` (`docker-compose.yml`, proyecto
  `englishworldcenter-chatbot`). Los contenedores son
  `ai-learning-platform-ewc-postgres`, `-temporal`, `-backend` y
  `-frontend-prod`.
- El **Apache del servidor** hace de proxy inverso y gestiona el TLS (Let's
  Encrypt). Su configuración está en `scripts/apache-ewc-config.inc.sh`.
- El frontend lo sirve un **nginx dentro de `frontend-prod`**
  (`frontend/nginx.conf.PROD.container`) en el puerto 8080 del servidor. El
  backend escucha en el 3000.
- Volúmenes: `ai-learning-platform-postgres-data` (BD),
  `ai-learning-platform-backend-uploads` (imágenes subidas) y
  `ai-learning-platform-backend-logs`.
- La base de datos se llama `ai_learning_platform`.

## Actualizar producción

**Antes**

1. Hacer un snapshot del VPS.
2. Elegir un momento fuera del horario de clases: el script reinicia el backend
   y corta las llamadas en curso.
3. Si el despliegue lleva migración, mira el aviso sobre `migrate-database.sh`
   en «Después».

**`./upgrade-production.sh`** es interactivo y se ejecuta como usuario de
despliegue o como root. En orden:

1. Pide confirmar que se ha hecho el snapshot.
2. Hace un backup con `backup.sh`.
3. Para el backend, el frontend y Temporal; PostgreSQL sigue funcionando.
4. Limpia las imágenes de Docker que han quedado sin usar.
5. Copia los `.env` con la fecha.
6. Hace `git pull`, después de pedir confirmación.
7. Reconstruye y arranca los contenedores.
8. Pasa una auditoría de vulnerabilidades.
9. Aplica las migraciones (`scripts/migrate-database.sh`).
10. Reinicia el backend.
11. Comprueba la salud del backend (`/health`, 5 intentos).

⚠️ **Las confirmaciones exigen escribir `yes` exacto.** Con un espacio de más
se cancela sin avisar con claridad y vuelve a arrancar las imágenes que había.
Pasó el 27-ago-2026.

**Después**

- Comprueba en la app lo que haya cambiado y haz una llamada de prueba con un
  alumno de prueba.
- Si había migración: `scripts/migrate-database.sh` dice «OK» aunque falle
  (ver [status.md](status.md)), así que hay que comprobar el estado a mano:

  ```bash
  docker exec ai-learning-platform-ewc-backend npx prisma migrate status --schema=./prisma/schema.prisma
  ```

- Si una migración queda marcada como fallida, pero se ha comprobado en la BD
  que el cambio sí está aplicado, se marca con
  `npx prisma migrate resolve --applied <migración>`. Es lo que se hizo con
  `20260815120000_add_bot_transcription_language` en agosto de 2026.

**Volver atrás**

- Volver al commit anterior y desplegar otra vez.
- No restaurar el `pg_dump` como primera opción: se perdería todo lo
  registrado desde el despliegue (consumo, conversaciones).

## Despliegue inicial

- `./clone-repository.sh` clona el proyecto en el vhost. Se ejecuta como el
  usuario de despliegue, sin sudo.
- `./deploy-to-server.sh <dominio> <email>` instala Apache con Certbot, un
  servicio de systemd y el cron de backup.

## Backups

- `./backup.sh` hace un `pg_dump` de la BD y copia los uploads y los logs en
  `/home/deploy/backups/AAAAMMDD/` (la ruta está fija en el script). También
  borra los backups de más de 7 días y renueva el certificado
  (`certbot renew`). Lo ejecuta `upgrade-production.sh` antes de actualizar, y
  `deploy-to-server.sh` lo programa con cron.
- `./restore.sh` es interactivo: lista los 5 últimos backups, restaura la BD,
  los uploads y los logs, y reinicia los servicios.
- `backup-copy.sh` es una variante de `backup.sh` que guarda en
  `/home/$USER/backups`. No la llama ningún script.

## Otros scripts

| Script | Para qué |
|---|---|
| `health-check.sh` | Comprueba los contenedores, los servicios, la BD y la conectividad |
| `diagnose-production.sh` | Recoge información del sistema para diagnosticar problemas |
| `check-ports.sh` | Comprueba si los puertos del servidor están libres |
| `security-audit.sh` | Verificación de seguridad |
| `fix-apache-ewc.sh` | Repara solo la configuración de Apache (proxy y TLS); no toca Docker ni la BD |
| `fix-migration-baseline.sh` | Corrige el baseline de migraciones (error P3005) |
| `upgrade-production-with-root.sh` | Reconstruye como root después de un `git pull` manual hecho con el usuario de despliegue |
| `start-production.sh`, `stop-production.sh` | Arrancan y paran producción |
| `start-development.sh`, `stop-development.sh`, `rebuild_development.sh` | Arrancan, paran y reconstruyen el entorno local |
| `clean-docker.sh` | Limpia las imágenes de Docker sin usar |
| `setup-openai.sh` | Configura OpenAI por línea de comandos (también se puede desde Configuración) |
| `create-admin-user.js` | Crea un usuario ADMIN con los datos escritos en el propio script, si no existe (ver [status.md](status.md#seguridad-urgente)) |

## Problemas conocidos

- **No puedo entrar en local.** El seed crea `admin@`, `teacher@` y
  `student@example.com`; sus contraseñas están en `backend/src/prisma/seed.ts`.
  Con Playwright u otro navegador automatizado, pon un User-Agent de navegador
  normal (`blockBotsOnAuth`).
- **Error P3005 al migrar** (la BD no está vacía): usa
  `./fix-migration-baseline.sh`, o hazlo a mano con `prisma migrate status`,
  `prisma migrate resolve --applied <migración>` y `prisma migrate deploy`.
- **Nunca en producción** `prisma migrate reset` ni `docker compose down -v`:
  los dos borran la BD.
- **Algo nuevo del backend no funciona en local** (por ejemplo, 404 en una ruta
  nueva): la imagen puede ser antigua o faltar una migración. Reconstruye con
  `docker compose --profile dev up -d --build` y aplica las migraciones. Pasó en
  agosto de 2026.
- **El frontend de producción llama a una API equivocada**: `VITE_API_URL` se
  fija al construir. Después de cambiarla, ejecuta
  `docker compose --profile prod build --no-cache frontend-prod`.
- **Parece que se han perdido datos**: comprueba que el volumen existe
  (`docker volume ls | grep postgres`) y que el contenedor lo usa
  (`docker inspect ai-learning-platform-ewc-postgres | grep -A5 Mounts`).
