🤔 Blindaje de Infraestructura en Raspberry Pi 3B (Raspberry OS Lite)

La Raspberry Pi 3B es una máquina increíblemente versátil, pero con sus 1GB de RAM, la estabilidad es nuestra prioridad número uno. En entornos de servidor (LAMP), una actualización imprevista de paquetes core como PHP 8.4 puede disparar el consumo de recursos o causar incompatibilidades que dejen tu servicio offline.

En este artículo, aprenderás a construir un Panel de Control de Inmutabilidad para «congelar» tu software y asegurar que tu Pi funcione exactamente como el día que la configuraste.

La idea es EVITAR actualizaciones que nos tiren el Servidor, concretamente un viernes a las 14.59, lo que es lo mismo… que no tengamos cambios entre el día que lo «lanzaste» (Base) y el día de hoy (Live).


1. El Concepto: Inmutabilidad de Paquetes

En sistemas basados en Debian (como Raspberry OS), el comando apt upgrade busca la versión más reciente de cada programa. El Blindaje (Apt-Pinning) marca los paquetes como «retenidos» (on hold). El sistema los ignorará por completo hasta que tú decidas liberar el candado.

¿Por qué en la 3B?

  • Recursos Críticos: Evitas que servicios nuevos más pesados saturen la RAM.
  • SD Card Health: Menos escrituras accidentales por actualizaciones masivas prolongan la vida de tu tarjeta microSD.

2. Preparación de la «Zona de Administración»

Para mantener el orden y la seguridad, crearemos una carpeta dedicada a scripts de sistema que el servidor web pueda invocar de forma controlada.

Bash

# Creamos la ruta de aplicaciones
sudo mkdir -p /var/www/apps/admin-scripts

# Ajustamos el propietario al usuario del servidor web
sudo chown -R www-data:www-data /var/www/apps/

3. El Script de Control: apt_lock.sh

Este script actúa como el brazo ejecutor. Es fundamental crearlo directamente en la Pi para evitar conflictos de formato entre Windows y Linux.

Ejecuta este comando para generar el archivo:

Bash

sudo tee /var/www/apps/admin-scripts/apt_lock.sh << 'EOF'
#!/bin/bash
# Script de Blindaje APT - Versión Purificada
PAQUETES="php8.4* apache2* mariadb-server* mariadb-client*"

case "$1" in
lock)
apt-mark hold $PAQUETES > /dev/null 2>&1
sync; echo 3 > /proc/sys/vm/drop_caches
systemctl restart php8.4-fpm
echo "PROTEGIDO"
;;
unlock)
apt-mark unhold $PAQUETES > /dev/null 2>&1
echo "VULNERABLE"
;;
status)
if apt-mark showhold | grep -q "php8.4"; then
echo "PROTEGIDO"
else
echo "VULNERABLE"
fi
;;
esac
EOF

Permisos críticos:

Bash

sudo chmod +x /var/www/apps/admin-scripts/apt_lock.sh
# Eliminamos posibles caracteres ocultos de Windows
sudo sed -i 's/\r$//' /var/www/apps/admin-scripts/apt_lock.sh

4. Configuración de Privilegios (Sudoers)

El servidor web (usuario www-data) no tiene permiso para modificar paquetes. Debemos concederle este «superpoder» estrictamente para nuestro script.

  1. Ejecuta: sudo visudo -f /etc/sudoers.d/panel-apt-locks
  2. Pega esta línea exacta: www-data ALL=(ALL) NOPASSWD: /var/www/apps/admin-scripts/apt_lock.sh

5. El Panel Web: lock-updates.php

Crea este archivo en la raíz de tu sitio web (/var/www/html/). Este código detecta el estado actual y ofrece el botón de acción.

PHP

<?php
session_start();
// Cambia 'auth' por la variable que uses en tu login
if (!isset($_SESSION['auth'])) { header("Location: admin.php"); exit(); }

$script = "/var/www/apps/admin-scripts/apt_lock.sh";

if (isset($_POST['toggle'])) {
    $accion = ($_POST['actual'] == "VULNERABLE") ? "lock" : "unlock";
    shell_exec("sudo $script $accion");
}

$status = trim(shell_exec("sudo $script status"));
$is_locked = ($status == "PROTEGIDO");
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Blindaje - Raspberry Pi</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body { background: #0f172a; color: #f8fafc; font-family: system-ui; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; }
        .card { background: #1e293b; padding: 2rem; border-radius: 1.5rem; width: 90%; max-width: 400px; text-align: center; border: 1px solid #334155; }
        .status-badge { padding: 1rem; border-radius: 0.75rem; margin: 1.5rem 0; font-weight: bold; font-family: monospace; }
        .locked { background: rgba(34,197,94,0.1); color: #4ade80; border: 1px solid #22c55e; }
        .unlocked { background: rgba(239,68,68,0.1); color: #f87171; border: 1px solid #ef4444; }
        .btn { width: 100%; padding: 1rem; border-radius: 0.75rem; border: none; font-weight: bold; cursor: pointer; transition: 0.2s; }
        .btn-lock { background: #22c55e; color: white; }
        .btn-unlock { background: #ef4444; color: white; }
        .btn:active { transform: scale(0.98); }
    </style>
</head>
<body>
    <div class="card">
        <h2>🛡️ Blindaje Pi 3B</h2>
        <p style="color: #94a3b8; font-size: 0.9rem;">Protección de versiones core para Raspberry OS Lite</p>
        
        <div class="status-badge <?php echo $is_locked ? 'locked' : 'unlocked'; ?>">
            ESTADO: <?php echo $status; ?>
        </div>

        <form method="POST">
            <input type="hidden" name="actual" value="<?php echo $status; ?>">
            <button type="submit" name="toggle" class="btn <?php echo $is_locked ? 'btn-unlock' : 'btn-lock'; ?>">
                <?php echo $is_locked ? '🔓 Permitir Actualizaciones' : '🔒 Bloquear Versiones Core'; ?>
            </button>
        </form>
        <br><a href="admin.php" style="color: #64748b; text-decoration: none; font-size: 0.8rem;">← Volver al Panel</a>
    </div>
</body>
</html>

6. Verificación: ¿Cómo saber si funciona?

Una vez actives la protección desde el panel, puedes comprobarlo en la terminal de dos maneras:

A. El comando de consulta

Bash

apt-mark showhold

Deberías ver una lista con php8.4, apache2, etc.

B. El simulacro de actualización

Bash

sudo apt-get upgrade --simulate

En el resumen final, verás una línea que dice: «X paquetes no actualizados» (not upgraded). Esos son tus paquetes blindados.


7. Consejos de Mantenimiento para Raspberry OS Lite

  1. Seguridad: Aunque el blindaje es excelente para la estabilidad, recuerda desbloquear el sistema una vez al mes, realizar un sudo apt update para parches de seguridad, y volver a bloquear.
  2. Logs: Revisa periódicamente /var/log/apache2/error.log si notas lentitud en el panel.
  3. Backups: Antes de desbloquear y actualizar, realiza un volcado de tu base de datos MariaDB.

8. «Puesta a Punto y Permisos»

Una vez creado el script, es vital prepararlo para el entorno de producción de la Raspberry Pi. No basta con que el archivo exista; debe ser ejecutable por el servidor web y tener el formato de texto correcto de Linux. Ejecuta este bloque de comandos para garantizar que todo funcione a la primera:

Bash

# 1. Limpieza de formato (Crucial si editas desde Windows)
# Elimina los caracteres invisibles \r que rompen la ejecución en Linux
sudo sed -i 's/\r$//' /var/www/apps/admin-scripts/apt_lock.sh

# 2. Asignación de permisos de ejecución
# Permitimos que el script se comporte como un programa
sudo chmod 755 /var/www/apps/admin-scripts/apt_lock.sh

# 3. Transferencia de propiedad
# Aseguramos que el usuario de Apache (www-data) sea el dueño del proceso
sudo chown www-data:www-data /var/www/apps/admin-scripts/apt_lock.sh

Nota de experto: El comando sed es tu mejor amigo cuando trabajas con Raspberry Pi OS desde un PC. Evita el 90% de los errores de «archivo no encontrado» cuando el archivo claramente está ahí.


¿Por qué incluirlos?

  1. Fiabilidad: Tu guía será a prueba de errores de usuario.
  2. Autoridad: Demuestras que conoces las tripas de Linux (manejo de CRLF vs LF).
  3. Soporte: Te ahorrarás muchos comentarios en el blog preguntando por qué el botón no hace nada.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *