up
This commit is contained in:
@@ -0,0 +1,270 @@
|
|||||||
|
# 🚀 Configuración SSE para HestiaCP
|
||||||
|
|
||||||
|
## ✅ Pasos para Activar SSE en tu Servidor HestiaCP
|
||||||
|
|
||||||
|
### 1. Verificar que el código esté en el servidor
|
||||||
|
```bash
|
||||||
|
# Subir por FTP/SFTP o Git
|
||||||
|
cd /home/tu-usuario/web/tu-dominio.com/public_html/
|
||||||
|
ls -la api/sse_events.php # Debe existir
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Configurar Apache para SSE (si usas Apache)
|
||||||
|
|
||||||
|
**Opción A: Editar .htaccess en la raíz**
|
||||||
|
```apache
|
||||||
|
# Agregar al final de .htaccess
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
# SSE Headers
|
||||||
|
<FilesMatch "sse_events\.php$">
|
||||||
|
Header set Cache-Control "no-cache, no-store, must-revalidate"
|
||||||
|
Header set X-Accel-Buffering "no"
|
||||||
|
SetEnv no-gzip 1
|
||||||
|
</FilesMatch>
|
||||||
|
</IfModule>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Opción B: Crear .htaccess específico en /api/**
|
||||||
|
```bash
|
||||||
|
cd /home/tu-usuario/web/tu-dominio.com/public_html/api/
|
||||||
|
nano .htaccess
|
||||||
|
```
|
||||||
|
|
||||||
|
Contenido:
|
||||||
|
```apache
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
Header set Cache-Control "no-cache, no-store, must-revalidate"
|
||||||
|
Header set X-Accel-Buffering "no"
|
||||||
|
SetEnv no-gzip 1
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Prevenir timeout en SSE
|
||||||
|
<IfModule mod_fcgid.c>
|
||||||
|
FcgidIOTimeout 300
|
||||||
|
</IfModule>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Ajustar PHP-FPM (Recomendado)
|
||||||
|
|
||||||
|
Editar configuración PHP-FPM en HestiaCP:
|
||||||
|
|
||||||
|
1. **Panel HestiaCP** → **Web** → **tu dominio** → **Edit**
|
||||||
|
2. **Backend Template**: PHP-FPM
|
||||||
|
3. **PHP Version**: 8.x
|
||||||
|
|
||||||
|
Luego editar el archivo de configuración (vía SSH):
|
||||||
|
```bash
|
||||||
|
# Ubicación típica en HestiaCP
|
||||||
|
sudo nano /etc/php/8.2/fpm/pool.d/tu-usuario.conf
|
||||||
|
|
||||||
|
# Agregar o modificar:
|
||||||
|
request_terminate_timeout = 300s
|
||||||
|
pm.max_requests = 500
|
||||||
|
```
|
||||||
|
|
||||||
|
Reiniciar PHP-FPM:
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart php8.2-fpm
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Verificar Nginx (si usas Nginx)
|
||||||
|
|
||||||
|
Si tu dominio usa Nginx como proxy, editar la configuración:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nano /etc/nginx/conf.d/domains/tu-dominio.com.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Agregar dentro del bloque `location ~ \.php$`:
|
||||||
|
```nginx
|
||||||
|
# Configuración especial para SSE
|
||||||
|
location ~ ^/api/sse_events\.php$ {
|
||||||
|
fastcgi_buffering off;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
fastcgi_read_timeout 300s;
|
||||||
|
fastcgi_send_timeout 300s;
|
||||||
|
|
||||||
|
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Reiniciar Nginx:
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Probar SSE desde el servidor
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Conectar por SSH a tu servidor
|
||||||
|
ssh usuario@tu-dominio.com
|
||||||
|
|
||||||
|
# Probar SSE
|
||||||
|
curl -N -m 5 'https://tu-dominio.com/api/sse_events.php?token=demo_token'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Respuesta esperada:**
|
||||||
|
```
|
||||||
|
event: connected
|
||||||
|
data: {"timestamp":1706300000,"user_id":"token_12345678","mode":"authenticated","status":"ready"}
|
||||||
|
|
||||||
|
: heartbeat
|
||||||
|
```
|
||||||
|
|
||||||
|
Si ves esto, **SSE está funcionando** ✅
|
||||||
|
|
||||||
|
### 6. Probar desde el navegador
|
||||||
|
|
||||||
|
1. Abrir tu sitio: `https://tu-dominio.com/conversations.php`
|
||||||
|
2. Abrir Consola del navegador (F12 → Console)
|
||||||
|
3. Buscar:
|
||||||
|
```
|
||||||
|
Conectando a SSE para eventos en tiempo real...
|
||||||
|
SSE URL: https://tu-dominio.com/api/sse_events.php?token=...
|
||||||
|
✅ SSE conectado (🔐 autenticado): {...}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Solución de Problemas
|
||||||
|
|
||||||
|
#### Error: "Failed to fetch" o timeout
|
||||||
|
|
||||||
|
**Causa**: Firewall o mod_security bloqueando
|
||||||
|
**Solución**:
|
||||||
|
```bash
|
||||||
|
# Desactivar mod_security para SSE (temporal)
|
||||||
|
sudo a2dismod security2
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
|
||||||
|
# O agregar excepción en .htaccess:
|
||||||
|
<IfModule mod_security2.c>
|
||||||
|
SecRuleEngine Off
|
||||||
|
</IfModule>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Error: "EventSource's response has a MIME type"
|
||||||
|
|
||||||
|
**Causa**: Headers incorrectos
|
||||||
|
**Solución**: Verificar que sse_events.php tenga:
|
||||||
|
```php
|
||||||
|
header('Content-Type: text/event-stream');
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Error: Conexión se cierra cada 30 segundos
|
||||||
|
|
||||||
|
**Causa**: Timeout de proxy
|
||||||
|
**Solución**: Aumentar timeouts en nginx.conf o apache2.conf:
|
||||||
|
```
|
||||||
|
# Apache
|
||||||
|
Timeout 300
|
||||||
|
KeepAliveTimeout 300
|
||||||
|
|
||||||
|
# Nginx
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. Configuración de Seguridad (Producción)
|
||||||
|
|
||||||
|
#### A. Token seguro en vez de demo_token
|
||||||
|
|
||||||
|
Editar `api/sse_events.php`:
|
||||||
|
```php
|
||||||
|
// Generar token en login
|
||||||
|
$_SESSION['sse_token'] = bin2hex(random_bytes(32));
|
||||||
|
|
||||||
|
// Validar token en SSE
|
||||||
|
$token = $_GET['token'] ?? null;
|
||||||
|
if ($token && isset($_SESSION['sse_token']) && $token === $_SESSION['sse_token']) {
|
||||||
|
$authenticated = true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
En `conversations.php`:
|
||||||
|
```javascript
|
||||||
|
// Usar token de sesión
|
||||||
|
const token = '<?php echo $_SESSION['sse_token'] ?? 'demo_token'; ?>';
|
||||||
|
const sseUrl = `${baseUrl}/api/sse_events.php?token=${token}&t=${Date.now()}`;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### B. Restringir acceso por IP (opcional)
|
||||||
|
|
||||||
|
En `.htaccess`:
|
||||||
|
```apache
|
||||||
|
<FilesMatch "sse_events\.php$">
|
||||||
|
# Solo permitir desde localhost o IPs específicas
|
||||||
|
Require ip 127.0.0.1
|
||||||
|
Require ip tu.ip.publica
|
||||||
|
</FilesMatch>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9. Monitoreo
|
||||||
|
|
||||||
|
Ver conexiones SSE activas:
|
||||||
|
```bash
|
||||||
|
# Ver procesos PHP activos
|
||||||
|
ps aux | grep sse_events
|
||||||
|
|
||||||
|
# Ver logs de errores
|
||||||
|
tail -f /var/log/php8.2-fpm.log
|
||||||
|
tail -f /var/log/apache2/error.log
|
||||||
|
tail -f /var/log/nginx/error.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10. Performance
|
||||||
|
|
||||||
|
Para muchos usuarios simultáneos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Aumentar límites PHP-FPM
|
||||||
|
sudo nano /etc/php/8.2/fpm/pool.d/tu-usuario.conf
|
||||||
|
|
||||||
|
pm = dynamic
|
||||||
|
pm.max_children = 50
|
||||||
|
pm.start_servers = 10
|
||||||
|
pm.min_spare_servers = 5
|
||||||
|
pm.max_spare_servers = 20
|
||||||
|
pm.max_requests = 500
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Checklist de Verificación
|
||||||
|
|
||||||
|
- [ ] Archivo `api/sse_events.php` subido al servidor
|
||||||
|
- [ ] `.htaccess` configurado con headers SSE
|
||||||
|
- [ ] PHP-FPM timeout aumentado a 300s
|
||||||
|
- [ ] Nginx/Apache configurado (si aplica)
|
||||||
|
- [ ] Test con curl funciona (muestra "event: connected")
|
||||||
|
- [ ] Test desde navegador funciona (console.log muestra "✅ SSE conectado")
|
||||||
|
- [ ] Token de seguridad configurado (no usar demo_token en producción)
|
||||||
|
- [ ] Firewall/mod_security permite conexiones largas
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 Soporte HestiaCP
|
||||||
|
|
||||||
|
Si tienes problemas:
|
||||||
|
|
||||||
|
1. **Panel HestiaCP**: https://tu-dominio.com:8083
|
||||||
|
2. **Logs**: Panel → Log Files
|
||||||
|
3. **SSH**: Usuario y contraseña en el panel
|
||||||
|
4. **Documentación**: https://docs.hestiacp.com/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Resultado Esperado
|
||||||
|
|
||||||
|
Una vez configurado correctamente:
|
||||||
|
|
||||||
|
```
|
||||||
|
ANTES (desarrollo local):
|
||||||
|
http://localhost:8000/api/sse_events.php
|
||||||
|
❌ Timeout (servidor PHP built-in no soporta SSE)
|
||||||
|
|
||||||
|
AHORA (producción HestiaCP):
|
||||||
|
https://tu-dominio.com/api/sse_events.php
|
||||||
|
✅ Conectado - eventos en tiempo real < 1 segundo
|
||||||
|
```
|
||||||
|
|
||||||
|
**¡Tu sistema de notificaciones en tiempo real estará funcionando!** 🚀
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Configuración SSE para HestiaCP
|
||||||
|
# Colocar este archivo en: /api/.htaccess
|
||||||
|
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
# Deshabilitar buffering para SSE
|
||||||
|
Header set Cache-Control "no-cache, no-store, must-revalidate"
|
||||||
|
Header set X-Accel-Buffering "no"
|
||||||
|
Header set Connection "keep-alive"
|
||||||
|
|
||||||
|
# Permitir CORS si es necesario
|
||||||
|
# Header set Access-Control-Allow-Origin "*"
|
||||||
|
# Header set Access-Control-Allow-Credentials "true"
|
||||||
|
|
||||||
|
# Deshabilitar compresión
|
||||||
|
SetEnv no-gzip 1
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Aumentar timeouts para SSE
|
||||||
|
<IfModule mod_fcgid.c>
|
||||||
|
FcgidIOTimeout 300
|
||||||
|
FcgidConnectTimeout 300
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Desactivar mod_security para SSE (si causa problemas)
|
||||||
|
<IfModule mod_security2.c>
|
||||||
|
SecRuleEngine Off
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Prevenir que Apache cierre la conexión
|
||||||
|
RewriteEngine Off
|
||||||
|
Options -MultiViews
|
||||||
|
|
||||||
|
# PHP settings
|
||||||
|
php_value max_execution_time 300
|
||||||
|
php_value max_input_time 300
|
||||||
Executable
+153
@@ -0,0 +1,153 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Script de verificación SSE para HestiaCP
|
||||||
|
# Ejecutar en el servidor: bash check_sse.sh
|
||||||
|
|
||||||
|
echo "🔍 Verificación de SSE para HestiaCP"
|
||||||
|
echo "===================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. Verificar que el archivo existe
|
||||||
|
echo "1️⃣ Verificando archivos..."
|
||||||
|
if [ -f "api/sse_events.php" ]; then
|
||||||
|
echo " ✅ api/sse_events.php existe"
|
||||||
|
else
|
||||||
|
echo " ❌ api/sse_events.php NO encontrado"
|
||||||
|
echo " → Asegúrate de subir el archivo al servidor"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Verificar permisos
|
||||||
|
echo ""
|
||||||
|
echo "2️⃣ Verificando permisos..."
|
||||||
|
PERMS=$(stat -c "%a" api/sse_events.php 2>/dev/null || stat -f "%A" api/sse_events.php 2>/dev/null)
|
||||||
|
if [ "$PERMS" -ge "644" ]; then
|
||||||
|
echo " ✅ Permisos correctos ($PERMS)"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Permisos: $PERMS (se recomienda 644)"
|
||||||
|
echo " Ejecutar: chmod 644 api/sse_events.php"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Verificar versión PHP
|
||||||
|
echo ""
|
||||||
|
echo "3️⃣ Verificando PHP..."
|
||||||
|
PHP_VERSION=$(php -v | head -n 1)
|
||||||
|
echo " $PHP_VERSION"
|
||||||
|
if php -v | grep -q "PHP 8"; then
|
||||||
|
echo " ✅ PHP 8.x detectado"
|
||||||
|
elif php -v | grep -q "PHP 7"; then
|
||||||
|
echo " ⚠️ PHP 7.x (recomendado PHP 8.x)"
|
||||||
|
else
|
||||||
|
echo " ❌ Versión PHP desconocida"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Verificar sintaxis PHP
|
||||||
|
echo ""
|
||||||
|
echo "4️⃣ Verificando sintaxis PHP..."
|
||||||
|
if php -l api/sse_events.php > /dev/null 2>&1; then
|
||||||
|
echo " ✅ Sin errores de sintaxis"
|
||||||
|
else
|
||||||
|
echo " ❌ Error de sintaxis en sse_events.php"
|
||||||
|
php -l api/sse_events.php
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 5. Verificar configuración PHP-FPM
|
||||||
|
echo ""
|
||||||
|
echo "5️⃣ Verificando PHP-FPM..."
|
||||||
|
if systemctl is-active --quiet php8.2-fpm || systemctl is-active --quiet php8.1-fpm || systemctl is-active --quiet php-fpm; then
|
||||||
|
echo " ✅ PHP-FPM está corriendo"
|
||||||
|
else
|
||||||
|
echo " ⚠️ PHP-FPM no detectado o no corriendo"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 6. Probar conexión SSE local
|
||||||
|
echo ""
|
||||||
|
echo "6️⃣ Probando conexión SSE..."
|
||||||
|
echo " Conectando (3 segundos)..."
|
||||||
|
|
||||||
|
RESPONSE=$(timeout 3 curl -N -s 'http://localhost/api/sse_events.php?token=demo_token' 2>&1 || echo "timeout")
|
||||||
|
|
||||||
|
if echo "$RESPONSE" | grep -q "event: connected"; then
|
||||||
|
echo " ✅ SSE funciona correctamente"
|
||||||
|
echo " Respuesta:"
|
||||||
|
echo "$RESPONSE" | head -5 | sed 's/^/ /'
|
||||||
|
elif echo "$RESPONSE" | grep -q "timeout"; then
|
||||||
|
echo " ⚠️ Timeout - SSE puede no estar configurado correctamente"
|
||||||
|
echo " → Revisar configuración Apache/Nginx"
|
||||||
|
elif echo "$RESPONSE" | grep -q "401"; then
|
||||||
|
echo " ⚠️ HTTP 401 - Problema de autenticación"
|
||||||
|
echo " → Revisar config/auth.php"
|
||||||
|
else
|
||||||
|
echo " ❌ Error inesperado"
|
||||||
|
echo " Respuesta:"
|
||||||
|
echo "$RESPONSE" | head -10 | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7. Verificar .htaccess
|
||||||
|
echo ""
|
||||||
|
echo "7️⃣ Verificando .htaccess..."
|
||||||
|
if [ -f "api/.htaccess" ]; then
|
||||||
|
echo " ✅ api/.htaccess existe"
|
||||||
|
if grep -q "X-Accel-Buffering" api/.htaccess; then
|
||||||
|
echo " ✅ Configuración SSE encontrada"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Falta configuración SSE en .htaccess"
|
||||||
|
echo " → Ver GUIA_HESTIA_SSE.md"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ⚠️ api/.htaccess no encontrado"
|
||||||
|
echo " → Crear según GUIA_HESTIA_SSE.md"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 8. Verificar configuración base de datos
|
||||||
|
echo ""
|
||||||
|
echo "8️⃣ Verificando configuración..."
|
||||||
|
if [ -f "config/config.php" ]; then
|
||||||
|
echo " ✅ config/config.php existe"
|
||||||
|
if php -r "require_once 'config/config.php'; echo 'OK';" 2>/dev/null | grep -q "OK"; then
|
||||||
|
echo " ✅ config.php carga correctamente"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Error al cargar config.php"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ❌ config/config.php NO encontrado"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 9. Verificar tabla notifications
|
||||||
|
echo ""
|
||||||
|
echo "9️⃣ Verificando tabla notifications..."
|
||||||
|
if php -r "require_once 'config/config.php'; \$db = Database::getInstance(); \$r = \$db->fetchAll('SHOW TABLES LIKE \"notifications\"'); echo (count(\$r) > 0 ? 'OK' : 'NO');" 2>/dev/null | grep -q "OK"; then
|
||||||
|
echo " ✅ Tabla notifications existe"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Tabla notifications no encontrada"
|
||||||
|
echo " → Ejecutar migration para crear tabla"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Resumen final
|
||||||
|
echo ""
|
||||||
|
echo "===================================="
|
||||||
|
echo "📊 Resumen"
|
||||||
|
echo "===================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if echo "$RESPONSE" | grep -q "event: connected"; then
|
||||||
|
echo "✅ SSE está funcionando correctamente"
|
||||||
|
echo ""
|
||||||
|
echo "Próximos pasos:"
|
||||||
|
echo "1. Abrir https://tu-dominio.com/conversations.php"
|
||||||
|
echo "2. Abrir consola del navegador (F12)"
|
||||||
|
echo "3. Verificar: '✅ SSE conectado'"
|
||||||
|
echo ""
|
||||||
|
echo "🚀 Sistema de notificaciones en tiempo real activo!"
|
||||||
|
else
|
||||||
|
echo "⚠️ SSE necesita configuración adicional"
|
||||||
|
echo ""
|
||||||
|
echo "Próximos pasos:"
|
||||||
|
echo "1. Revisar GUIA_HESTIA_SSE.md"
|
||||||
|
echo "2. Configurar .htaccess para SSE"
|
||||||
|
echo "3. Ajustar PHP-FPM timeout (300s)"
|
||||||
|
echo "4. Ejecutar: bash check_sse.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
+5
-3
@@ -1081,9 +1081,11 @@
|
|||||||
console.log('Conectando a SSE para eventos en tiempo real...');
|
console.log('Conectando a SSE para eventos en tiempo real...');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// EventSource no soporta withCredentials directamente
|
// Detectar URL base automáticamente (funciona en dev y producción)
|
||||||
// Usar token en URL como alternativa
|
const baseUrl = window.location.origin; // http://localhost:8000 o https://tu-dominio.com
|
||||||
const sseUrl = 'api/sse_events.php?token=demo_token&t=' + Date.now();
|
const sseUrl = `${baseUrl}/api/sse_events.php?token=demo_token&t=${Date.now()}`;
|
||||||
|
|
||||||
|
console.log('SSE URL:', sseUrl);
|
||||||
this.eventSource = new EventSource(sseUrl);
|
this.eventSource = new EventSource(sseUrl);
|
||||||
|
|
||||||
// Evento: conexión establecida
|
// Evento: conexión establecida
|
||||||
|
|||||||
Reference in New Issue
Block a user