workspace/projects/gamilit/docs/95-guias-desarrollo/GUIA-DESPLIEGUE-PRODUCCION-COMPLETA.md
rckrdmrd a23f31ce8f feat(db): Sincronizar scripts de BD y documentacion de produccion
## Scripts de Base de Datos (12 archivos)
- init-database.sh: Inicializacion completa con usuario y BD
- init-database-v3.sh: Version con dotenv-vault
- reset-database.sh: Reset BD manteniendo usuario
- recreate-database.sh: Recreacion completa
- cleanup-duplicados.sh, fix-duplicate-triggers.sh
- verify-users.sh, verify-missions-status.sh
- load-users-and-profiles.sh, DB-127-validar-gaps.sh

## Scripts de Produccion (5 archivos)
- build-production.sh: Compilar backend y frontend
- deploy-production.sh: Desplegar con PM2
- pre-deploy-check.sh: Validaciones pre-deploy
- repair-missing-data.sh: Reparar datos faltantes
- migrate-missing-objects.sh: Migrar objetos SQL

## Documentacion (7 archivos)
- GUIA-DESPLIEGUE-PRODUCCION-COMPLETA.md
- GUIA-ACTUALIZACION-PRODUCCION.md
- GUIA-VALIDACION-PRODUCCION.md
- GUIA-DEPLOYMENT-AGENTE-PRODUCCION.md
- GUIA-SSL-NGINX-PRODUCCION.md
- GUIA-SSL-AUTOFIRMADO.md
- DIRECTIVA-DEPLOYMENT.md

## Actualizaciones DDL/Seeds
- 99-post-ddl-permissions.sql: Permisos actualizados
- LOAD-SEEDS-gamification_system.sh: Seeds completos

## Nuevos archivos
- PROMPT-AGENTE-PRODUCCION.md: Prompt para agente productivo
- FLUJO-CARGA-LIMPIA.md: Documentacion de carga limpia

Resuelve: Problema de carga de BD entre dev y produccion
Cumple: DIRECTIVA-POLITICA-CARGA-LIMPIA.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 15:01:03 -06:00

1201 lines
38 KiB
Markdown

# Guia Completa de Despliegue en Produccion - GAMILIT
> **Version:** 1.0.0
> **Fecha:** 2025-12-18
> **Servidor:** 74.208.126.102
> **Autor:** Documentacion generada por analisis de configuracion existente
---
## Indice
1. [Resumen Ejecutivo](#1-resumen-ejecutivo)
2. [Arquitectura de Produccion](#2-arquitectura-de-produccion)
3. [Pre-requisitos del Servidor](#3-pre-requisitos-del-servidor)
4. [Configuracion de Base de Datos](#4-configuracion-de-base-de-datos)
5. [Configuracion de Aplicaciones](#5-configuracion-de-aplicaciones)
6. [Proceso de Despliegue con PM2](#6-proceso-de-despliegue-con-pm2)
7. [Configuracion HTTPS con Certbot](#7-configuracion-https-con-certbot)
8. [Comandos de Referencia Rapida](#8-comandos-de-referencia-rapida)
9. [Troubleshooting](#9-troubleshooting)
---
## 1. Resumen Ejecutivo
### Componentes Desplegados
| Componente | Puerto | Instancias | Tecnologia |
|------------|--------|------------|------------|
| **Backend API** | 3006 | 2 (cluster) | NestJS + TypeORM |
| **Frontend** | 3005 | 1 (fork) | React + Vite |
| **PostgreSQL** | 5432 | 1 | PostgreSQL 16+ |
### URLs de Acceso
```
Frontend: http://74.208.126.102:3005
Backend API: http://74.208.126.102:3006/api
API Docs: http://74.208.126.102:3006/api/docs (deshabilitado en produccion)
```
---
## 2. Arquitectura de Produccion
```
┌─────────────────────────────────────────────────────────────┐
│ SERVIDOR 74.208.126.102 │
│ │
Usuario │ ┌──────────────┐ ┌──────────────────────────────┐ │
│ │ │ Frontend │ │ Backend API │ │
│ │ │ (Vite) │ │ (NestJS) │ │
│ │ │ :3005 │ │ :3006 │ │
▼ │ │ │ │ ┌────────┐ ┌────────┐ │ │
┌──────┐ │ │ 1 instancia │ │ │ Inst 1 │ │ Inst 2 │ │ │
│ HTTP │──────────┼───┤ │◄─────┼──┤ Cluster│ │ Cluster│ │ │
└──────┘ │ └──────────────┘ │ └────────┘ └────────┘ │ │
│ └──────────────┬───────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────┐ │
│ │ PostgreSQL 16+ │ │
│ │ :5432 │ │
│ │ DB: gamilit_platform │ │
│ └──────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ PM2 │ │
│ │ - Gestion de procesos │ │
│ │ - Auto-restart │ │
│ │ - Cluster mode (backend) │ │
│ │ - Logs centralizados │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
---
## 3. Pre-requisitos del Servidor
### Software Requerido
| Software | Version Minima | Comando de Verificacion |
|----------|---------------|------------------------|
| Node.js | 18.0.0+ | `node -v` |
| npm | 9.0.0+ | `npm -v` |
| PostgreSQL | 16+ | `psql --version` |
| PM2 | Latest | `pm2 -v` |
| Git | Latest | `git --version` |
### Instalacion de PM2 (si no esta instalado)
```bash
npm install -g pm2
```
### Verificacion Pre-Deploy
```bash
# Verificar Node.js
node -v # Debe ser >= 18.0.0
# Verificar npm
npm -v # Debe ser >= 9.0.0
# Verificar PostgreSQL
psql --version
# Verificar PM2
pm2 -v
# Verificar espacio en disco
df -h
```
---
## 4. Configuracion de Base de Datos
### 4.1 Estructura de Schemas
La base de datos contiene **17 schemas**:
| Schema | Descripcion |
|--------|-------------|
| `auth` | Autenticacion (Supabase-compatible) |
| `auth_management` | Gestion de usuarios, perfiles, roles |
| `educational_content` | Modulos, ejercicios, rubricas |
| `gamification_system` | XP, ML Coins, logros, rangos, tienda |
| `progress_tracking` | Progreso de usuarios, intentos |
| `social_features` | Escuelas, aulas, amistades |
| `notifications` | Sistema de notificaciones |
| `content_management` | Gestion de contenido |
| `communication` | Mensajeria entre usuarios |
| `audit_logging` | Logs de auditoria |
| `system_configuration` | Feature flags, parametros |
| `admin_dashboard` | Vistas administrativas |
| `lti_integration` | Learning Tools Interoperability |
| `storage` | Almacenamiento de archivos |
| `gamilit` | Funciones compartidas |
| `public` | Schema legacy |
### 4.2 Credenciales de Base de Datos
```bash
# Variables de entorno requeridas
DB_HOST=localhost
DB_PORT=5432
DB_NAME=gamilit_platform
DB_USER=gamilit_user
DB_PASSWORD=<CONTRASEÑA_SEGURA>
```
### 4.3 Crear Base de Datos desde Cero
#### Opcion A: Creacion Limpia (Recomendado para primer despliegue)
```bash
cd apps/database
# Definir URL de conexion
export DATABASE_URL="postgresql://gamilit_user:<PASSWORD>@localhost:5432/gamilit_platform"
# Ejecutar script de creacion
./create-database.sh "$DATABASE_URL"
```
#### Opcion B: Drop y Recreacion (Para reset completo)
```bash
cd apps/database
# ADVERTENCIA: Esto ELIMINARA toda la data existente
export DATABASE_URL="postgresql://gamilit_user:<PASSWORD>@localhost:5432/gamilit_platform"
./drop-and-recreate-database.sh "$DATABASE_URL"
```
### 4.4 Fases de Creacion de Base de Datos
El script `create-database.sh` ejecuta **16 fases** en orden:
| Fase | Descripcion | Contenido |
|------|-------------|-----------|
| 0 | Extensions | pgcrypto, uuid-ossp |
| 1 | Prerequisites | Schemas y ENUMs base |
| 2 | Funciones Compartidas | Schema gamilit |
| 3 | Auth Schema | Autenticacion Supabase |
| 4 | Storage Schema | Almacenamiento |
| 5 | Auth Management | Usuarios, perfiles |
| 6 | Educational Content | Modulos, ejercicios |
| 6.5 | Notifications | Sistema de notificaciones |
| 7 | Gamification System | XP, rangos, logros |
| 8 | Progress Tracking | Progreso usuarios |
| 9 | Social Features | Escuelas, aulas |
| 9.5 | FK Constraints | Dependencias circulares |
| 10 | Content Management | Gestion contenido |
| 10.5 | Communication | Mensajeria |
| 11 | Audit Logging | Logs auditoria |
| 12-15 | Otros | Config, Admin, LTI |
| 16 | **Seeds PROD** | **57 archivos de datos iniciales** |
### 4.5 Seeds de Produccion (57 archivos)
Los seeds de produccion cargan:
| Categoria | Registros | Descripcion |
|-----------|-----------|-------------|
| **Usuarios** | 48 | 3 testing + 45 produccion |
| **Modulos** | 5 | Modulos educativos (M1-M5) |
| **Ejercicios** | 23 | M1: 5, M2: 5, M3: 5, M4: 5, M5: 3 |
| **Logros** | 30 | Achievement system |
| **Rangos Maya** | 5 | Ajaw, Nacom, Ah K'in, Halach Uinic, K'uk'ulkan |
| **Tienda** | 25 | 5 categorias, 20 items |
| **Misiones** | 11 | Templates de misiones |
| **Feature Flags** | 26 | Configuracion de features |
| **Escuelas** | 2+ | Demo + produccion |
| **Aulas** | 4+ | Aulas de prueba |
---
## 5. Configuracion de Aplicaciones
### 5.1 Backend - `.env.production`
Ubicacion: `apps/backend/.env.production`
```bash
# ============================================================================
# GAMILIT Backend - Production Environment
# Servidor: 74.208.126.102
# ============================================================================
# Server
NODE_ENV=production
PORT=3006
API_PREFIX=api
# Database
DB_HOST=localhost
DB_PORT=5432
DB_NAME=gamilit_platform
DB_USER=gamilit_user
DB_PASSWORD=${DB_PASSWORD}
DB_SYNCHRONIZE=false
DB_LOGGING=false
# JWT (IMPORTANTE: Cambiar a valor seguro)
# Generar con: openssl rand -base64 32
JWT_SECRET=${JWT_SECRET}
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
# CORS
CORS_ORIGIN=http://74.208.126.102:3005,http://74.208.126.102,http://74.208.126.102:80
ENABLE_CORS=true
ENABLE_SWAGGER=false
# Logging
LOG_LEVEL=warn
LOG_TO_FILE=true
# Rate Limiting
RATE_LIMIT_TTL=60
RATE_LIMIT_MAX=100
# Session
SESSION_SECRET=${SESSION_SECRET}
SESSION_MAX_AGE=86400000
# Email
EMAIL_FROM=noreply@gamilit.com
EMAIL_REPLY_TO=support@gamilit.com
# Frontend URL
FRONTEND_URL=http://74.208.126.102:3005
```
### 5.2 Frontend - `.env.production`
Ubicacion: `apps/frontend/.env.production`
```bash
# ============================================================================
# GAMILIT Frontend - Production Environment
# Servidor: 74.208.126.102
# ============================================================================
# Application
VITE_APP_NAME=GAMILIT Platform
VITE_APP_VERSION=1.0.0
VITE_APP_ENV=production
VITE_ENV=production
# API Configuration
VITE_API_HOST=74.208.126.102:3006
VITE_API_PROTOCOL=http
VITE_API_VERSION=v1
VITE_API_TIMEOUT=30000
# WebSocket
VITE_WS_HOST=74.208.126.102:3006
VITE_WS_PROTOCOL=ws
# Authentication
VITE_JWT_EXPIRATION=7d
# Feature Flags
VITE_ENABLE_GAMIFICATION=true
VITE_ENABLE_SOCIAL_FEATURES=true
VITE_ENABLE_ANALYTICS=true
VITE_ENABLE_DEBUG=false
VITE_ENABLE_STORYBOOK=false
VITE_MOCK_API=false
# External Services (configurar en produccion)
VITE_GOOGLE_ANALYTICS_ID=
VITE_SENTRY_DSN=
# Logging
VITE_LOG_LEVEL=error
```
### 5.3 PM2 - `ecosystem.config.js`
Ubicacion: Raiz del proyecto
```javascript
module.exports = {
apps: [
// BACKEND - NestJS API
{
name: 'gamilit-backend',
cwd: './apps/backend',
script: 'dist/main.js',
node_args: '-r tsconfig-paths/register',
instances: 2, // 2 instancias en cluster
exec_mode: 'cluster',
autorestart: true,
watch: false,
max_memory_restart: '1G',
env_production: {
NODE_ENV: 'production',
PORT: 3006,
},
env_file: './.env.production',
error_file: '../../logs/backend-error.log',
out_file: '../../logs/backend-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
min_uptime: '10s',
max_restarts: 10,
kill_timeout: 5000,
wait_ready: true,
listen_timeout: 10000,
},
// FRONTEND - Vite Preview
{
name: 'gamilit-frontend',
cwd: './apps/frontend',
script: 'npx',
args: 'vite preview --port 3005 --host 0.0.0.0',
instances: 1,
exec_mode: 'fork',
autorestart: true,
watch: false,
max_memory_restart: '512M',
env_production: {
NODE_ENV: 'production',
VITE_ENV: 'production',
},
env_file: './.env.production',
error_file: '../../logs/frontend-error.log',
out_file: '../../logs/frontend-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
min_uptime: '10s',
max_restarts: 10,
kill_timeout: 5000,
},
],
};
```
---
## 6. Proceso de Despliegue con PM2
### 6.1 Flujo Completo de Despliegue
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ PROCESO DE DESPLIEGUE PRODUCCION │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ PASO 1: Preparacion │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ 1.1 git pull origin main │ │
│ │ 1.2 Verificar pre-requisitos │ │
│ │ 1.3 Configurar variables de entorno (.env.production) │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ PASO 2: Base de Datos (si es necesario) │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ 2.1 cd apps/database │ │
│ │ 2.2 export DATABASE_URL="postgresql://..." │ │
│ │ 2.3 ./create-database.sh "$DATABASE_URL" (o drop-and-recreate) │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ PASO 3: Build de Aplicaciones │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ 3.1 cd apps/backend && npm install && npm run build │ │
│ │ 3.2 cd apps/frontend && npm install && npm run build:prod │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ PASO 4: Despliegue PM2 │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ 4.1 pm2 start ecosystem.config.js --env production │ │
│ │ 4.2 pm2 save │ │
│ │ 4.3 pm2 startup (para auto-inicio) │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ PASO 5: Verificacion │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ 5.1 pm2 status │ │
│ │ 5.2 curl http://74.208.126.102:3006/api/health │ │
│ │ 5.3 Acceder a http://74.208.126.102:3005 │ │
│ └────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
### 6.2 Comandos Paso a Paso
#### Paso 1: Preparacion
```bash
# Ir al directorio del proyecto
cd /path/to/gamilit
# Obtener ultimos cambios
git pull origin main
```
#### Paso 2: Base de Datos (Solo si es necesario)
```bash
# Ir al directorio de database
cd apps/database
# Configurar URL de conexion
export DATABASE_URL="postgresql://gamilit_user:TU_PASSWORD@localhost:5432/gamilit_platform"
# OPCION A: Crear base de datos nueva
./create-database.sh "$DATABASE_URL"
# OPCION B: Reset completo (ELIMINA TODA LA DATA)
./drop-and-recreate-database.sh "$DATABASE_URL"
# Volver al directorio raiz
cd ../..
```
#### Paso 3: Build de Aplicaciones
```bash
# Build Backend
cd apps/backend
npm install
npm run build
# Verificar build exitoso
ls -la dist/main.js
# Build Frontend
cd ../frontend
npm install
npm run build:prod
# Verificar build exitoso
ls -la dist/
# Volver al directorio raiz
cd ../..
```
#### Paso 4: Despliegue con PM2
```bash
# Crear directorio de logs
mkdir -p logs
# Detener procesos anteriores (si existen)
pm2 delete gamilit-backend gamilit-frontend 2>/dev/null || true
# Iniciar aplicaciones
pm2 start ecosystem.config.js --env production
# Guardar configuracion
pm2 save
# Configurar inicio automatico (primera vez)
pm2 startup
# Ejecutar el comando que muestre el output anterior
```
#### Paso 5: Verificacion
```bash
# Ver estado de procesos
pm2 status
# Verificar health del backend
curl http://74.208.126.102:3006/api/health
# Ver logs en tiempo real
pm2 logs
# Acceder al frontend en el navegador
# http://74.208.126.102:3005
```
### 6.3 Script Automatizado
Existe un script que automatiza el proceso:
```bash
# Ejecutar script de despliegue
./scripts/deploy-production.sh
```
Este script:
1. Verifica que PM2 este instalado
2. Verifica que los builds existan
3. Verifica archivos `.env.production`
4. Crea directorio de logs
5. Detiene procesos PM2 existentes
6. Inicia backend (2 instancias cluster)
7. Inicia frontend (1 instancia)
8. Guarda configuracion PM2
9. Muestra resumen final
---
## 7. Configuracion HTTPS con Certbot
### 7.1 Arquitectura HTTPS
```
ARQUITECTURA HTTPS PRODUCCION
┌─────────────────────────────────────────────────────────────────────────────┐
│ │
│ Usuario │
│ │ │
│ │ HTTPS (443) │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ NGINX REVERSE PROXY │ │
│ │ (Terminacion SSL) │ │
│ │ │ │
│ │ ┌─────────────────────┐ ┌─────────────────────────────────┐ │ │
│ │ │ SSL Certificate │ │ Rutas: │ │ │
│ │ │ (Certbot/LE) │ │ / → Frontend :3005 │ │ │
│ │ │ │ │ /api → Backend :3006 │ │ │
│ │ │ /etc/letsencrypt/ │ │ /socket.io → Backend :3006 │ │ │
│ │ └─────────────────────┘ └─────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │ │
│ │ HTTP (interno) │ HTTP (interno) │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ Frontend │ │ Backend │ │
│ │ (Vite) │ │ (NestJS) │ │
│ │ :3005 │ │ :3006 │ │
│ │ interno │ │ interno │ │
│ └──────────────────┘ └──────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
**Concepto clave:** Nginx actua como terminador SSL. Las aplicaciones (Backend/Frontend) siguen corriendo en HTTP internamente, pero todo el trafico externo usa HTTPS.
### 7.2 Requisitos para HTTPS
| Requisito | Descripcion | Estado |
|-----------|-------------|--------|
| **Dominio** | Necesario para Certbot/Let's Encrypt | Opcional (IP requiere certificado autofirmado) |
| **Nginx** | Reverse proxy y terminador SSL | Requerido |
| **Certbot** | Cliente ACME para Let's Encrypt | Requerido (con dominio) |
| **Puertos abiertos** | 80 (HTTP), 443 (HTTPS) | Requerido |
### 7.3 Instalacion de Nginx y Certbot
```bash
# Actualizar repositorios
sudo apt update
# Instalar Nginx
sudo apt install nginx -y
# Verificar Nginx
sudo systemctl status nginx
# Instalar Certbot con plugin Nginx
sudo apt install certbot python3-certbot-nginx -y
# Verificar Certbot
certbot --version
```
### 7.4 Opcion A: HTTPS con Dominio (Recomendado)
#### Paso 1: Configurar DNS
Asegurar que el dominio apunte a la IP del servidor:
```
A Record: gamilit.com → 74.208.126.102
A Record: www.gamilit.com → 74.208.126.102
A Record: api.gamilit.com → 74.208.126.102 (opcional)
```
#### Paso 2: Configurar Nginx inicial (HTTP)
Crear `/etc/nginx/sites-available/gamilit`:
```nginx
server {
listen 80;
server_name gamilit.com www.gamilit.com;
# Frontend - React App
location / {
proxy_pass http://127.0.0.1:3005;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
# Backend API
location /api {
proxy_pass http://127.0.0.1:3006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
# Timeouts para API
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# WebSocket
location /socket.io {
proxy_pass http://127.0.0.1:3006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Timeouts para WebSocket
proxy_connect_timeout 7d;
proxy_send_timeout 7d;
proxy_read_timeout 7d;
}
}
```
Habilitar sitio:
```bash
# Crear symlink
sudo ln -s /etc/nginx/sites-available/gamilit /etc/nginx/sites-enabled/
# Eliminar default si existe
sudo rm /etc/nginx/sites-enabled/default 2>/dev/null || true
# Verificar configuracion
sudo nginx -t
# Recargar Nginx
sudo systemctl reload nginx
```
#### Paso 3: Obtener Certificado SSL con Certbot
```bash
# Obtener certificado (automatico)
sudo certbot --nginx -d gamilit.com -d www.gamilit.com
# Durante el proceso:
# 1. Ingresar email para notificaciones
# 2. Aceptar terminos de servicio
# 3. Elegir si redirigir HTTP a HTTPS (recomendado: SI)
```
Certbot automaticamente:
- Obtiene el certificado de Let's Encrypt
- Modifica la configuracion de Nginx
- Configura renovacion automatica
#### Paso 4: Verificar Configuracion Nginx (Post-Certbot)
Despues de ejecutar certbot, el archivo se vera asi:
```nginx
server {
listen 80;
server_name gamilit.com www.gamilit.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name gamilit.com www.gamilit.com;
# Certificados generados por Certbot
ssl_certificate /etc/letsencrypt/live/gamilit.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gamilit.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Frontend - React App
location / {
proxy_pass http://127.0.0.1:3005;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Backend API
location /api {
proxy_pass http://127.0.0.1:3006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket (wss://)
location /socket.io {
proxy_pass http://127.0.0.1:3006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
```
### 7.5 Opcion B: HTTPS con IP (Sin Dominio)
Si no tienes dominio, necesitas certificado autofirmado:
```bash
# Crear directorio para certificados
sudo mkdir -p /etc/nginx/ssl
# Generar certificado autofirmado (valido 365 dias)
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/gamilit.key \
-out /etc/nginx/ssl/gamilit.crt \
-subj "/C=MX/ST=Estado/L=Ciudad/O=Gamilit/CN=74.208.126.102"
```
Configuracion Nginx para IP con SSL:
```nginx
server {
listen 80;
server_name 74.208.126.102;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name 74.208.126.102;
# Certificado autofirmado
ssl_certificate /etc/nginx/ssl/gamilit.crt;
ssl_certificate_key /etc/nginx/ssl/gamilit.key;
# Configuracion SSL
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_session_cache shared:SSL:10m;
# Frontend
location / {
proxy_pass http://127.0.0.1:3005;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Backend API
location /api {
proxy_pass http://127.0.0.1:3006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket
location /socket.io {
proxy_pass http://127.0.0.1:3006;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
```
**Nota:** Los navegadores mostraran advertencia de certificado no confiable.
### 7.6 Actualizar Variables de Entorno para HTTPS
#### Backend `.env.production`
```bash
# ANTES (HTTP)
CORS_ORIGIN=http://74.208.126.102:3005,http://74.208.126.102
FRONTEND_URL=http://74.208.126.102:3005
# DESPUES (HTTPS con dominio)
CORS_ORIGIN=https://gamilit.com,https://www.gamilit.com,https://74.208.126.102
FRONTEND_URL=https://gamilit.com
# DESPUES (HTTPS con IP)
CORS_ORIGIN=https://74.208.126.102
FRONTEND_URL=https://74.208.126.102
```
#### Frontend `.env.production`
```bash
# ANTES (HTTP)
VITE_API_HOST=74.208.126.102:3006
VITE_API_PROTOCOL=http
VITE_WS_HOST=74.208.126.102:3006
VITE_WS_PROTOCOL=ws
# DESPUES (HTTPS con Nginx proxy - RECOMENDADO)
# Nginx maneja SSL, frontend accede via proxy
VITE_API_HOST=gamilit.com
VITE_API_PROTOCOL=https
VITE_WS_HOST=gamilit.com
VITE_WS_PROTOCOL=wss
# DESPUES (HTTPS con IP)
VITE_API_HOST=74.208.126.102
VITE_API_PROTOCOL=https
VITE_WS_HOST=74.208.126.102
VITE_WS_PROTOCOL=wss
```
### 7.7 Rebuild y Reinicio
Despues de cambiar las variables de entorno:
```bash
# 1. Rebuild del Frontend (variables VITE_ se embeben en build)
cd apps/frontend
npm run build:prod
# 2. Reiniciar servicios
pm2 restart all
# 3. Verificar Nginx
sudo nginx -t
sudo systemctl reload nginx
```
### 7.8 Renovacion Automatica de Certificados
Certbot configura renovacion automatica. Verificar:
```bash
# Ver timer de renovacion
sudo systemctl status certbot.timer
# Probar renovacion (dry-run)
sudo certbot renew --dry-run
# Forzar renovacion si es necesario
sudo certbot renew --force-renewal
```
Los certificados de Let's Encrypt expiran cada 90 dias. Certbot los renueva automaticamente.
### 7.9 URLs Finales con HTTPS
#### Con Dominio
```
Frontend: https://gamilit.com
Backend API: https://gamilit.com/api
WebSocket: wss://gamilit.com/socket.io
Health Check: https://gamilit.com/api/health
```
#### Con IP (certificado autofirmado)
```
Frontend: https://74.208.126.102
Backend API: https://74.208.126.102/api
WebSocket: wss://74.208.126.102/socket.io
Health Check: https://74.208.126.102/api/health
```
### 7.10 Verificacion HTTPS
```bash
# Verificar certificado SSL
curl -vI https://gamilit.com 2>&1 | grep -E "SSL|certificate|subject"
# Verificar API sobre HTTPS
curl -s https://gamilit.com/api/health | jq
# Verificar que HTTP redirige a HTTPS
curl -I http://gamilit.com
# Verificar WebSocket (requiere wscat)
npm install -g wscat
wscat -c wss://gamilit.com/socket.io
```
### 7.11 Checklist HTTPS
- [ ] Nginx instalado y corriendo
- [ ] Certbot instalado
- [ ] Dominio configurado en DNS (o usar IP)
- [ ] Configuracion Nginx creada en sites-available
- [ ] Symlink creado en sites-enabled
- [ ] `nginx -t` sin errores
- [ ] Certificado SSL obtenido (certbot o autofirmado)
- [ ] `CORS_ORIGIN` actualizado con https://
- [ ] `FRONTEND_URL` actualizado con https://
- [ ] `VITE_API_PROTOCOL=https` en frontend
- [ ] `VITE_WS_PROTOCOL=wss` en frontend
- [ ] Frontend recompilado (`npm run build:prod`)
- [ ] PM2 reiniciado (`pm2 restart all`)
- [ ] Nginx recargado (`sudo systemctl reload nginx`)
- [ ] Health check responde sobre HTTPS
- [ ] Frontend carga sin errores de mixed content
- [ ] WebSocket conecta sobre wss://
---
## 8. Comandos de Referencia Rapida
### PM2 - Operaciones Basicas
```bash
# Ver estado
pm2 status
pm2 list
# Logs
pm2 logs # Todos los logs
pm2 logs gamilit-backend # Solo backend
pm2 logs gamilit-frontend # Solo frontend
# Monitoreo
pm2 monit # Monitor interactivo
# Reinicio
pm2 restart all # Reiniciar todo
pm2 restart gamilit-backend # Solo backend
pm2 reload gamilit-backend # Zero-downtime reload
# Detener
pm2 stop all
pm2 stop gamilit-backend
# Eliminar
pm2 delete all
pm2 delete gamilit-backend
```
### PM2 - Operaciones Avanzadas
```bash
# Informacion detallada
pm2 show gamilit-backend
# Flush logs
pm2 flush
# Guardar configuracion
pm2 save
# Restaurar procesos guardados
pm2 resurrect
# Configurar inicio automatico
pm2 startup
# Actualizar PM2
pm2 update
```
### Base de Datos
```bash
# Variables
export DATABASE_URL="postgresql://gamilit_user:PASSWORD@localhost:5432/gamilit_platform"
# Crear estructura DDL + Seeds
./create-database.sh "$DATABASE_URL"
# Drop y recrear (RESET TOTAL)
./drop-and-recreate-database.sh "$DATABASE_URL"
# Conectar a PostgreSQL
psql "$DATABASE_URL"
# Backup
pg_dump -U gamilit_user -d gamilit_platform -F c -f backup_$(date +%Y%m%d).dump
# Restore
pg_restore -U gamilit_user -d gamilit_platform -c backup_20251218.dump
```
### Build
```bash
# Backend
cd apps/backend && npm run build
# Frontend (produccion)
cd apps/frontend && npm run build:prod
# Frontend (desarrollo)
cd apps/frontend && npm run build
```
---
## 9. Troubleshooting
### Problema: Backend no inicia
```bash
# Ver logs de error
pm2 logs gamilit-backend --err --lines 50
# Verificar que el build existe
ls -la apps/backend/dist/main.js
# Verificar conexion a base de datos
psql "$DATABASE_URL" -c "SELECT 1"
# Verificar puerto no ocupado
sudo lsof -i :3006
```
### Problema: Frontend no inicia
```bash
# Ver logs de error
pm2 logs gamilit-frontend --err --lines 50
# Verificar que el build existe
ls -la apps/frontend/dist/
# Verificar puerto no ocupado
sudo lsof -i :3005
```
### Problema: Error de conexion a BD
```bash
# Verificar PostgreSQL corriendo
sudo systemctl status postgresql
# Reiniciar PostgreSQL
sudo systemctl restart postgresql
# Verificar usuario y permisos
psql -U postgres -c "\\du"
psql -U postgres -c "\\l"
```
### Problema: Puerto ocupado
```bash
# Encontrar proceso usando el puerto
sudo lsof -i :3006
sudo lsof -i :3005
# Matar proceso
sudo kill -9 <PID>
# O usar fuser
sudo fuser -k 3006/tcp
```
### Problema: Memoria alta
```bash
# Ver uso de memoria PM2
pm2 monit
# Reiniciar con limite de memoria
pm2 restart gamilit-backend --max-memory-restart 500M
```
### Problema: CORS
```bash
# Verificar CORS_ORIGIN en backend
grep CORS_ORIGIN apps/backend/.env.production
# Debe incluir el origen del frontend
# CORS_ORIGIN=http://74.208.126.102:3005,http://74.208.126.102
```
---
## Checklist de Despliegue
### Pre-Despliegue
- [ ] Verificar version de Node.js >= 18
- [ ] Verificar version de npm >= 9
- [ ] Verificar PostgreSQL corriendo
- [ ] Verificar PM2 instalado
- [ ] Actualizar codigo: `git pull origin main`
### Base de Datos
- [ ] Configurar DATABASE_URL
- [ ] Ejecutar `create-database.sh` (o `drop-and-recreate`)
- [ ] Verificar que los seeds cargaron correctamente
### Configuracion
- [ ] Configurar `apps/backend/.env.production`
- [ ] Configurar `apps/frontend/.env.production`
- [ ] Verificar JWT_SECRET es seguro
- [ ] Verificar CORS_ORIGIN correcto
### Build
- [ ] Build backend: `npm run build`
- [ ] Build frontend: `npm run build:prod`
- [ ] Verificar archivos en `dist/`
### Despliegue
- [ ] Ejecutar `pm2 start ecosystem.config.js --env production`
- [ ] Verificar `pm2 status` - ambos online
- [ ] Ejecutar `pm2 save`
- [ ] Configurar `pm2 startup` (primera vez)
### Verificacion
- [ ] Verificar health: `curl http://74.208.126.102:3006/api/health`
- [ ] Acceder a frontend: http://74.208.126.102:3005
- [ ] Probar login con usuario de prueba
- [ ] Verificar logs sin errores: `pm2 logs`
---
## Contacto y Soporte
Para problemas de despliegue:
1. Revisar logs: `pm2 logs`
2. Consultar esta documentacion
3. Verificar `docs/DEPLOYMENT.md` para mas detalles
4. Revisar `docs/95-guias-desarrollo/DEPLOYMENT-GUIDE.md` para HTTPS
---
> **Nota:** Esta documentacion fue generada automaticamente analizando los archivos de configuracion existentes en el proyecto. Mantener actualizada cuando haya cambios en la arquitectura.