Configurar actualizaciones de seguridad automáticas con unattended-upgrades

Publicado el 17 min de lectura

Cómo configurar unattended-upgrades para que funcione de verdad: fuentes permitidas, paquetes excluidos, comportamiento en el reinicio, informe por correo y la prueba en el log de que algo ha ocurrido realmente.

Entre el momento en que aparece una actualización de seguridad y el momento en que se instala hay, en la mayoría de los servidores, un hueco. Rara vez nace del descuido, nace de que alguien se propone aplicarla "la semana que viene". Los escáneres prueban una vulnerabilidad recién publicada en cuestión de horas. El paquete unattended-upgrades cierra ese hueco.

La versión corta ya está como paso 7 en la checklist para un servidor root nuevo. Aquí va todo lo que viene después: actualizaciones de seguridad frente a todas las actualizaciones, el reinicio en un servidor de juegos, el aviso por correo, los paquetes excluidos, la ejecución en seco y la prueba en el log.

Comprobado en Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS y Ubuntu 22.04 LTS. Donde los cuatro se diferencian, queda indicado. Los comandos son para root; si trabajas como usuario normal, antepón sudo a cada uno.

Qué está pasando aquí en realidad

Aquí las búsquedas de fallos se alargan porque no queda claro cuál de las tres piezas implicadas no hace lo que debería:

  1. Dos temporizadores de systemd: apt-daily.timer para las listas de paquetes y la descarga, apt-daily-upgrade.timer para la instalación.
  2. El script /usr/lib/apt/apt.systemd.daily, que evalúa las opciones bajo APT::Periodic::.
  3. El programa unattended-upgrade, que evalúa las opciones bajo Unattended-Upgrade:: y hace el trabajo.

Fíjate en el singular: el paquete es unattended-upgrades, el programa es unattended-upgrade.

systemctl list-timers 'apt-daily*' --all
systemctl cat apt-daily-upgrade.timer

Las columnas LAST y PASSED indican si alguna vez ha habido una ejecución. En la unit está OnCalendar=*-*-* 6:00 junto con RandomizedDelaySec=60m: la ejecución cae entre las seis y las siete, y en apt-daily.timer la dispersión es de doce horas. Quien mira a las 06:05 da por roto el mecanismo sin motivo.

Antes del primer cambio: el camino de vuelta

Las actualizaciones automáticas actúan cuando tú no estás delante. Tres cosas pueden salir mal: un reinicio saca el servidor de servicio, una operación con paquetes se interrumpe y deja dpkg a medias, o un servicio ya no arranca después.

El acceso que sigue funcionando en los tres casos no es SSH. Los servidores root KVM y los servidores dedicados de KernelHost no tienen IPMI ni iDRAC, el acceso de emergencia va por la consola VNC del área de cliente. Esa consola cuelga de la capa de virtualización, o del propio puerto, así que una avería dentro del sistema huésped no la alcanza. Entra una vez por ahí antes de empezar y comprueba la contraseña de root. Una vía de rescate que se prueba por primera vez el día del incidente no es una vía de rescate.

Después, asegura el estado de partida:

mkdir -p /root/previo-unattended
cp -a /etc/apt/apt.conf.d/50unattended-upgrades /root/previo-unattended/
dpkg --get-selections > /root/previo-unattended/paquetes.txt
apt-mark showhold > /root/previo-unattended/holds.txt

El interruptor de emergencia existe por partida doble. En duro, a través de los temporizadores:

systemctl disable --now apt-daily-upgrade.timer apt-daily.timer

La vía suave consiste en poner en /etc/apt/apt.conf.d/20auto-upgrades el valor APT::Periodic::Unattended-Upgrade "0";. Así las listas de paquetes siguen al día, pero no se instala nada.

Comprobación:

systemctl is-enabled apt-daily-upgrade.timer
apt-config dump APT::Periodic

Para volver atrás: /var/log/apt/history.log nombra el número de versión antiguo y el nuevo. Pero un apt install paquete=version solo funciona mientras la versión antigua siga en algún servidor espejo, y los archivos suelen guardar únicamente el estado actual. Cuenta con corregir hacia delante y con tener un backup.

Instalación y activación

apt update
apt install -y unattended-upgrades

Diferencia entre las distribuciones: en Ubuntu 22.04 y 24.04 el paquete viene instalado y activo en las imágenes de servidor, así que ahí comprueba eso primero. En Debian falta en las imágenes mínimas, y la instalación pregunta si las actualizaciones estables deben aplicarse solas. Si no se ejecuta de forma interactiva, por ejemplo al construir una imagen, vale el valor por defecto y el archivo decisivo no llega a crearse.

Porque el paquete por sí solo no activa nada. Eso lo hace este archivo:

cat /etc/apt/apt.conf.d/20auto-upgrades

Si falta, el comando responde cat: /etc/apt/apt.conf.d/20auto-upgrades: No such file or directory. Entonces recupera la pregunta con dpkg-reconfigure -plow unattended-upgrades o escribe el archivo tú mismo:

cat > /etc/apt/apt.conf.d/20auto-upgrades <<'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
EOF

Los valores no son interruptores de sí o no, sino intervalos en días: "1" a diario, "7" como mucho una vez por semana, "0" desactivado. AutocleanInterval retira archivos de paquete que ya no existen en el servidor espejo, algo que se nota en sistemas con poco almacenamiento (disco lleno en Linux).

Comprobación: apt-config dump APT::Periodic imprime las líneas definidas. Si no sale nada, no se ha leído ningún archivo y la ejecución nocturna no hace nada.

Tus propios ajustes, en el sitio correcto

El archivo /etc/apt/apt.conf.d/50unattended-upgrades que viene de serie pertenece al paquete. Si lo modificas, en la siguiente actualización del paquete aparece un conflicto sobre el archivo de configuración y unattended-upgrades se salta ese paquete. La herramienta de las actualizaciones automáticas quedaría excluida de ellas.

Tus valores van en un archivo propio con un número más alto. APT lee el directorio por orden alfabético y, en los valores simples, gana el último que ha leído:

cat > /etc/apt/apt.conf.d/52unattended-upgrades-local <<'EOF'
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
Unattended-Upgrade::MinimalSteps "true";
EOF

MinimalSteps viene activado de serie y parte la ejecución en pasos pequeños que se pueden interrumpir de forma limpia al apagar. Remove-Unused-Kernel-Packages retira los kernel antiguos, que si no acaban llenando la partición /boot. Las dos opciones de limpieza vienen puestas de serie en Ubuntu, en Debian no.

El nombre del archivo no es un detalle. APT solo lee aquí archivos sin extensión o con .conf, y solo nombres formados por letras, cifras, guion, guion bajo y punto. Un archivo de backup 52unattended-upgrades-local.bak se ignora en silencio, lo cual viene bien; un archivo 52-mis-ajustes.txt también, lo cual fastidia.

Comprobación, justo después de cada cambio:

apt-config dump > /dev/null && echo "Sintaxis correcta"
apt-config dump | grep "^Unattended-Upgrade::"

Un punto y coma que falte deja inservible cualquier llamada a apt, también la nocturna.

Solo actualizaciones de seguridad o todas las actualizaciones

Qué paquetes entran en juego lo decide una lista de fuentes permitidas. Las distribuciones se diferencian ya en el nombre de la clave: Debian usa Unattended-Upgrade::Origins-Pattern, Ubuntu Unattended-Upgrade::Allowed-Origins.

sed -n '/Allowed-Origins\|Origins-Pattern/,/};/p' /etc/apt/apt.conf.d/50unattended-upgrades

De serie están activos los patrones para la fuente de seguridad y para el archivo base de la propia publicación. Comentados quedan los pockets -updates, -proposed y -backports. En Ubuntu hay además dos entradas para el servicio de mantenimiento ampliado; sin suscripción no aportan nada. Los marcadores ${distro_id} y ${distro_codename} los resuelve el programa en tiempo de ejecución, por ejemplo a Debian y trixie.

De dónde salen las piezas de un patrón lo enseña apt-cache policy. Para cada fuente hay ahí una línea que empieza por release con los campos o= (origen), a= (archivo), n= (nombre en clave), l= (etiqueta) y c= (componente). La fuente de seguridad de Debian lleva la etiqueta Debian-Security, y justo a eso apunta el patrón que viene de serie.

Si quieres que lleguen también de forma automática las correcciones corrientes de la distribución, añade el patrón en tu propio archivo. En la configuración de apt las listas se amplían, no se sustituyen:

Unattended-Upgrade::Origins-Pattern {
        "origin=Debian,codename=${distro_codename}-updates";
};

En Ubuntu el equivalente es "${distro_id}:${distro_codename}-updates"; dentro de un bloque Allowed-Origins. Sustituir una lista por completo solo es posible si antes la vacías con #clear Unattended-Upgrade::Origins-Pattern;.

Para las fuentes de terceros vale el mismo procedimiento. Eso sí, suelen traer versiones con funciones nuevas en lugar de correcciones de seguridad puras, y aplicarlas de noche sin vigilancia es otra categoría de riesgo. Para sistemas en producción la regla es, por tanto: quédate en las fuentes de seguridad.

La ejecución en seco

apt update
unattended-upgrade --dry-run --debug

El apt update previo no es un adorno: la ejecución en seco no actualiza por sí misma las listas de paquetes, así que sin esa llamada estarías valorando el estado de ayer. No se instala nada. En la salida cuentan cuatro puntos:

  • Allowed origins are: con la lista que rige de verdad. Esa es la prueba de que tu cambio ha llegado, no mirar el archivo.
  • Initial blacklist: con tus excepciones. Si ahí no hay nada aunque hayas apuntado alguna, tu archivo no se está leyendo.
  • Las líneas que empiezan por Checking:, una por paquete, con su fuente y con la admisión.
  • Al final, o bien Packages that will be upgraded: con una lista, o bien No packages found that can be upgraded unattended and no pending auto-removals.

El último mensaje aparece también cuando apt list --upgradable sí lista paquetes. No es un fallo, es el filtro haciendo su trabajo: cada paquete que sale ahí y falta en la ejecución en seco viene de una fuente no permitida, está en tu lista de excepciones, está retenido con apt-mark hold o provoca una pregunta sobre un archivo de configuración.

Excluir paquetes del automatismo

Hay cosas que no deben actualizarse de noche: una base de datos cuyo reinicio deja colgada a una aplicación, o el kernel de un sistema que no se reinicia sin avisar. El primero de los dos caminos actúa solo sobre el automatismo:

Unattended-Upgrade::Package-Blacklist {
        "mariadb-server$";
        "nginx$";
        "linux-image-";
};

Las entradas son expresiones regulares ancladas al principio del nombre del paquete. Por eso "nginx" sin el signo del dólar alcanza también a nginx-common y a nginx-full; el $ limita la entrada a ese nombre exacto. Al revés, "linux-image-" sin $ es lo correcto si te refieres a todos los paquetes de kernel.

El segundo camino actúa sobre cualquier llamada a apt, también sobre tu apt upgrade manual:

apt-mark hold mariadb-server
apt-mark showhold

Se deshace con apt-mark unhold. Si un paquete solo no debe actualizarse de forma desatendida, usa la lista de excepciones; si no debe actualizarse en absoluto, usa hold.

Comprobación: apt-config dump | grep -i "Package-Blacklist" y apt-mark showhold. La parte incómoda: un paquete excluido tienes que actualizarlo tú. Apunta una fecha para ello, porque si no, dentro de medio año esa excepción será una vulnerabilidad olvidada.

Reinicio automático

Tras la actualización, un kernel nuevo está en el almacenamiento, pero no entra en marcha hasta que hay un reinicio; las bibliotecas sustituidas no surten efecto hasta que el servicio se reinicia. Tres opciones controlan eso:

Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";

Automatic-Reboot viene desactivado de serie. Automatic-Reboot-WithUsers viene activado de serie, y eso sorprende a mucha gente: una sesión SSH abierta no impide el reinicio, y quien quiera impedirlo pone el valor en "false". Automatic-Reboot-Time es obligatorio en cuanto el reinicio está activo. Sin ese dato rige now, es decir, el servidor se reinicia justo después de la ejecución, o sea entre las seis y las siete de la mañana.

No lo dispara el paquete del kernel, sino un archivo de marca:

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

La diferencia de más peso de todo este artículo: Ubuntu crea ese archivo (viene del paquete update-notifier-common), y el segundo nombra los paquetes responsables. Debian no lo crea de forma estándar. Ahí Automatic-Reboot "true" puede quedarse sin efecto de forma permanente sin que nada dé un error. Quien se fía de eso lleva meses con un kernel antiguo y una buena sensación. En Debian lo que sirve es esto:

apt install -y needrestart
needrestart -b

La salida nombra en NEEDRESTART-KCUR el kernel en marcha y en NEEDRESTART-KEXP el esperado; si son distintos, toca reiniciar. Las líneas NEEDRESTART-SVC listan los servicios que siguen funcionando con bibliotecas ya sustituidas.

Por qué en un servidor de juegos el ajuste es otro

En un servidor web, un reinicio a las 02:00 es cosa de segundos y nadie se entera. En un servidor de juegos hay jugadores conectados, el mundo está en la RAM y la partida no se escribe entera hasta que el proceso termina de forma ordenada. Si el proceso se corta en duro, pierdes lo avanzado desde el último guardado intermedio y, en el peor caso, el archivo del mundo queda dañado.

A eso se suma un detalle de systemd: al apagar, cada servicio recibe su señal de parada y después un plazo limitado, tras el cual se le termina en duro. Un servidor de juego que guarda al cerrar suele necesitar más tiempo del que da el valor por defecto, y también un comando de parada que envíe un stop a la consola del servidor en lugar de una simple señal a un lanzador. Para los servidores de juegos, por eso, la combinación sensata es esta:

  • Automatic-Reboot "false". Las actualizaciones de seguridad siguen su curso, el reinicio sigue siendo decisión tuya.
  • Una ventana de mantenimiento con pocos jugadores, anunciada en vez de por sorpresa.
  • Una unit de systemd con un comando de parada que guarde y con un TimeoutStopSec suficiente, mira crear un servicio systemd.
  • Y si aun así lo quieres automático, pon Automatic-Reboot-Time en una hora con poca gente conectada.

Todo esto se puede comprobar sin reiniciar: para el servicio con systemctl stop, mira la partida guardada y vuelve a arrancarlo. Si eso sale limpio, también aguanta un reinicio a las 02:00.

Mover la hora de la ejecución

systemctl edit apt-daily-upgrade.timer
[Timer]
OnCalendar=
OnCalendar=*-*-* 03:30
RandomizedDelaySec=30m

La línea vacía OnCalendar= es obligatoria, borra el valor que viene de serie. Sin ella, tu hora se suma a la anterior y la ejecución ocurre dos veces al día.

systemctl daemon-reload
systemctl restart apt-daily-upgrade.timer
systemctl list-timers 'apt-daily*' --all

Comprobación: en la columna NEXT aparece la hora nueva.

Aviso por correo electrónico

Un mecanismo del que nadie oye nada no se vigila, se olvida. Dos líneas cambian eso:

Unattended-Upgrade::Mail "admin@tu-dominio.es";
Unattended-Upgrade::MailReport "on-change";

MailReport conoce tres valores: always después de cada ejecución, on-change solo cuando se ha instalado algo o algo ha salido mal, only-on-error únicamente en caso de error. La opción más antigua MailOnlyOnError sustitúyela en cuanto te la encuentres.

La condición es que exista una vía de envío. unattended-upgrades envía a través de /usr/bin/mail o de /usr/sbin/sendmail. Si faltan los dos, el envío no se produce y tú no te enteras. En un servidor recién instalado ese es el caso normal:

apt install -y bsd-mailx
echo "Mensaje de prueba" | mail -s "Prueba desde el servidor" admin@tu-dominio.es

Con ello se instala también un servicio de transporte de correo. Comprueba después con ss -lntp | grep ':25' que solo escucha en 127.0.0.1. Además, los mensajes enviados directamente desde la IP de un servidor acaban a menudo en la carpeta de spam; si quieres que el informe llegue, dirige el envío a través de un servidor de relay con un dominio de remitente bien configurado.

Consejo práctico: pon always durante las dos primeras semanas. Un mensaje diario que informa de que no había nada que hacer es la prueba más sencilla de que el mecanismo funciona. Después vuelve a on-change, porque si no acabarás borrándolo sin leerlo.

Comprobar en los logs si de verdad ha pasado algo

ls -l /var/log/unattended-upgrades/
tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.log

Ahí hay hasta tres archivos. unattended-upgrades.log deja constancia de lo que ha decidido el programa. unattended-upgrades-dpkg.log contiene la salida en bruto de la instalación, y es donde miras cuando un paquete ha fallado al configurarse. unattended-upgrades-shutdown.log aparece cuando una ejecución terminó durante el apagado.

Una ejecución sin novedades acaba con No packages found that can be upgraded unattended and no pending auto-removals. Una ejecución que ha hecho algo contiene Packages that will be upgraded: y, más abajo, All upgrades installed. Si el archivo está vacío o falta la carpeta, nunca ha habido una ejecución.

Al margen de eso, la gestión de paquetes registra cada acción con el número de versión antiguo y el nuevo:

grep -E "^(Start-Date|Commandline|Upgrade|End-Date):" /var/log/apt/history.log | tail -n 20
zgrep -h "^Upgrade:" /var/log/apt/history.log*.gz | tail -n 10

La segunda llamada accede a los archivos ya rotados; quien mira solo el actual no encuentra nada y saca de ahí la conclusión equivocada. La tercera fuente es systemd:

journalctl -u apt-daily-upgrade.service --since "-7 days" --no-pager

La trampa en la que cae casi todo el mundo alguna vez: systemctl status unattended-upgrades.service muestra de forma permanente active (running). Eso no es una actualización en marcha. Esa unit se encarga de terminar durante el apagado una ejecución ya empezada, y el resto del tiempo espera. La instalación ocurre en apt-daily-upgrade.service.

Errores frecuentes y soluciones

cat: /etc/apt/apt.conf.d/20auto-upgrades: No such file or directory
El paquete está instalado, pero no hay nada activado; en Debian es el estado normal tras una instalación no interactiva. Solución: dpkg-reconfigure -plow unattended-upgrades.

No packages found that can be upgraded unattended and no pending auto-removals, aunque apt list --upgradable muestre paquetes
No es un fallo, es el filtro. Comprueba por orden: las fuentes permitidas en la ejecución en seco, la lista de excepciones, apt-mark showhold y las preguntas de configuración.

E: Syntax error /etc/apt/apt.conf.d/52unattended-upgrades-local:2: Extra junk at end of file
Falta un punto y coma al final de una línea, o hay una llave sin cerrar. Mientras el error siga ahí, falla cualquier llamada a apt, no solo el automatismo.

E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (unattended-upgr) junto con E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
La ejecución automática está ocupada, y el nombre del proceso, recortado a quince caracteres, lo delata. Espera unos minutos. Matar el proceso genera el siguiente error de esta lista. En detalle: solucionar el error de apt "Could not get lock".

E: dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem.
Ejecuta exactamente ese comando. El Unattended-Upgrade::AutoFixInterruptedDpkg que viene puesto de serie deja que la siguiente ejecución lo repare sola, pero solo si llega a producirse.

Package nginx-common has conffile prompt and needs to be upgraded manually en el log
Has modificado un archivo de configuración que pertenece al paquete, y la versión nueva trae una variante distinta. El programa se salta entonces ese paquete de forma permanente. Haz tú esa actualización a mano. Los casos abiertos los muestra esto:

find /etc -type f \( -name "*.dpkg-dist" -o -name "*.dpkg-new" -o -name "*.ucf-dist" \)

Cache has broken packages, exiting en el log
De una acción anterior queda un estado incompleto. apt --fix-broken install y después dpkg --configure -a. Hasta entonces, el automatismo no hace nada cada noche.

Tus ajustes no surten efecto y no hay ningún mensaje de error.
Es la señal típica de un nombre de archivo ignorado. Comprueba con apt-config dump | grep -i unattended si los valores se han leído.

Automatic-Reboot "true" no hace nada en Debian.
Ahí falta el archivo de marca /var/run/reboot-required.

Los cuatro sistemas en comparación

SistemaPaquete de serieClave para las fuentesFuente de seguridadArchivo de marca para el reinicio
Debian 13 (trixie)no, hay que instalarloOrigins-Patterntrixie-security, etiqueta Debian-Securityno se crea
Debian 12 (bookworm)no, hay que instalarloOrigins-Patternbookworm-security, etiqueta Debian-Securityno se crea
Ubuntu 24.04 LTSsí, activo en las imágenes de servidorAllowed-Originsnoble-security/var/run/reboot-required
Ubuntu 22.04 LTSsí, activo en las imágenes de servidorAllowed-Originsjammy-security/var/run/reboot-required

Lo que el automatismo no hace

  • Ningún salto a una versión principal nueva y ninguna fuente de terceros mientras no haya un patrón apuntado para ella.
  • Nada que quede fuera de la gestión de paquetes. Los programas descomprimidos a mano, las extensiones de un gestor de contenidos, los plugins de un servidor de juego y los contenedores siguen con la versión que tengan.
  • Ningún sustituto del backup ni de la monitorización. Una actualización puede dejar parado un servicio y, si nadie mira, sigue parado hasta la mañana siguiente.
  • Ninguna protección frente a los ataques de red. Los paquetes al día cierran vulnerabilidades conocidas, pero contra los ataques volumétricos solo sirve el filtrado en la red que hay delante, en el caso de KernelHost en el centro de datos maincubes de Fráncfort del Meno.

La comprobación final

  1. apt-config dump APT::Periodic imprime Update-Package-Lists "1" y Unattended-Upgrade "1".
  2. apt-config dump | grep "^Unattended-Upgrade::" muestra tus propios valores.
  3. systemctl list-timers 'apt-daily*' --all muestra los dos temporizadores con una columna NEXT plausible.
  4. unattended-upgrade --dry-run --debug termina sin errores y nombra las fuentes esperadas.
  5. tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.log contiene, tras la primera ejecución, una entrada con fecha.
  6. ls -l /var/run/reboot-required en Ubuntu, needrestart -b en Debian.

El punto cinco es el que de verdad cuenta, y pide un día de paciencia: todo lo anterior es preparación, la prueba es la entrada de esta noche.

Preguntas frecuentes

¿De verdad unattended-upgrades instala solo actualizaciones de seguridad?
Con los valores por defecto, sí. Debian lo controla con Unattended-Upgrade::Origins-Pattern y Ubuntu con Unattended-Upgrade::Allowed-Origins. De serie están activos los patrones para la fuente de seguridad y para el archivo base de la propia publicación, mientras que los pockets -updates, -proposed y -backports figuran comentados. Lo que rige de verdad lo enseña la ejecución en seco con unattended-upgrade --dry-run --debug en la línea "Allowed origins are:", no mirar el archivo de configuración.
He instalado el paquete y aun así no pasa nada. ¿A qué se debe?
Casi siempre a que falta /etc/apt/apt.conf.d/20auto-upgrades. Instalar el paquete por sí solo no activa nada, eso lo hace únicamente ese archivo con APT::Periodic::Update-Package-Lists "1" y APT::Periodic::Unattended-Upgrade "1". En Debian no se crea si la instalación no se ejecutó de forma interactiva, por ejemplo al construir una imagen. Puedes recuperarlo con dpkg-reconfigure -plow unattended-upgrades. Y lo compruebas con apt-config dump APT::Periodic: si no aparece ninguna salida, no se ha leído ningún archivo.
¿A qué hora se ejecuta la actualización?
Lo controla apt-daily-upgrade.timer. Por defecto está OnCalendar=*-*-* 6:00 junto con RandomizedDelaySec=60m, así que la ejecución cae en algún momento entre las seis y las siete. En apt-daily.timer, que es el que recoge las listas de paquetes, la dispersión es de doce horas. Puedes moverlo con systemctl edit apt-daily-upgrade.timer, teniendo en cuenta que delante de tu propio valor tiene que ir una línea vacía OnCalendar=, porque si no el temporizador se ejecuta dos veces al día.
He puesto Automatic-Reboot en true y mi servidor Debian no se reinicia nunca. ¿Por qué?
Porque el reinicio no lo dispara el paquete del kernel, sino el archivo de marca /var/run/reboot-required. Ubuntu lo crea, ahí viene del paquete update-notifier-common, y /var/run/reboot-required.pkgs nombra incluso los paquetes responsables. Debian no lo crea de forma estándar, así que ahí la opción se queda sin efecto sin que nada dé un error. En Debian compruebas la necesidad con needrestart -b y comparas NEEDRESTART-KCUR con NEEDRESTART-KEXP.
¿Debería activar el reinicio automático en un servidor de juegos?
Mejor no. En un servidor de juegos hay jugadores conectados, el mundo está en la RAM y la partida no se escribe entera hasta que el proceso termina de forma ordenada. Si el proceso se corta en duro al agotarse el plazo de parada de systemd, pierdes lo avanzado desde el último guardado intermedio o el archivo del mundo se queda dañado. Lo sensato es Automatic-Reboot "false", una ventana de mantenimiento anunciada y una unit de systemd con un comando de parada que guarde y con un TimeoutStopSec suficiente.
¿Cómo excluyo un solo paquete de las actualizaciones automáticas?
Hay dos caminos con alcance distinto. Unattended-Upgrade::Package-Blacklist actúa solo sobre el automatismo; las entradas son expresiones regulares ancladas al principio del nombre del paquete, por eso "nginx" alcanza también a nginx-common y a nginx-full, mientras que "nginx$" se refiere solo a ese nombre. apt-mark hold, en cambio, actúa sobre cualquier llamada a apt, también sobre tu apt upgrade manual. Conviene que apuntes las dos cosas: un paquete excluido tienes que actualizarlo tú.
En el log pone "No packages found that can be upgraded unattended" aunque apt muestra actualizaciones. ¿Es un fallo?
No, es el filtro haciendo su trabajo. Un paquete que aparece en apt list --upgradable y falta en la ejecución en seco viene de una fuente no permitida, está en la lista de excepciones, está retenido con apt-mark hold o provocaría una pregunta sobre un archivo de configuración. El último caso se reconoce en el log por la línea "has conffile prompt and needs to be upgraded manually" y afecta al paquete de forma permanente, hasta que lo actualizas a mano.
¿Por qué systemctl status unattended-upgrades muestra permanentemente "active (running)"?
Eso no es una actualización en marcha. Esa unit tiene la tarea de cerrar de forma limpia durante el apagado una ejecución ya empezada, y el resto del tiempo espera. La instalación ocurre en apt-daily-upgrade.service, que solo se ejecuta unos pocos minutos al día. Lo que de verdad ha pasado lo lees en /var/log/unattended-upgrades/unattended-upgrades.log y en /var/log/apt/history.log.

unattended-upgrades Actualizaciones de seguridad apt Debian Ubuntu Seguridad de servidores systemd Servidor root