Disaster Recovery & Depuración Atómica
El plan de continuidad operativa y recuperación ante desastres de Mañuti implementa respaldo sincronizado de bases de datos híbridas (SQL + NoSQL), almacenamiento fuera de sitio (off-site) vía SFTP/SSH y políticas de retención automatizadas gobernadas por el planificador atómico de Laravel.
1. Respaldo Híbrido Sincronizado (system:backup)
El comando personalizado system:backup consolida los motores relacionales y documentales en un único artefacto de recuperación:
[php artisan system:backup]
|
+---> 1. Dump MongoDB: mongodump a /storage/app/backup-temp/mongo.gz
|
+---> 2. Spatie Backup: Inyecta dump de MariaDB + archivo mongo.gz
|
+---> 3. Cifra y comprime paquete final (.zip)
|
+---> 4. Transfiere vía SFTP a nodo de almacenamiento remoto
|
+---> 5. Purga archivos temporales locales
|
+---> 6. Registra éxito en MongoDB (system.backup)
Configuración Dinámica de Destino SFTP
Las credenciales de almacenamiento no residen fijas en archivos de configuración. Se resuelven dinámicamente desde configuracion_sistema antes de abrir el túnel de transporte:
Config::set('filesystems.disks.sftp_dynamic', [
'driver' => 'sftp',
'host' => ConfiguracionSistema::getValor('backup_remote_host'),
'username' => ConfiguracionSistema::getValor('backup_remote_username'),
'password' => ConfiguracionSistema::getValor('backup_remote_password'),
'root' => ConfiguracionSistema::getValor('backup_remote_path'),
'timeout' => 30,
]);
2. Política de Retención y Depuración (privacy:prune-logs)
Para dar cumplimiento al principio de limitación de plazo de conservación de datos (ISO 27701), el sistema elimina periódicamente información que supera la ventana de prescripción legal configurada (security_log_retention_days, default 1825 días / 5 años):
// app/Console/Commands/PruneSystemLogs.php
public function handle(): int
{
$dias = (int) ConfiguracionSistema::getValor('security_log_retention_days', 1825);
$corte = Carbon::now()->subDays($dias);
// 1. Purga relacional en MariaDB
$deletedSQL = LoginLog::where('created_at', '<', $corte)->delete();
// 2. Purga masiva en MongoDB
$deletedMongo = AuditLog::where('created_at', '<', $corte)->delete();
Log::info("Data Retention: Purga completada. SQL: {$deletedSQL}, Mongo: {$deletedMongo}");
return 0;
}
3. Orquestación Atómica en Clúster (onOneServer)
En arquitecturas distribuidas de alta disponibilidad con múltiples nodos web detrás de un balanceador de carga, el planificador de tareas se programa para evitar ejecuciones concurrentes o duplicidad de backups:
// routes/console.php
use Illuminate\Support\Facades\Schedule;
// Ejecución nocturna del plan de respaldo
Schedule::command('system:backup')
->dailyAt('02:00')
->onOneServer(); // Bloqueo atómico distribuido en Redis
// Ejecución de la depuración de logs
Schedule::command('privacy:prune-logs')
->dailyAt('03:00')
->onOneServer();
- Mecanismo de Exclusión Mutua: Al utilizar
onOneServer(), Laravel adquiere un bloqueo atómico (lock) en la instancia central de Redis. El primer servidor que toma el lock ejecuta la tarea; los nodos restantes en el clúster omiten la invocación, impidiendo colisiones de I/O o respaldos corruptos.
4. Purgado Quirúrgico de Caché en Caliente (Hot Cache Purge)
Desde el panel de administración, la invalidación de caché no utiliza artisan optimize:clear (lo cual destruiría las sesiones activas en Redis). Ejecuta un purgado selectivo:
Cache::forget('global_site_config'): Refresca parámetros de la base de datos.Artisan::call('view:clear'): Fuerza la recompilación de vistas Blade.Artisan::call('event:clear'): Actualiza el registro de listeners.- Preservación de Estado: El espacio de nombres de sesiones en Redis se mantiene inalterado, garantizando que los operadores no sean desconectados del sistema.
Enlaces Relacionados
- Cumplimiento Normativo: Cifrado PII & Derechos ARCO
- Auditoría Forense Asíncrona (MongoDB)
- Hardening HTTP, CSP & Control de Caché