✨ 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
348 lines
9.0 KiB
Bash
Executable File
348 lines
9.0 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
#######################################
|
||
# SIAX Agent - Script de Despliegue
|
||
# Instalación automática production-ready
|
||
#######################################
|
||
|
||
set -e # Salir si hay errores
|
||
|
||
# Colores para output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Variables
|
||
INSTALL_DIR="/opt/siax-agent"
|
||
SERVICE_USER="siax-agent"
|
||
BACKUP_DIR="/tmp/siax-agent-backup-$(date +%s)"
|
||
|
||
#######################################
|
||
# Funciones
|
||
#######################################
|
||
|
||
print_header() {
|
||
echo -e "${BLUE}"
|
||
echo "============================================"
|
||
echo " SIAX Agent - Deployment Script"
|
||
echo "============================================"
|
||
echo -e "${NC}"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
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 Agent - Process Monitor and Manager
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
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
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable siax-agent.service
|
||
|
||
print_success "Servicio systemd creado y habilitado"
|
||
}
|
||
|
||
verify_installation() {
|
||
print_info "Verificando instalación..."
|
||
|
||
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
|