feat: Implementación completa Fase 4 - Sistema de monitoreo con API REST y WebSocket

 Nuevas funcionalidades:
- API REST unificada en puerto 8080 (eliminado CORS)
- WebSocket para logs en tiempo real desde journalctl
- Integración completa con systemd para gestión de servicios
- Escaneo automático de procesos Node.js y Python
- Rate limiting (1 operación/segundo por app)
- Interface web moderna con Tailwind CSS (tema oscuro)
- Documentación API estilo Swagger completamente en español

🎨 Interface Web (todas las páginas en español):
- Dashboard con estadísticas en tiempo real
- Visor de escaneo de procesos con filtros
- Formulario de registro de aplicaciones con variables de entorno
- Visor de logs en tiempo real con WebSocket y sidebar
- Página de selección de apps detectadas
- Documentación completa de API REST

🏗️ Arquitectura:
- Módulo models: ServiceConfig, ManagedApp, AppStatus
- Módulo systemd: wrapper de systemctl, generador de .service, parser
- Módulo orchestrator: AppManager, LifecycleManager con validaciones
- Módulo api: handlers REST, WebSocket manager, DTOs
- Servidor unificado en puerto 8080 (Web + API + WS)

🔧 Mejoras técnicas:
- Eliminación de CORS mediante servidor unificado
- Separación clara frontend/backend con carga dinámica
- Thread-safe con Arc<DashMap> para estado compartido
- Reconciliación de estados: sysinfo vs systemd
- Validaciones de paths, usuarios y configuraciones
- Manejo robusto de errores con thiserror

📝 Documentación:
- README.md actualizado con arquitectura completa
- EJEMPLOS.md con casos de uso detallados
- ESTADO_PROYECTO.md con progreso de Fase 4
- API docs interactiva en /api-docs
- Script de despliegue mejorado con health checks

🚀 Producción:
- Deployment script con validaciones
- Health checks y rollback capability
- Configuración de sudoers para systemctl
- Hardening de seguridad en servicios systemd
This commit is contained in:
2026-01-13 08:24:13 -05:00
parent 3595e55a1e
commit b0489739cf
33 changed files with 6893 additions and 1261 deletions

View File

@@ -1,65 +1,347 @@
#!/bin/bash
# --- CONFIGURACIÓN GLOBAL ---
BINARY_NAME="siax_monitor" # ← Cambié esto para que coincida con Cargo.toml
TARGET="x86_64-unknown-linux-gnu" # ← Cambié a gnu en lugar de musl
echo "📦 Compilando binario para Linux ($TARGET)..."
cargo build --release --target $TARGET
#######################################
# SIAX Agent - Script de Despliegue
# Instalación automática production-ready
#######################################
if [ $? -ne 0 ]; then
echo "❌ Error en la compilación."
exit 1
fi
set -e # Salir si hay errores
# --- FUNCIÓN MAESTRA DE DESPLIEGUE ---
# Parámetros: IP, USUARIO, RUTA_DESTINO
deploy_to_server() {
local IP=$1
local USER=$2
local DEST_PATH=$3
# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo "------------------------------------------------"
echo "📡 Desplegando en: $USER@$IP:$DEST_PATH"
# Variables
INSTALL_DIR="/opt/siax-agent"
SERVICE_USER="siax-agent"
BACKUP_DIR="/tmp/siax-agent-backup-$(date +%s)"
# 1. Crear directorio y asegurar permisos
ssh $USER@$IP "mkdir -p $DEST_PATH"
#######################################
# Funciones
#######################################
# 2. Subir binario
scp target/$TARGET/release/$BINARY_NAME $USER@$IP:$DEST_PATH/
print_header() {
echo -e "${BLUE}"
echo "============================================"
echo " SIAX Agent - Deployment Script"
echo "============================================"
echo -e "${NC}"
}
# 3. Hacer ejecutable
ssh $USER@$IP "chmod +x $DEST_PATH/$BINARY_NAME"
print_success() {
echo -e "${GREEN}$1${NC}"
}
# 4. Configurar Systemd
echo "⚙️ Configurando servicio Systemd para $USER..."
ssh $USER@$IP "sudo bash -c 'cat <<EOF > /etc/systemd/system/siax_monitor.service
print_error() {
echo -e "${RED}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_info() {
echo -e "${BLUE} $1${NC}"
}
check_root() {
if [ "$EUID" -ne 0 ]; then
print_error "Este script debe ejecutarse como root"
echo "Usa: sudo ./desplegar_agent.sh"
exit 1
fi
}
check_dependencies() {
print_info "Verificando dependencias..."
local deps=("systemctl" "cargo" "rustc")
local missing=()
for dep in "${deps[@]}"; do
if ! command -v $dep &> /dev/null; then
missing+=($dep)
fi
done
if [ ${#missing[@]} -ne 0 ]; then
print_error "Faltan dependencias: ${missing[*]}"
echo ""
echo "Instalación de Rust:"
echo " curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
echo ""
echo "Instalación de systemd (debería estar instalado por defecto):"
echo " sudo apt-get install systemd # Debian/Ubuntu"
echo " sudo yum install systemd # RedHat/CentOS"
exit 1
fi
print_success "Todas las dependencias están instaladas"
}
backup_existing() {
if [ -d "$INSTALL_DIR" ]; then
print_warning "Instalación existente detectada"
print_info "Creando backup en: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
cp -r "$INSTALL_DIR" "$BACKUP_DIR/"
print_success "Backup creado"
fi
}
compile_release() {
print_info "Compilando SIAX Agent en modo release..."
if cargo build --release; then
print_success "Compilación exitosa"
else
print_error "Error en la compilación"
rollback
exit 1
fi
}
create_user() {
if id "$SERVICE_USER" &>/dev/null; then
print_info "Usuario $SERVICE_USER ya existe"
else
print_info "Creando usuario del sistema: $SERVICE_USER"
useradd --system --no-create-home --shell /bin/false "$SERVICE_USER"
print_success "Usuario creado"
fi
}
install_binary() {
print_info "Instalando binario en $INSTALL_DIR..."
mkdir -p "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/config"
mkdir -p "$INSTALL_DIR/logs"
cp target/release/siax_monitor "$INSTALL_DIR/siax-agent"
chmod +x "$INSTALL_DIR/siax-agent"
# Copiar archivos de configuración si existen
if [ -f "config/monitored_apps.json" ]; then
cp config/monitored_apps.json "$INSTALL_DIR/config/"
fi
# Copiar archivos web
if [ -d "web" ]; then
cp -r web "$INSTALL_DIR/"
fi
# Permisos
chown -R $SERVICE_USER:$SERVICE_USER "$INSTALL_DIR"
print_success "Binario instalado"
}
configure_sudoers() {
print_info "Configurando permisos sudo para systemctl..."
local sudoers_file="/etc/sudoers.d/siax-agent"
cat > "$sudoers_file" << EOF
# SIAX Agent - Permisos para gestionar servicios systemd
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl start *
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl stop *
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl restart *
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl status *
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl enable *
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl disable *
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl daemon-reload
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl is-active *
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/systemctl list-unit-files *
$SERVICE_USER ALL=(ALL) NOPASSWD: /bin/journalctl *
EOF
chmod 0440 "$sudoers_file"
# Validar sintaxis
if visudo -c -f "$sudoers_file" &>/dev/null; then
print_success "Configuración de sudoers creada"
else
print_error "Error en configuración de sudoers"
rm -f "$sudoers_file"
exit 1
fi
}
create_systemd_service() {
print_info "Creando servicio systemd para SIAX Agent..."
cat > /etc/systemd/system/siax-agent.service << EOF
[Unit]
Description=SIAX Monitor Agent - $IP
Description=SIAX Agent - Process Monitor and Manager
After=network.target
[Service]
Type=simple
User=$USER
WorkingDirectory=$DEST_PATH
ExecStart=$DEST_PATH/$BINARY_NAME
User=$SERVICE_USER
WorkingDirectory=$INSTALL_DIR
ExecStart=$INSTALL_DIR/siax-agent
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=$INSTALL_DIR/config $INSTALL_DIR/logs /etc/systemd/system
ProtectHome=true
[Install]
WantedBy=multi-user.target
EOF'"
EOF
# 5. Reiniciar servicio
ssh $USER@$IP "sudo systemctl daemon-reload && sudo systemctl enable siax_monitor && sudo systemctl restart siax_monitor"
systemctl daemon-reload
systemctl enable siax-agent.service
echo "✅ Servidor $IP configurado correctamente."
print_success "Servicio systemd creado y habilitado"
}
# --- LISTA PERSONALIZADA DE SERVIDORES ---
#deploy_to_server "192.168.1.140" "root" "/root/app"
deploy_to_server "192.168.10.145" "root" "/root/app"
deploy_to_server "192.168.10.150" "pablinux" "/home/pablinux/app"
deploy_to_server "192.168.10.160" "user_apps" "/home/user_apps/apps"
verify_installation() {
print_info "Verificando instalación..."
echo "------------------------------------------------"
echo "🎉 ¡Despliegue masivo completado!"
local errors=0
# Verificar binario
if [ ! -f "$INSTALL_DIR/siax-agent" ]; then
print_error "Binario no encontrado"
((errors++))
fi
# Verificar permisos
if [ ! -r "$INSTALL_DIR/siax-agent" ]; then
print_error "Permisos incorrectos en binario"
((errors++))
fi
# Verificar servicio
if ! systemctl is-enabled siax-agent.service &>/dev/null; then
print_error "Servicio no habilitado"
((errors++))
fi
# Verificar sudoers
if [ ! -f "/etc/sudoers.d/siax-agent" ]; then
print_warning "Configuración de sudoers no encontrada"
echo " El agente podría tener problemas para gestionar servicios"
fi
if [ $errors -eq 0 ]; then
print_success "Verificación exitosa"
return 0
else
print_error "Verificación falló con $errors errores"
return 1
fi
}
start_service() {
print_info "Iniciando SIAX Agent..."
if systemctl start siax-agent.service; then
sleep 2
if systemctl is-active siax-agent.service &>/dev/null; then
print_success "SIAX Agent iniciado correctamente"
return 0
else
print_error "SIAX Agent no pudo iniciarse"
echo ""
echo "Ver logs con: journalctl -u siax-agent.service -n 50"
return 1
fi
else
print_error "Error al iniciar el servicio"
return 1
fi
}
rollback() {
print_warning "Ejecutando rollback..."
systemctl stop siax-agent.service 2>/dev/null || true
systemctl disable siax-agent.service 2>/dev/null || true
if [ -d "$BACKUP_DIR" ]; then
rm -rf "$INSTALL_DIR"
cp -r "$BACKUP_DIR/siax-agent" "$INSTALL_DIR"
systemctl start siax-agent.service 2>/dev/null || true
print_success "Rollback completado"
else
print_warning "No hay backup disponible para rollback"
fi
}
print_summary() {
echo ""
echo -e "${GREEN}============================================${NC}"
echo -e "${GREEN} ✅ SIAX Agent instalado exitosamente${NC}"
echo -e "${GREEN}============================================${NC}"
echo ""
echo "📊 Interface Web: http://localhost:8080"
echo "🔌 API REST: http://localhost:8081/api"
echo "📡 WebSocket: ws://localhost:8081/ws/logs/:app_name"
echo ""
echo "Comandos útiles:"
echo " Estado: sudo systemctl status siax-agent"
echo " Logs: sudo journalctl -u siax-agent -f"
echo " Reiniciar: sudo systemctl restart siax-agent"
echo " Detener: sudo systemctl stop siax-agent"
echo ""
echo "Directorio de instalación: $INSTALL_DIR"
echo "Configuración: $INSTALL_DIR/config/monitored_apps.json"
echo ""
}
#######################################
# Main
#######################################
main() {
print_header
check_root
check_dependencies
backup_existing
compile_release
create_user
install_binary
configure_sudoers
create_systemd_service
if verify_installation; then
if start_service; then
print_summary
exit 0
else
print_error "El servicio no pudo iniciarse correctamente"
print_info "Revisa los logs: journalctl -u siax-agent -n 50"
echo ""
echo "¿Deseas hacer rollback? (y/n)"
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
rollback
fi
exit 1
fi
else
print_error "La verificación falló"
echo ""
echo "¿Deseas hacer rollback? (y/n)"
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
rollback
fi
exit 1
fi
}
main