Files
Horux360/docs/architecture/deployment.md
Consultoria AS 351b14a78c security: comprehensive security audit and remediation (20 fixes)
CRITICAL fixes:
- Restrict X-View-Tenant impersonation to global admin only (was any admin)
- Add authorization to subscription endpoints (was open to any user)
- Make webhook signature verification mandatory (was skippable)
- Remove databaseName from JWT payload (resolve server-side with cache)
- Reduce body size limit from 1GB to 10MB (50MB for bulk CFDI)
- Restrict .env file permissions to 600

HIGH fixes:
- Add authorization to SAT cron endpoints (global admin only)
- Add Content-Security-Policy and Permissions-Policy headers
- Centralize isGlobalAdmin() utility with caching
- Add rate limiting on auth endpoints (express-rate-limit)
- Require authentication on logout endpoint

MEDIUM fixes:
- Replace Math.random() with crypto.randomBytes for temp passwords
- Remove console.log of temporary passwords in production
- Remove DB credentials from admin notification email
- Add escapeHtml() to email templates (prevent HTML injection)
- Add file size validation on FIEL upload (50KB max)
- Require TLS for SMTP connections
- Normalize email to lowercase before uniqueness check
- Remove hardcoded default for FIEL_ENCRYPTION_KEY

Also includes:
- Complete production deployment documentation
- API reference documentation
- Security audit report with remediation details
- Updated README with v0.5.0 changelog
- New client admin email template
- Utility scripts (create-carlos, test-emails)
- PM2 ecosystem config updates

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:32:04 +00:00

6.0 KiB

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)

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

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

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_<rfc>           ← Base de cada cliente

Backups

# 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)

NODE_ENV=production
PORT=4000
DATABASE_URL="postgresql://postgres:<password>@localhost:5432/horux360?schema=public"
JWT_SECRET=<min 32 chars>
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
CORS_ORIGIN=https://horuxfin.com
FRONTEND_URL=https://horuxfin.com
FIEL_ENCRYPTION_KEY=<min 32 chars, REQUERIDO>
FIEL_STORAGE_PATH=/var/horux/fiel

# MercadoPago
MP_ACCESS_TOKEN=<token>
MP_WEBHOOK_SECRET=<secret, REQUERIDO para producción>

# SMTP (Google Workspace)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=ivan@horuxfin.com
SMTP_PASS=<app-password>
SMTP_FROM=Horux360 <ivan@horuxfin.com>

# Admin
ADMIN_EMAIL=carlos@horuxfin.com

Web (apps/web/.env.local)

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

# 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

pm2 logs horux-api --lines 50      # Ver logs de error
pm2 restart horux-api               # Reiniciar

Puerto en uso

lsof -i :4000                      # Ver quién usa el puerto
kill <PID>                          # Matar proceso
pm2 restart horux-api

Certificado SSL expirado

certbot renew
systemctl reload nginx

Base de datos lenta

sudo -u postgres psql -c "SELECT * FROM pg_stat_activity WHERE state = 'active';"