# Guía de Despliegue en Producción - Horux360 ## Infraestructura ### Servidor - **OS:** Ubuntu 24.04 LTS - **RAM:** 22GB - **CPU:** 8 cores - **Dominio:** horuxfin.com (DNS en AWS Route 53) - **SSL:** Let's Encrypt (certificado real via DNS challenge) - **IP Interna:** 192.168.10.212 ### Stack | Componente | Tecnología | Puerto | |-----------|-----------|--------| | Reverse Proxy | Nginx 1.24 | 80/443 | | API | Node.js + Express + tsx | 4000 | | Frontend | Next.js 14 | 3000 | | Base de datos | PostgreSQL 16 | 5432 | | Process Manager | PM2 | — | --- ## Arquitectura de Red ``` Internet │ ▼ Nginx (443/SSL) ├── /api/* → 127.0.0.1:4000 (horux-api) ├── /api/auth/* → 127.0.0.1:4000 (rate limit: 5r/s) ├── /api/webhooks/* → 127.0.0.1:4000 (rate limit: 10r/s) ├── /health → 127.0.0.1:4000 └── /* → 127.0.0.1:3000 (horux-web) ``` --- ## PM2 - Gestión de Procesos ### Configuración (`ecosystem.config.js`) ```javascript module.exports = { apps: [ { name: 'horux-api', interpreter: 'node', script: '/root/Horux/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/dist/cli.mjs', args: 'src/index.ts', cwd: '/root/Horux/apps/api', instances: 1, exec_mode: 'fork', autorestart: true, max_memory_restart: '1G', kill_timeout: 5000, listen_timeout: 10000, env: { NODE_ENV: 'production', PORT: 4000 }, }, { name: 'horux-web', script: 'node_modules/next/dist/bin/next', args: 'start', cwd: '/root/Horux/apps/web', instances: 1, exec_mode: 'fork', autorestart: true, max_memory_restart: '512M', kill_timeout: 5000, env: { NODE_ENV: 'production', PORT: 3000 }, }, ], }; ``` ### Notas - La API usa `tsx` en lugar de `tsc` compilado porque `@horux/shared` exporta TypeScript raw (ESM) que `dist/` no puede resolver. - Next.js usa la ruta directa `node_modules/next/dist/bin/next` porque `node_modules/.bin/next` es un shell script que PM2 no puede ejecutar como script Node.js. ### Comandos Útiles ```bash pm2 restart all # Reiniciar todo pm2 logs horux-api # Ver logs del API pm2 logs horux-web # Ver logs del frontend pm2 monit # Monitor en tiempo real pm2 save # Guardar estado actual pm2 startup # Configurar inicio automático ``` --- ## Nginx ### Archivo: `/etc/nginx/sites-available/horux360.conf` #### Rate Limiting | Zona | Límite | Burst | Uso | |------|--------|-------|-----| | `auth` | 5r/s | 10 | `/api/auth/*` | | `webhook` | 10r/s | 20 | `/api/webhooks/*` | | `api` | 30r/s | 50 | `/api/*` (general) | #### Security Headers - `Content-Security-Policy`: Restrictivo (`default-src 'self'`) - `Strict-Transport-Security`: 1 año con includeSubDomains - `X-Frame-Options`: SAMEORIGIN - `X-Content-Type-Options`: nosniff - `Permissions-Policy`: camera, microphone, geolocation deshabilitados - `Referrer-Policy`: strict-origin-when-cross-origin #### Body Limits - Global: `50M` (Nginx) - API default: `10mb` (Express) - `/api/cfdi/bulk`: `50mb` (Express route-specific) ### Renovar SSL ```bash certbot renew --dry-run # Verificar certbot renew # Renovar ``` --- ## PostgreSQL ### Configuración de Rendimiento (`postgresql.conf`) | Parámetro | Valor | Descripción | |-----------|-------|-------------| | `max_connections` | 300 | Para multi-tenant con pools por tenant | | `shared_buffers` | 4GB | ~18% de 22GB RAM | | `work_mem` | 16MB | Memoria por operación de sort/hash | | `effective_cache_size` | 16GB | ~72% de RAM | | `maintenance_work_mem` | 512MB | Para VACUUM, CREATE INDEX | | `wal_buffers` | 64MB | Write-ahead log buffers | ### Arquitectura Multi-Tenant Cada cliente tiene su propia base de datos PostgreSQL: ``` horux360 ← Base central (tenants, users, subscriptions) horux_cas2408138w2 ← Base del admin global horux_ ← Base de cada cliente ``` ### Backups ```bash # Cron job: 0 1 * * * /root/Horux/scripts/backup.sh # Ubicación: /var/horux/backups/ # Retención: 7 diarios + 4 semanales ``` --- ## Variables de Entorno ### API (`apps/api/.env`) ```env NODE_ENV=production PORT=4000 DATABASE_URL="postgresql://postgres:@localhost:5432/horux360?schema=public" JWT_SECRET= JWT_EXPIRES_IN=15m JWT_REFRESH_EXPIRES_IN=7d CORS_ORIGIN=https://horuxfin.com FRONTEND_URL=https://horuxfin.com FIEL_ENCRYPTION_KEY= FIEL_STORAGE_PATH=/var/horux/fiel # MercadoPago MP_ACCESS_TOKEN= MP_WEBHOOK_SECRET= # SMTP (Google Workspace) SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=ivan@horuxfin.com SMTP_PASS= SMTP_FROM=Horux360 # Admin ADMIN_EMAIL=carlos@horuxfin.com ``` ### Web (`apps/web/.env.local`) ```env NEXT_PUBLIC_API_URL=https://horuxfin.com/api ``` --- ## Directorios Importantes ``` /root/Horux/ ← Código fuente /var/horux/fiel/ ← Archivos FIEL encriptados (0700) /var/horux/backups/ ← Backups de PostgreSQL /etc/nginx/sites-available/ ← Config de Nginx /etc/letsencrypt/live/ ← Certificados SSL ``` --- ## Despliegue de Cambios ```bash # 1. Pull cambios cd /root/Horux git pull origin main # 2. Instalar dependencias pnpm install # 3. Build pnpm build # 4. Reiniciar servicios pm2 restart all # 5. Si hay cambios en nginx: cp deploy/nginx/horux360.conf /etc/nginx/sites-available/horux360.conf nginx -t && systemctl reload nginx ``` --- ## Troubleshooting ### API no inicia ```bash pm2 logs horux-api --lines 50 # Ver logs de error pm2 restart horux-api # Reiniciar ``` ### Puerto en uso ```bash lsof -i :4000 # Ver quién usa el puerto kill # Matar proceso pm2 restart horux-api ``` ### Certificado SSL expirado ```bash certbot renew systemctl reload nginx ``` ### Base de datos lenta ```bash sudo -u postgres psql -c "SELECT * FROM pg_stat_activity WHERE state = 'active';" ```