Refactor(DIIAA): Evolución del ADN a dtic-DIIAA, renombrando scripts/ a automatizacion/ y actualizando manifiestos y URLs de servicios web

This commit is contained in:
Ricardo Monla
2026-03-10 21:42:37 -03:00
parent 188d31f611
commit 174ef7d53c
17 changed files with 25 additions and 25 deletions
+231
View File
@@ -0,0 +1,231 @@
#!/usr/bin/env ruby
# script: alta_nodo.rb
# Uso: ruby automatizacion/alta_nodo.rb <IP> <HOSTNAME> [USUARIO]
# Descripción: Automatiza la configuración SSH y la documentación del ADN para un nuevo nodo.
require 'fileutils'
require 'date'
require 'json'
require 'time'
# --- Configuración ---
ADN_DIR = File.expand_path('../adn', __dir__)
NODOS_DIR = File.join(ADN_DIR, 'nodos')
ONTOLOGIA_FILE = File.join(ADN_DIR, '01_ontologia.md')
SSH_CONFIG_FILE = File.expand_path('~/.ssh/config')
SSH_PUB_KEY = File.expand_path('~/.ssh/id_rsa.pub')
# --- Argumentos ---
ip = ARGV[0]
user = ARGV[1] || 'rmonla'
unless ip
puts "❌ Error: Falta la IP."
puts "Uso correcto: ruby automatizacion/alta_nodo.rb <IP> [USUARIO]"
puts "Ejemplo: ruby automatizacion/alta_nodo.rb 10.0.10.205 rmonla"
exit 1
end
puts "--- 🚀 Iniciando Alta de Nodo: #{ip} con Usuario: #{user} ---"
# --- 🚨 PROTOCOLO DE SEGURIDAD (CANDADO JIT) ---
TOKEN_FILE = File.expand_path('../.agent_token', __dir__)
def verificar_autorizacion!
unless File.exist?(TOKEN_FILE)
puts "\n⛔ ACCESO DENEGADO: No se encontró token de autorización."
puts "🔒 Protocolo de seguridad activo. El Agente requiere permiso explícito."
puts "👉 Ejecuta: ruby automatizacion/candado.rb"
exit 1
end
begin
token = JSON.parse(File.read(TOKEN_FILE))
expires_at = Time.parse(token['expires_at'])
if Time.now > expires_at
puts "\n⛔ ACCESO DENEGADO: El token de autorización ha EXPIRADO."
puts "💀 Expiró a las: #{expires_at.strftime('%H:%M:%S')}"
puts "👉 Ejecuta nuevamente: ruby automatizacion/candado.rb"
exit 1
end
puts "🔓 Autorización Verificada (Válida hasta #{expires_at.strftime('%H:%M:%S')})"
rescue => e
puts "\n❌ Error al verificar token: #{e.message}"
exit 1
end
end
verificar_autorizacion!
# -----------------------------------------------
# Variable para trackear si tenemos acceso sin password/interactivo
ssh_access_ok = false
# Detectamos si necesitamos flags legacy
# Intentamos primero con flags modernos, si falla, probamos con legacy
ssh_flags = "-o ConnectTimeout=5 -o StrictHostKeyChecking=no"
ssh_legacy_flags = "#{ssh_flags} -o PubkeyAcceptedAlgorithms=+ssh-rsa -o HostKeyAlgorithms=+ssh-rsa"
# --- 0. Detección de Hostname y Verificación de Acceso ---
puts "\n🔍 0. Detectando Hostname y Verificando Acceso..."
begin
# Probamos conexión con BatchMode para ver si ya entramos sin password
check_cmd = "ssh -o BatchMode=yes #{ssh_legacy_flags} #{user}@#{ip} hostname 2>/dev/null"
hostname = `#{check_cmd}`.strip
if $?.success? && !hostname.empty?
puts "✅ Acceso SSH verificado (Sin contraseña)."
puts "✅ Hostname detectado: #{hostname}"
ssh_access_ok = true
else
puts "⚠️ Acceso directo no disponible. Intentando conexión interactiva (pedirá password)..."
# Usamos flags legacy aquí también por si acaso
hostname = `ssh #{ssh_legacy_flags} #{user}@#{ip} hostname`.strip
if $?.success? && !hostname.empty?
puts "✅ Hostname detectado: #{hostname}"
else
puts "❌ No se pudo obtener el hostname. Verifica la IP y credenciales."
exit 1
end
end
rescue => e
puts "❌ Error al intentar conectar: #{e.message}"
exit 1
end
# --- 1. Configuración SSH Local ---
puts "\n🔧 1. Configurando SSH Local..."
if File.read(SSH_CONFIG_FILE).include?("Host #{hostname}")
puts "️ Host '#{hostname}' ya existe en #{SSH_CONFIG_FILE}."
else
puts "📝 Agregando '#{hostname}' a #{SSH_CONFIG_FILE}..."
File.open(SSH_CONFIG_FILE, 'a') do |f|
f.puts "\nHost #{hostname}"
f.puts " HostName #{ip}"
f.puts " User #{user}"
f.puts " StrictHostKeyChecking no"
f.puts " PubkeyAcceptedAlgorithms +ssh-rsa"
f.puts " HostKeyAlgorithms +ssh-rsa"
end
puts "✅ Configuración SSH actualizada (con soporte legacy)."
end
# --- 2. Copia de Claves SSH ---
if ssh_access_ok
puts "\n🔑 2. Copia de Claves SSH: OMITIDO (Ya tienes acceso)."
else
puts "\n🔑 2. Instalando Clave SSH en #{user}@#{ip}..."
if File.exist?(SSH_PUB_KEY)
# ssh-copy-id pedirá password una única vez aquí
# Pasamos opciones legacy explícitamente
system("ssh-copy-id #{ssh_legacy_flags} -i #{SSH_PUB_KEY} #{user}@#{ip}")
if $?.success?
puts "✅ Clave instalada exitosamente."
ssh_access_ok = true
else
puts "⚠️ Falló ssh-copy-id. Quizás debas hacerlo manualmente o verificar password."
end
else
puts "❌ No se encontró clave pública en #{SSH_PUB_KEY}."
end
end
require 'json'
# --- 3. Relevamiento de Hardware (Extracción Cruda & Procesamiento Local) ---
puts "\n🔍 3. Extrayendo Datos Crudos del Nodo (Procesamiento Local)..."
# Script remoto minimalista: Solo "cat" de archivos clave y lsblk
# Usamos delimitadores únicos para separar bloques
# Agregamos recolección de evidencia para detección de roles
remote_script = <<~SHELL
echo "---START_HOSTNAME---"; cat /etc/hostname
echo "---START_CPUINFO---"; cat /proc/cpuinfo
echo "---START_MEMINFO---"; cat /proc/meminfo
echo "---START_OSRELEASE---"; cat /etc/os-release
echo "---START_LSBLK---"; lsblk -d -o NAME,SIZE,MODEL,TYPE -J 2>/dev/null || lsblk -d -o NAME,SIZE,MODEL,TYPE
echo "---START_PROCESSES---"; ps -ef --sort=-%mem | head -n 20
echo "---START_PORTS---"; ss -tuln 2>/dev/null || netstat -tuln 2>/dev/null
echo "---START_MARKERS---"
[ -d "/etc/xen" ] && echo "xen_config_dir_exists"
[ -d "/etc/pve" ] && echo "pve_config_dir_exists"
[ -d "/var/lib/docker" ] && echo "docker_lib_dir_exists"
[ -f "/usr/bin/dockerd" ] && echo "dockerd_bin_exists"
[ -f "/opt/xensource/bin/xe" ] && echo "citrix_xe_bin_exists"
SHELL
safe_script = remote_script.gsub('"', '\\"')
# Usamos flags legacy para la sonda también
raw_output = `ssh #{ssh_legacy_flags} #{hostname} "#{safe_script}"`
# Parsers Locales (Host-Side Logic)
def parse_block(output, key)
return "" unless output.include?("---START_#{key}---")
output.split("---START_#{key}---")[1].split("---START_")[0].strip
rescue
""
end
hostname_raw = parse_block(raw_output, 'HOSTNAME')
cpuinfo_raw = parse_block(raw_output, 'CPUINFO')
meminfo_raw = parse_block(raw_output, 'MEMINFO')
osrelease_raw = parse_block(raw_output, 'OSRELEASE')
lsblk_raw = parse_block(raw_output, 'LSBLK')
processes_raw = parse_block(raw_output, 'PROCESSES')
ports_raw = parse_block(raw_output, 'PORTS')
markers_raw = parse_block(raw_output, 'MARKERS')
# Analizador de CPU (Local)
cpu_model = cpuinfo_raw.scan(/model name\s+:\s+(.*)/).flatten.first || "Unknown"
cpu_cores = cpuinfo_raw.scan(/^processor\s+:/).count
cpu_arch = "x86_64" # Default (podría sacarse de flags en cpuinfo 'lm' = long mode)
# Analizador de RAM (Local)
mem_total_kb = meminfo_raw.scan(/MemTotal:\s+(\d+)\s+kB/).flatten.first.to_i
mem_total_human = "#{(mem_total_kb / 1024.0 / 1024.0).round(2)} GiB"
# Analizador de OS (Local)
os_distro = osrelease_raw.scan(/PRETTY_NAME="(.*)"/).flatten.first || "Unknown Linux"
os_kernel_ver = "Linux (Kernel ver. unknown)" # Kernel version requiring 'uname -r', keeping simple for now or parsing from /proc/version if needed later
params = {}
params[:timestamp] = Time.now.to_s
params[:connector] = { ip: ip, user: user, hostname_detected: hostname_raw.empty? ? hostname : hostname_raw }
params[:cpu] = { model: cpu_model, cores: cpu_cores, arch: cpu_arch }
params[:ram] = { total: mem_total_human, raw: mem_total_kb * 1024 }
params[:os] = { distro: os_distro, kernel: os_kernel_ver } # Simplified
# Procesamiento de Discos (Local)
if lsblk_raw.strip.start_with?("{")
begin
params[:disks] = JSON.parse(lsblk_raw)
rescue
params[:disks] = { format: 'raw', content: lsblk_raw }
end
else
params[:disks] = { format: 'text', content: lsblk_raw }
end
# Evidencia para Inteligencia de Agente
params[:evidence] = {
processes: processes_raw.lines.map(&:strip),
ports: ports_raw.lines.map(&:strip),
file_markers: markers_raw.lines.map(&:strip)
}
puts " ✅ Datos crudos extraídos y procesados localmente."
# --- 4. Salida para el Agente (STDOUT) ---
puts "\n💾 4. Telemetría Final (Para consumo del Agente)..."
puts "---START_PAYLOAD---"
puts JSON.pretty_generate(params)
puts "---END_PAYLOAD---"
puts "\n✅ Proceso finalizado. Copia el bloque JSON anterior si necesitas procesarlo manualmente, o deja que el Agente lo lea."
+61
View File
@@ -0,0 +1,61 @@
#!/bin/bash
# Script: alta_nodo.sh
# Uso: ./automatizacion/alta_nodo.sh <IP> <HOSTNAME> [USUARIO]
# Descripción: Automatiza la configuración SSH local y el despliegue de claves al nuevo nodo.
IP=$1
NAME=$2
USER_SSH=${3:-rmonla} # Por defecto usa 'rmonla' si no se especifica
# Validar argumentos básicos
if [ -z "$IP" ] || [ -z "$NAME" ]; then
echo "❌ Error: Faltan argumentos."
echo "Uso correcto: ./automatizacion/alta_nodo.sh <IP> <HOSTNAME> [USUARIO]"
echo "Ejemplo: ./automatizacion/alta_nodo.sh 10.0.10.205 srv-pmox4 rmonla"
exit 1
fi
echo "--- Iniciando Alta de Nodo: $NAME ($IP) con Usuario: $USER_SSH ---"
# 1. Configurar SSH local (~/.ssh/config)
if grep -q "^Host $NAME$" ~/.ssh/config; then
echo "️ Host '$NAME' ya existe en ~/.ssh/config (Se asume configuración correcta)."
else
echo "🔧 Agregando '$NAME' a ~/.ssh/config..."
cat >> ~/.ssh/config <<EOF
Host $NAME
HostName $IP
User $USER_SSH
StrictHostKeyChecking no
EOF
fi
# 2. Verificar Conectividad
echo "📡 Verificando conexión (Ping)..."
ping -c 2 $IP > /dev/null
if [ $? -ne 0 ]; then
echo "⚠️ Alerta: No hay ping a $IP. Verifica la red."
else
echo "✅ Ping exitoso."
fi
# 3. Intentar instalación automática de clave (ssh-copy-id)
echo "🔑 Intentando instalar clave SSH automáticamente en $USER_SSH@$IP..."
ssh-copy-id -o ConnectTimeout=5 -i ~/.ssh/id_rsa.pub $USER_SSH@$IP 2>/dev/null
if [ $? -eq 0 ]; then
echo "✅ Clave instalada exitosamente via ssh-copy-id."
echo "🚀 Probando conexión SSH..."
ssh -o ConnectTimeout=5 $NAME "uptime"
else
echo "⚠️ No se pudo copiar la clave automáticamente."
echo "Probablemente necesites ingresar la contraseña de '$USER_SSH' si te la pide."
echo ""
echo "📋 SI FALLA, EJECUTA ESTO MANUALMENTE EN LA TERMINAL DEL NODO ($IP) con tu usuario:"
echo "-----------------------------------------------------------"
# Generamos el comando dinámicamente con la clave actual
PUBKEY=$(cat ~/.ssh/id_rsa.pub)
echo "mkdir -p ~/.ssh && echo \"$PUBKEY\" >> ~/.ssh/authorized_keys"
echo "-----------------------------------------------------------"
fi
+81
View File
@@ -0,0 +1,81 @@
#!/bin/bash
# scripts/configurar_red_hibrida.sh
# CONFIGURACIÓN DE RED HÍBRIDA (Policy Routing)
# Objetivo:
# - Mantener Gateway Default 10.0.10.1 (Navegación Rápida).
# - Habilitar IP Pública 190.114.205.18 para acceso entrante.
# - Responder tráfico entrante de 190... por su propio Gateway (190.114.205.1).
CON_NAME="Red LAN 10"
IP_PUB="190.114.205.18/24"
GW_PUB="190.114.205.1"
TABLE_ID="190"
TIMEOUT_SEC=300 # 5 Minutos
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Ejecutar con sudo.${NC}"
exit 1
fi
echo -e "${YELLOW}Configurando Red Híbrida en conexión '$CON_NAME'...${NC}"
# 1. Agregar IP Pública (si no existe ya)
# Nota: nmcli es idempotente para esto si se usa correctamente, pero limpiaremos "ipv4.addresses" duplicadas si es manual.
# Aquí simplemente agregamos.
echo -e "[1/4] Agregando IP Pública $IP_PUB..."
nmcli con mod "$CON_NAME" +ipv4.addresses "$IP_PUB"
# 2. Agregar Ruta a Tabla Secundaria
# Sintaxis: ip/prefix next-hop priority attributes
echo -e "[2/4] Configurando ruta de retorno (Tabla $TABLE_ID)..."
nmcli con mod "$CON_NAME" +ipv4.routes "0.0.0.0/0 $GW_PUB 100 table=$TABLE_ID"
# 3. Agregar Regla de Enrutamiento
# Sintaxis: priority from <ip> table <id>
echo -e "[3/4] Configurando regla de política (Policy Rule)..."
nmcli con mod "$CON_NAME" +ipv4.routing-rules "priority 30000 from ${IP_PUB%/*} table $TABLE_ID"
# 4. Aplicar Cambios (Temporales para validación)
echo -e "Aplicando configuración... (Si pierdes conexión, espera $TIMEOUT_SEC segundos)"
nmcli con mod "$CON_NAME" +ipv4.addresses "$IP_PUB"
nmcli con mod "$CON_NAME" +ipv4.routes "0.0.0.0/0 $GW_PUB 100 table=$TABLE_ID"
nmcli con mod "$CON_NAME" +ipv4.routing-rules "priority 30000 from ${IP_PUB%/*} table $TABLE_ID"
nmcli con up "$CON_NAME"
# --- VERIFICACIÓN / ROLLBACK LOOP ---
echo -e "\n${GREEN}*** CAMBIOS APLICADOS ***${NC}"
echo "Verifica que tienes conectividad (tanto LAN como WAN)."
echo "Tienes $TIMEOUT_SEC segundos para confirmar escribiendo 's' y Enter."
CONFIRMADO=0
for ((i=TIMEOUT_SEC; i>0; i--)); do
echo -ne " Tiempo restante para ROLLBACK: $i segundos \r"
read -t 1 -n 1 key
if [[ $key = "s" ]] || [[ $key = "S" ]]; then
CONFIRMADO=1
break
fi
done
if [ $CONFIRMADO -eq 1 ]; then
echo -e "\n\n${GREEN}¡CONFIRMADO! Configuración de Red Híbrida establecida.${NC}"
exit 0
else
echo -e "\n\n${RED}¡TIEMPO AGOTADO! REVIERTIENDO CAMBIOS...${NC}"
# Revertir (Undo)
echo "Eliminando reglas..."
nmcli con mod "$CON_NAME" -ipv4.addresses "$IP_PUB"
nmcli con mod "$CON_NAME" -ipv4.routes "0.0.0.0/0 $GW_PUB 100 table=$TABLE_ID"
nmcli con mod "$CON_NAME" -ipv4.routing-rules "priority 30000 from ${IP_PUB%/*} table $TABLE_ID"
echo "Recargando conexión..."
nmcli con up "$CON_NAME"
echo -e "${GREEN}Sistema restaurado al estado original.${NC}"
fi
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
if [ -f ".env.enc" ]; then
openssl enc -d -aes-256-cbc -in .env.enc -out .env -pass pass:"\$2y\$10\$Xo7lM" 2>/dev/null
echo "Secret successfully decrypted to .env for temporary use."
else
echo "Encrypted .env.enc not found."
fi
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
# scripts/instalar_nginx_simple.sh
# Script para instalar Nginx y aplicar configuraciones (Sin manipulación de IP).
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Ejecutar con sudo.${NC}"
exit 1
fi
echo -e "${YELLOW}[1/3] Instalando Nginx...${NC}"
apt-get update && apt-get install -y nginx
echo -e "${YELLOW}[2/3] Aplicando configuraciones de servicios...${NC}"
# Remover default si molesta
# rm /etc/nginx/sites-enabled/default 2>/dev/null
# Enlazar configs
CONFIG_DIR="/home/rmonla/Documentos/GitHub/dtic-DIIAA/servicios/nginx/conf.d"
ln -sf $CONFIG_DIR/*.conf /etc/nginx/conf.d/
echo -e "${YELLOW}[3/3] Iniciando servicio...${NC}"
systemctl enable nginx
systemctl restart nginx
echo -e "${GREEN}Instalación completada.${NC}"
echo "Nginx está corriendo en el Host."
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
# scripts/instalar_ssl.sh
# Script para instalar Certbot y obtener certificado SSL para ns8.frlr.utn.edu.ar
DOMAIN="ns8.frlr.utn.edu.ar"
EMAIL="admin@ns8.frlr.utn.edu.ar" # Ajustar si es necesario, Certbot pedirá uno real interactivo o usará este
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Ejecutar con sudo.${NC}"
exit 1
fi
echo -e "${YELLOW}[1/4] Instalando Certbot y plugin Nginx...${NC}"
apt-get update
apt-get install -y certbot python3-certbot-nginx
echo -e "${YELLOW}[2/4] Activando configuración del dominio $DOMAIN...${NC}"
# Enlazar la nueva config si no existe
ln -sf /home/rmonla/Documentos/GitHub/dtic-DIIAA/servicios/nginx/conf.d/ns8.conf /etc/nginx/conf.d/ns8.conf
echo -e "${YELLOW}[3/4] Verificando y Recargando Nginx...${NC}"
nginx -t && systemctl reload nginx
echo -e "${YELLOW}[4/4] Ejecutando Certbot...${NC}"
echo "Sigue las instrucciones en pantalla (ingresa tu email si se solicita)."
certbot --nginx -d $DOMAIN
echo -e "${GREEN}Proceso finalizado.${NC}"
echo "Prueba acceder a https://$DOMAIN"
+30
View File
@@ -0,0 +1,30 @@
#!/bin/bash
# scripts/instalar_tailscale.sh
# Automatización de la instalación de Tailscale en srv-NS8
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Ejecutar con sudo.${NC}"
exit 1
fi
echo -e "${YELLOW}Iniciando instalación de Tailscale...${NC}"
# 1. Ejecutar script oficial de instalación
curl -fsSL https://tailscale.com/install.sh | sh
# 2. Habilitar el servicio
systemctl enable --now tailscaled
# 3. Informar al usuario para la autenticación
echo -e "\n${GREEN}Tailscale ha sido instalado.${NC}"
echo -e "${YELLOW}IMPORTANTE: Ahora debes autenticar el servidor.${NC}"
echo -e "Ejecuta el siguiente comando en tu terminal y sigue el enlace de autenticación:"
echo -e "${CYAN}sudo tailscale up${NC}"
# 4. Nota sobre Subnet Routing (opcional)
echo -e "\n${NC}Si deseas acceder a la LAN 10.0.10.x desde fuera, usa el flag: --advertise-routes=10.0.10.0/24${NC}"
+100
View File
@@ -0,0 +1,100 @@
#!/usr/bin/env ruby
# [PROC-01] - Mantenimiento de Backups Proxmox (Ruby Edition)
# Lógica: Granular por VMID, Retención 6 días, Destino zfsDISCO1
require 'date'
require 'fileutils'
STORAGE_NAME = "zfsDISCO1"
# NOTA: En Proxmox, la ruta suele ser /mnt/pve/zfsDISCO1 o similar.
# Ajustamos a la ruta montada del storage.
BASE_PATH = "/mnt/pve/#{STORAGE_NAME}/dump"
RETENTION_DAYS = 6
VM_PATTERN = /^srv[v]?-/
def log(message, type = "INFO")
timestamp = Time.now.strftime("%Y-%m-%d %H:%M:%S")
puts "[#{timestamp}] [#{type}] #{message}"
end
def get_vmid_list
# Obtener IDs de VMs (QEMU) y Contenedores (LXC)
ids = []
# QEMU VMs
`qm list`.each_line.with_index do |line, idx|
next if idx == 0 # Cabecera
parts = line.split
vmid = parts[0]
name = parts[1]
ids << vmid if name =~ VM_PATTERN
end
# LXC Containers
`pct list`.each_line.with_index do |line, idx|
next if idx == 0
parts = line.split
vmid = parts[0]
name = parts[2] # El nombre suele ser la 3er columna en pct list
ids << vmid if name =~ VM_PATTERN
end
ids.uniq
end
def prune_old_backups(vmid)
log("Iniciando fase de limpieza para VMID: #{vmid}...")
return unless Dir.exist?(BASE_PATH)
# Patrón de archivos de Proxmox: vzdump-[qemu|lxc]-<VMID>-<TIMESTAMP>.*
# Buscamos archivos de este VMID específico
files = Dir.glob("#{BASE_PATH}/vzdump-*-#{vmid}-*")
files.each do |file|
mtime = File.mtime(file)
age_days = (Date.today - mtime.to_date).to_i
if age_days > RETENTION_DAYS
log("Eliminando backup antiguo: #{File.basename(file)} (Antigüedad: #{age_days} días)", "WARN")
begin
FileUtils.rm(file)
rescue => e
log("Error al eliminar #{file}: #{e.message}", "ERROR")
end
end
end
end
def run_backup(vmid)
log("Iniciando backup para VMID: #{vmid} hacia #{STORAGE_NAME}...")
# Usamos --mode stop para asegurar reinicio automático y consistencia
cmd = "vzdump #{vmid} --storage #{STORAGE_NAME} --mode stop --compress zstd"
log("Ejecutando: #{cmd}")
success = system(cmd)
if success
log("Backup completado exitosamente para VMID: #{vmid}", "SUCCESS")
else
log("FALLO en el backup para VMID: #{vmid}", "ERROR")
end
end
# --- EJECUCIÓN PRINCIPAL ---
log("=== INICIO DE CICLO DE MANTENIMIENTO DE BACKUPS ===")
unless Dir.exist?(BASE_PATH)
log("Error: No se encuentra la ruta del storage #{BASE_PATH}. ¿Está montado?", "ERROR")
exit 1
end
vmids = get_vmid_list
log("Nodos detectados para procesar: #{vmids.join(', ')}")
vmids.each do |vmid|
prune_old_backups(vmid)
run_backup(vmid)
puts "-" * 40
end
log("=== FIN DE CICLO DE MANTENIMIENTO ===")
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
# scripts/respaldar_configs.sh
# Sistema de respaldo de configuraciones críticas para srv-NS8
BACKUP_ROOT="/home/rmonla/Documentos/GitHub/dtic-DIIAA/backups/configs"
TIMESTAMP=$(date +%Y%m%d_%H%M)
LOG_FILE="/home/rmonla/Documentos/GitHub/dtic-DIIAA/logs/backup_${TIMESTAMP}.log"
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
mkdir -p "$BACKUP_ROOT"
mkdir -p "/home/rmonla/Documentos/GitHub/dtic-DIIAA/logs"
echo -e "${GREEN}Iniciando respaldo de configuraciones...${NC}" | tee -a "$LOG_FILE"
# Lista de directorios a respaldar
PATHS=(
"/etc/anydesk"
"/home/rmonla/.anydesk"
"/etc/rustdesk"
"/home/rmonla/.config/rustdesk"
"/var/lib/tailscale"
"/etc/nginx"
"/home/rmonla/Documentos/GitHub/dtic-DIIAA/servicios/homepage/.env"
)
for SRC in "${PATHS[@]}"; do
if [ -d "$SRC" ] || [ -f "$SRC" ]; then
echo "Respaldando $SRC..." | tee -a "$LOG_FILE"
# Usamos rsync para mantener la estructura y permisos (requiere sudo para rutas root)
DEST="${BACKUP_ROOT}${SRC}"
mkdir -p "$(dirname "$DEST")"
sudo rsync -avR --delete "$SRC" "$BACKUP_ROOT/" >> "$LOG_FILE" 2>&1
else
echo -e "${RED}Advertencia: No se encontró $SRC${NC}" | tee -a "$LOG_FILE"
fi
done
# Generar un comprimido del respaldo actual
tar -czf "${BACKUP_ROOT}/../configs_backup_${TIMESTAMP}.tar.gz" -C "$BACKUP_ROOT" .
echo -e "${GREEN}Respaldo completado en ${BACKUP_ROOT}/../configs_backup_${TIMESTAMP}.tar.gz${NC}" | tee -a "$LOG_FILE"