La mayoría de las intrusiones exitosas en servidores no ocurre por exploits ingeniosos sino por una vulnerabilidad cuyo parche salió hace meses. El motivo no suele ser la pereza: actualizar a mano en un servidor en producción da miedo, porque apt upgrade a veces reinicia lo que nadie le pidió. Las actualizaciones automáticas resuelven la cuestión, pero tienen mala fama, merecida exactamente en la medida en que se configuran con prisas.

Veamos una configuración en la que los parches de seguridad llegan solos y la versión de PHP no cambia de noche.

Instalación

sudo apt install unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades

El diálogo crea /etc/apt/apt.conf.d/20auto-upgrades. Compruebe qué ha salido de ahí:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

Los unos significan «a diario». Todo eso lo lanza un temporizador de systemd, no el cron clásico:

systemctl list-timers | grep apt

Lo principal: solo seguridad

El archivo principal es /etc/apt/apt.conf.d/50unattended-upgrades. Contiene una lista Allowed-Origins (en Debian, Origins-Pattern), y por omisión ahí está activado solo el repositorio de seguridad. Déjelo así.

La tentación de descomentar la línea con -updates —«que se actualice todo»— es fuerte. No lo haga: el repositorio de actualizaciones trae versiones nuevas y no solo correcciones, y de ahí vienen precisamente las sorpresas nocturnas. Seguridad y novedad son tareas distintas, y la segunda se hace mejor a mano, con usted al teclado.

Si algún paquete no debe actualizarse automáticamente, existe una lista negra:

Unattended-Upgrade::Package-Blacklist {
    "mariadb-server";
    "php8.3-fpm";
};

Úsela con conciencia: cada línea ahí significa «este paquete lo actualizo yo», y esa promesa habrá que cumplirla.

Los reinicios

La línea clave:

Unattended-Upgrade::Automatic-Reboot "false";

Dejar false es lo correcto para un servidor con un sitio: un reinicio sin aviso a las tres de la madrugada es peor que un parche aplazado un día. Pero esa decisión tiene una segunda mitad obligatoria, y es la que se olvida.

Cuando se actualizan el núcleo, libc u openssl, el sistema crea el archivo /var/run/reboot-required. Hasta que no haya reinicio, la versión corregida está en el disco mientras la antigua funciona en memoria: la vulnerabilidad, por tanto, no ha desaparecido, aunque el paquete conste como actualizado. Compruébelo de forma explícita:

ls -l /var/run/reboot-required
cat /var/run/reboot-required.pkgs

El segundo archivo enumera qué ha hecho necesario el reinicio. La regla es sencilla: en cuanto vea el indicador, planifique una ventana en los próximos uno o dos días, y no «algún día».

Las bibliotecas son caso aparte. Se actualiza openssl mientras nginx y PHP-FPM siguen funcionando con la versión antigua en memoria, y no aparece indicador de reinicio alguno. Quién necesita reiniciarse lo muestra needrestart:

sudo apt install needrestart
sudo needrestart -b

Póngalo solo en modo «mostrar, no preguntar»: de lo contrario empezará a hacer preguntas en mitad de una instalación no interactiva y la dejará colgada. Para ello, deje en /etc/needrestart/conf.d/ un archivo con la línea $nrconf{restart} = 'l';.

Comprobar que funciona

Una pasada de prueba sin instalar:

sudo unattended-upgrade --dry-run --debug

La salida muestra qué paquetes encajan en las reglas y cuáles se descartaron y por qué. Lo que ocurrió realmente está en los registros:

sudo tail -50 /var/log/unattended-upgrades/unattended-upgrades.log

Cuántas actualizaciones esperan ahora mismo:

apt list --upgradable 2>/dev/null | grep -i security

Ese último comando es el más útil de todos. Unas actualizaciones automáticas configuradas tienen la costumbre de romperse en silencio: se acabó el sitio en /boot, un repositorio cambió de clave, el temporizador quedó desactivado tras algún ajuste manual. Por fuera todo está bien, y los parches llevan meses sin instalarse.

El espacio en /boot

Un clásico: los núcleos antiguos no se eliminan, la partición /boot se llena, la instalación de un núcleo nuevo falla y las actualizaciones se detienen en conjunto. Cada pocos meses merece la pena echar un vistazo:

df -h /boot
sudo apt autoremove --purge

O active la limpieza automática en ese mismo 50unattended-upgrades: Remove-Unused-Kernel-Packages "true" y Remove-Unused-Dependencies "true".

Lo que le queda a la persona

Las actualizaciones automáticas quitan la rutina, no la vigilancia. Dos preguntas que debería poder responder en cualquier momento: cuántas actualizaciones de seguridad esperan y si está puesto el indicador de reinicio. Ambas respuestas son una línea en una página, y todo el sentido está en que esa línea le salte a la vista por sí sola y no por iniciativa suya una vez por trimestre.