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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user