193 lines
7.4 KiB
Markdown
193 lines
7.4 KiB
Markdown
# Despliegue en Coolify — Moraworld Imports
|
|
|
|
> **TL;DR** — Coolify gestiona Postgres + Redis. Solo necesitas el repo, `coolify-compose.yml` y las variables de `.env.example`.
|
|
|
|
---
|
|
|
|
## 1️⃣ Requisitos previos
|
|
|
|
- Servidor con **Docker 24+** y **Coolify** instalado (`curl -fsSL https://get.coolify.io | bash`)
|
|
- Dominio propio con DNS apuntando al servidor (A/AAAA + wildcard `*.tu-dominio.com`)
|
|
- Cuenta GitHub/GitLab con el repo clonado
|
|
|
|
---
|
|
|
|
## 2️⃣ Crear Project en Coolify
|
|
|
|
1. **Projects → New Project** → nombre: `moraworld-imports`
|
|
2. **Resources → New → Docker Compose**
|
|
- **Repository**: `https://github.com/lizandrogd/moraworld-imports`
|
|
- **Branch**: `main`
|
|
- **Compose file**: `coolify-compose.yml`
|
|
- **Build pack**: `Dockerfile` (auto-detectado)
|
|
|
|
---
|
|
|
|
## 3️⃣ Servicios gestionados (managed services)
|
|
|
|
En el projecto → **Services → Add Service**:
|
|
|
|
| Servicio | Tipo | Nombre lógico | Notas |
|
|
|----------|------|---------------|-------|
|
|
| **PostgreSQL** | `PostgreSQL 16` | `postgres` | Coolify inyecta `DATABASE_URL` |
|
|
| **Redis** | `Redis 7` | `redis` | Coolify inyecta `REDIS_URL` |
|
|
| **MinIO** (opcional) | `MinIO` | `minio` | Solo si no usas S3 externo; expón puertos 9000/9001 |
|
|
|
|
> **Importante**: Los nombres lógicos (`postgres`, `redis`) deben coincidir con los hostnames usados en `DATABASE_URL`/`REDIS_URL` si los escribes a mano. Coolify los resuelve automáticamente.
|
|
|
|
---
|
|
|
|
## 4️⃣ Variables de entorno
|
|
|
|
En **Project → Environment Variables**, añade **una por una** (no pegues el bloque completo):
|
|
|
|
| Variable | Ejemplo / Generación |
|
|
|----------|----------------------|
|
|
| `NODE_ENV` | `production` |
|
|
| `NEXT_PUBLIC_API_URL` | `https://api.tu-dominio.com` |
|
|
| `NEXT_PUBLIC_WS_URL` | `https://api.tu-dominio.com` |
|
|
| `JWT_SECRET` | `openssl rand -base64 48` |
|
|
| `JWT_REFRESH_SECRET` | `openssl rand -base64 48` (distinto) |
|
|
| `AUDIT_HMAC_SECRET` | `openssl rand -hex 32` |
|
|
| `CORS_ORIGINS` | `https://app.tu-dominio.com,https://www.tu-dominio.com` |
|
|
| `S3_ENDPOINT` | `https://s3.tu-proveedor.com` (o vacío para disco local) |
|
|
| `S3_ACCESS_KEY` | `minioadmin` |
|
|
| `S3_SECRET_KEY` | `minioadmin` |
|
|
| `S3_BUCKET` | `moraworld-imports` |
|
|
| `S3_REGION` | `us-east-1` |
|
|
| `S3_PUBLIC_URL` | `https://cdn.tu-dominio.com` |
|
|
| `STRIPE_WEBHOOK_SECRET` | `whsec_...` (de Stripe Dashboard) |
|
|
|
|
> **No pongas** claves de Zeptomail, SENAE, Amazon, Twilio, WhatsApp, etc. aquí. Se configuran en **Admin → Integraciones** tras el primer deploy.
|
|
|
|
---
|
|
|
|
## 5️⃣ Dominios y TLS
|
|
|
|
En **Project → Domains** añade:
|
|
|
|
| Dominio | Servicio | Puerto | TLS |
|
|
|---------|----------|--------|-----|
|
|
| `api.tu-dominio.com` | `api` | `3001` | ✅ Auto |
|
|
| `app.tu-dominio.com` | `web` | `3000` | ✅ Auto |
|
|
| `ws.tu-dominio.com` | `api` | `3001` | ✅ Auto (WebSocket) |
|
|
|
|
Coolify genera certificados Let's Encrypt automáticos y renueva cada 60 días.
|
|
|
|
> **WebSocket**: el gateway corre en `/ws` bajo el mismo puerto 3001. El dominio `ws.tu-dominio.com` apunta al mismo servicio `api`.
|
|
|
|
---
|
|
|
|
## 6️⃣ Health Checks
|
|
|
|
Coolify usa los health checks del `docker-compose` para saber cuándo el servicio está listo:
|
|
|
|
- **API**: `GET http://localhost:3001/api/health` → 200 OK
|
|
- **Web**: `GET http://localhost:3000/status` → 200 OK (crea `apps/web/public/status.txt` con `ok` si no existe)
|
|
|
|
Si el health check falla, Coolify reintenta según `retries` y `start_period`.
|
|
|
|
---
|
|
|
|
## 7️⃣ Primer deploy y post-configuración
|
|
|
|
1. **Deploy** → espera a que ambos servicios estén "Healthy"
|
|
2. Entra a `https://app.tu-dominio.com`
|
|
3. Regístrate (primer usuario = `SUPER_ADMIN` automático si BD vacía)
|
|
4. Ve a **Admin → Configuración → Integraciones** y guarda:
|
|
- **Zeptomail**: `zeptomail_api_key`, `email_from`, `email_from_name`
|
|
- **SENAE**: `senae_endpoint`, `senae_api_key`, `senae_ruc`, `senae_agent_code`
|
|
- **Stripe**: `stripe_public_key`, `stripe_secret_key`, `stripe_webhook_secret`
|
|
- **Amazon SP-API**: `amazon_client_id`, `amazon_client_secret`, `amazon_refresh_token`
|
|
- **Twilio SMS**: `sms_account_sid`, `sms_auth_token`, `sms_from_number`
|
|
- **WhatsApp Business**: `whatsapp_api_token`, `whatsapp_phone_number_id`
|
|
- **Couriers** (FedEx/DHL/UPS), **INEN**, **Bodega**, etc. según necesites
|
|
5. **Stripe Webhook** en Dashboard → `https://api.tu-dominio.com/api/payments/webhook?tenant=mi-tenant-slug`
|
|
- Eventos: `checkout.session.completed`, `checkout.session.expired`
|
|
|
|
---
|
|
|
|
## 8️⃣ Actualizaciones
|
|
|
|
**Auto-deploy** (recomendado):
|
|
- Project → Settings → **Auto Deploy** = ON
|
|
- Push a `main` → Coolify detecta, build y despliega sin downtime (rolling update)
|
|
|
|
**Manual**:
|
|
- Project → Deploy → **Force rebuild** si cambiaste Dockerfile o dependencias
|
|
|
|
---
|
|
|
|
## 9️⃣ Backups y recuperación
|
|
|
|
- **PostgreSQL**: Coolify → Service `postgres` → Backups → Schedule (diario/semanal)
|
|
- **Redis**: No crítico (cache/sesiones), pero puedes snapshottear
|
|
- **MinIO**: Versiona el bucket o replica a otro S3
|
|
- **Código**: GitHub es la fuente de verdad
|
|
|
|
Para restaurar: detén servicios → restaura dump SQL → `pnpm prisma db push` → reinicia.
|
|
|
|
---
|
|
|
|
## 🔟 Troubleshooting rápido
|
|
|
|
| Síntoma | Causa probable | Solución |
|
|
|---------|----------------|----------|
|
|
| API 502 / health fail | `DATABASE_URL` mal formada | Revisa variable; usa hostname `postgres` |
|
|
| WebSocket no conecta | Dominio `ws.` no apunta a `api` | Añade dominio `ws.tu-dominio.com` → servicio `api` |
|
|
| CORS error | `CORS_ORIGINS` sin tu frontend | Añade `https://app.tu-dominio.com` |
|
|
| Stripe webhook 404 | URL mal escrita en Dashboard | Debe ser `/api/payments/webhook?tenant=<slug>` |
|
|
| Prisma migrate fail | `prisma db push` en prod | Usa `prisma migrate deploy` en CI si migras schema |
|
|
| Uploads 404 | `S3_ENDPOINT` vacío pero archivos en disco | Configura MinIO/S3 o sirve `/uploads` vía reverse proxy |
|
|
|
|
---
|
|
|
|
## 📁 Estructura de archivos Coolify
|
|
|
|
```
|
|
moraworld-imports/
|
|
├── coolify-compose.yml # ← Coolify usa este archivo
|
|
├── .env.example # ← Copia valores a Coolify UI
|
|
├── apps/
|
|
│ ├── api/Dockerfile # Multi-stage, standalone node
|
|
│ └── web/Dockerfile # Next.js standalone output
|
|
├── packages/database/ # Prisma schema
|
|
└── COOLIFY.md # ← Este archivo
|
|
```
|
|
|
|
---
|
|
|
|
## 🔐 Secrets management
|
|
|
|
Coolify encripta las variables marcadas como **Secret** en la UI.
|
|
Para rotar secrets:
|
|
1. Genera nuevo valor local
|
|
2. Actualiza en Coolify → Environment Variables
|
|
3. Redeploy (rolling, cero downtime)
|
|
|
|
---
|
|
|
|
## 📊 Monitoring básico
|
|
|
|
- **Logs**: Coolify → Service → Logs (stdout/stderr)
|
|
- **Metrics**: Coolify → Service → Metrics (CPU, RAM, Network)
|
|
- **Uptime**: Configura Uptime Kuma / Better Uptime apuntando a `/api/health` y `/status`
|
|
|
|
---
|
|
|
|
## 🚀 Checklist pre-producción
|
|
|
|
- [ ] `JWT_SECRET` y `JWT_REFRESH_SECRET` únicos, 48+ chars base64
|
|
- [ ] `AUDIT_HMAC_SECRET` 32+ chars hex
|
|
- [ ] `CORS_ORIGINS` solo tus dominios reales (sin `*`)
|
|
- [ ] `DATABASE_URL` apunta a Postgres gestionado por Coolify
|
|
- [ ] `REDIS_URL` apunta a Redis gestionado por Coolify
|
|
- [ ] Dominios `api.`, `app.`, `ws.` creados en Coolify con TLS
|
|
- [ ] Health checks pasan en ambos servicios
|
|
- [ ] Integraciones guardadas en Admin UI
|
|
- [ ] Stripe webhook registrado y probado
|
|
- [ ] Backup automático de Postgres configurado
|
|
|
|
---
|
|
|
|
**¿Problemas?** Revisa logs en Coolify → Service → Logs. La mayoría son variables de entorno mal escritas o health checks que tardan más de `start_period`. |