SSD Nodes Learn Hosting plans →
Guías Matt ConnorPor Matt Connor · Actualizado 2026-09-05

Por qué unattended-upgrades no funciona en Debian

Debian instala unattended-upgrades desactivado. Actívalo, revisa Origins-Pattern y los temporizadores apt-daily para confirmar que aplica actualizaciones automáticamente.

Por qué unattended-upgrades no hace nada en una instalación nueva de Debian

En Debian, unattended-upgrades puede estar instalado y no ejecutar nunca ninguna actualización, porque instalar el paquete y habilitarlo son dos pasos distintos. El paquete formula una pregunta de debconf antes de configurarse, y el instalador de Debian guarda la respuesta false para esa pregunta. Ubuntu responde a la misma pregunta de otra forma. Por eso el mismo paquete parece funcionar allí y parece estar averiado aquí.

El sistema no informa de este problema. No aparece ningún error durante el arranque ni ninguna advertencia al iniciar sesión. Tampoco hay ningún archivo de registro que revisar, porque el código que escribiría ese registro nunca se ejecuta. Activarlo requiere un solo comando. El resto de esta guía cubre los cuatro aspectos que todavía pueden impedir su ejecución: desde qué repositorios puede actualizar, cuándo se activan realmente los temporizadores de systemd, cómo saber si una ejecución ha fallado y si el equipo tiene permitido reiniciarse automáticamente.

Muestre lo que el sistema tiene configurado antes de cambiar nada

dpkg -l unattended-upgrades | tail -n 1
sudo apt install -y debconf-utils
sudo debconf-show unattended-upgrades
cat /etc/apt/apt.conf.d/20auto-upgrades
apt-config dump APT::Periodic

debconf-show muestra el valor almacenado de unattended-upgrades/enable_auto_updates. Un * al principio de esa línea indica que algo estableció el valor en lugar de dejar el valor predeterminado del paquete. En una máquina instalada con el instalador de Debian, ese algo es el instalador.

cat puede mostrar cat: /etc/apt/apt.conf.d/20auto-upgrades: No such file or directory. Esto explica por sí solo la falta de actividad: sin ese archivo no hay claves periódicas, por lo que nunca se programa ninguna tarea.

apt-config dump es el comando importante. APT lee todos los archivos de /etc/apt/apt.conf.d/ en el orden de sus nombres y los combina, por lo que un valor definido en 99local sobrescribe el mismo valor de 20auto-upgrades. Leer un archivo le indica lo que contiene ese archivo. apt-config dump le indica lo que APT ejecutará realmente.

Dos claves determinan si se ejecuta algo:

  • APT::Periodic::Update-Package-Lists actualiza las listas de paquetes. Esa es la tarea que apt update realiza manualmente.
  • APT::Periodic::Unattended-Upgrade ejecuta la actualización.

Sus valores no son verdadero y falso. Son intervalos en días. "1" significa «hacerlo si no se ha hecho durante el último día», "7" significa semanalmente y "0" significa nunca. APT::Periodic::Unattended-Upgrade "0"; es una configuración válida que no ejecuta nada, indefinidamente y sin mostrar ningún error. Si el volcado muestra 0 para esa clave, o no muestra esa clave en absoluto, ya ha encontrado la causa.

Actívelo: dpkg-reconfigure o escriba las claves manualmente

sudo apt update
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

--priority=low no es opcional en este caso. La pregunta tiene una prioridad baja, por lo que, con la prioridad predeterminada, dpkg-reconfigure no muestra nada, no cambia nada y termina con el código 0. Esto parece exactamente un comando que se ejecutó correctamente. Responda afirmativamente al cuadro de diálogo. Después, el script postinst del paquete escribe /etc/apt/apt.conf.d/20auto-upgrades a partir de su respuesta.

En un equipo que se prepara mediante un script no hay ningún cuadro de diálogo al que responder. Establezca primero la respuesta:

echo 'unattended-upgrades unattended-upgrades/enable_auto_updates boolean true' \
  | sudo debconf-set-selections
sudo dpkg-reconfigure -f noninteractive unattended-upgrades
apt-config dump APT::Periodic

También puede escribir las dos claves directamente:

printf 'APT::Periodic::Update-Package-Lists "1";\nAPT::Periodic::Unattended-Upgrade "1";\n' \
  | sudo tee /etc/apt/apt.conf.d/20auto-upgrades
apt-config dump APT::Periodic

Esto funciona de inmediato, pero deja una trampa. La respuesta de debconf sigue indicando el valor anterior, por lo que el siguiente dpkg-reconfigure, o una reinstalación del paquete, vuelve a escribir el archivo a partir de debconf y deshace la modificación sin mostrar ningún mensaje. Establezca ambas cosas, o configure debconf y deje que postinst administre el archivo.

Esta es la única diferencia real respecto al otro miembro de la familia. Allí, el instalador habilita el mismo paquete automáticamente, por lo que la configuración de actualizaciones desatendidas de Ubuntu parte de un sistema que ya instala sus propios parches y dedica su tiempo a los ajustes. Todo lo que sigue se aplica a ambos.

¿Qué actualizaciones instala realmente Debian?

Habilitar el temporizador no equivale a aceptar la instalación de todo. Cada fuente de paquetes incluye metadatos de versión: un origen, una etiqueta, una suite, un nombre en clave y un sitio. unattended-upgrades consulta la versión candidata de cada paquete actualizable, lee los metadatos de la fuente de la que procedería y sólo lo instala si esa fuente coincide con una entrada de Unattended-Upgrade::Origins-Pattern. Si no hay coincidencia, no se realiza ninguna actualización. Es el comportamiento previsto.

Muestre sus patrones y, después, los metadatos con los que se comparan:

apt-config dump Unattended-Upgrade::Origins-Pattern
grep -H -E '^(Origin|Label|Suite|Codename|Components):' /var/lib/apt/lists/*Release
apt-cache policy

grep -H conserva el nombre de archivo en cada línea. Así puede ver a qué fuente pertenece cada bloque de metadatos. Los valores de esos campos son los valores del lado derecho de sus patrones. Dentro de un patrón, ${distro_codename} se sustituye en tiempo de ejecución por el nombre en clave de la versión que está usando. De este modo, un solo archivo sigue funcionando después de actualizar la versión.

Lea sus propios patrones junto a esos metadatos. La respuesta a «¿recibo sólo correcciones de seguridad o también actualizaciones de punto?» está escrita ahí y en ningún otro lugar:

  • Un patrón que nombre label=Debian-Security coincide con el archivo de seguridad. Ahí se publican los avisos de seguridad de Debian.
  • Un patrón que nombre la suite -updates coincide con stable-updates, que contiene lo que Debian publica entre versiones de punto, como los datos de zonas horarias.
  • Un patrón que nombre la suite de la versión sin más componentes incorpora los cambios de las versiones de punto cuando se publican. Esto implica más cambios y más trabajo de pruebas por su parte.
  • Un repositorio que haya añadido usted no coincide con nada hasta que escriba un patrón para él.

Esto último sorprende a muchas personas. Un repositorio de terceros tiene su propio origen y su propia etiqueta. Por tanto, unattended-upgrades ve la versión candidata, comprueba que la fuente no coincide con nada y continúa. Añadir un patrón para ese repositorio es una decisión que conviene tomar con calma, porque un repositorio de un proveedor puede publicar una versión principal nueva dentro de la misma suite. En ese caso, habrá aceptado las actualizaciones principales automáticas de ese software durante la noche.

unattended-upgrades tampoco cambia nunca de una versión de Debian a otra. Actualiza los paquetes dentro de la versión que está usando. Pasar de una versión estable a la siguiente sigue siendo una tarea manual que debe programar usted.

Cuando cambie la lista, recuerde que las listas de APT se acumulan. Un segundo bloque Origins-Pattern en otro archivo se añade a la lista proporcionada por el paquete en lugar de sustituirla. Si quiere reemplazarla, debe eliminarla primero:

#clear Unattended-Upgrade::Origins-Pattern;
Unattended-Upgrade::Origins-Pattern {
  "origin=Debian,codename=${distro_codename},label=Debian-Security";
  "origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};

Guarde los cambios locales en un archivo nuevo que se ordene después del archivo proporcionado por el paquete, por ejemplo /etc/apt/apt.conf.d/52unattended-upgrades-local. 50unattended-upgrades es un conffile, por lo que editarlo hará que cada actualización futura del paquete se detenga y pregunte qué debe hacer con su versión. Un archivo independiente nunca entra en conflicto.

Hay otras dos claves que conviene mostrar en este punto. Unattended-Upgrade::Allowed-Origins es la forma antigua de expresar la misma idea, escrita como pares origin:archive, y todavía se lee. Por eso, una configuración copiada de un tutorial suele terminar con ambas listas y sin una respuesta clara sobre cuál coincidió. Unattended-Upgrade::Package-Blacklist contiene expresiones regulares que se comparan con los nombres de los paquetes. Una expresión demasiado amplia puede bloquear muchos más paquetes de los previstos. La simulación siguiente muestra lo que se aplicó realmente.

¿Por qué no se ejecutó nada a la hora prevista?

Dos temporizadores de systemd controlan este proceso y realizan tareas diferentes. apt-daily.timer inicia apt-daily.service, que actualiza las listas de paquetes y descarga paquetes. apt-daily-upgrade.timer inicia apt-daily-upgrade.service, que es el que llama a unattended-upgrade. Ambos ejecutan /usr/lib/apt/apt.systemd.daily con argumentos diferentes. Si el segundo temporizador está deshabilitado o enmascarado, ambas claves periódicas pueden mostrar 1 y aun así no se instalará nada.

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

list-timers muestra NEXT, LEFT, LAST y PASSED para cada unidad. Un temporizador sin NEXT no se ejecutará. Que is-enabled muestre masked significa que alguien lo deshabilitó de forma forzada, y nada de lo que escriba en apt.conf.d cambiará esa situación.

Ahora lea la sección [Timer] que mostró systemctl cat. OnCalendar es el momento más temprano en que puede activarse el temporizador. RandomizedDelaySec añade una espera aleatoria a partir de ese momento, para que una flota de máquinas Debian no acceda a los mismos mirrors en el mismo segundo. Por eso la columna NEXT muestra una hora que no coincide con OnCalendar y por eso la ejecución de ayer se produjo en un minuto diferente. Es el comportamiento previsto. Persistent=true hace que una máquina apagada a la hora programada ejecute el trabajo poco después del siguiente arranque, en lugar de omitirlo ese día.

Para cambiar la ventana, cree una sobreescritura de la unidad en lugar de editarla:

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

La línea OnCalendar= vacía es necesaria porque la configuración de las unidades basada en listas se acumula: si la omite, conservará el calendario incluido con el paquete y añadirá un segundo calendario. systemctl edit vuelve a cargar systemd, así que confirme el resultado con systemctl list-timers 'apt-daily*' y compruebe el nuevo NEXT.

No es necesario esperar a que se active un temporizador para probar todo esto:

sudo systemctl start apt-daily-upgrade.service
journalctl -u apt-daily-upgrade.service --since -1h

Hay algo que confunde a quienes buscan en /etc/cron.daily: APT todavía incluye /etc/cron.daily/apt-compat para los sistemas sin systemd. Léalo con cat. En un sistema con systemd termina pronto, por lo que el trabajo no se realiza dos veces.

Compruebe que funciona: unattended-upgrade --dry-run --debug

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

El binario está en singular y el nombre del paquete, en plural. Si escribe unattended-upgrades aquí, obtiene command not found, algo que muchas personas interpretan como prueba de que falta el paquete.

Este comando responde a casi todas las preguntas sobre por qué se omitió un paquete, porque muestra su propio razonamiento. Cerca del principio, muestra los orígenes que calculó a partir de sus patrones:

Allowed origins are: ...

Después muestra una línea por cada paquete candidato, con el registro de origen de la versión que instalaría:

Checking: curl ([<Origin component:'main' archive:'stable' origin:'Debian' label:'Debian' site:'deb.debian.org' isTrusted:True>])

A continuación muestra la lista sobre la que actuaría o, en un sistema sin tareas pendientes:

No packages found that can be upgraded unattended and no pending auto-removals

Compare la primera y la segunda sección para obtener un diagnóstico directo. Busque la línea Checking: del paquete que esperaba ver actualizado. Compare campo por campo su registro de origen con los orígenes permitidos que se muestran arriba. Un campo que no coincida, normalmente label o archive, es el motivo completo por el que se omitió.

--dry-run marca los paquetes en memoria y no instala nada, así que puede ejecutarlo tantas veces como quiera. Aun así, añade información a /var/log/unattended-upgrades/unattended-upgrades.log.

Si los orígenes coinciden y un paquete sigue retenido, revise estos puntos:

  • apt-mark showhold muestra los paquetes fijados por usted o por una herramienta. unattended-upgrades no modificará un paquete retenido.
  • La actualización tendría que eliminar o añadir otro paquete. unattended-upgrades evita esa operación, salvo que las claves correspondientes la permitan. Compare con sudo apt-get -s upgrade, que muestra la misma decisión sin esas reglas de seguridad.
  • dpkg quedó parcialmente configurado después de una ejecución interrumpida. Corríjalo con sudo dpkg --configure -a y vuelva a comprobarlo.
  • /var no tiene espacio libre, por lo que no se descarga ni desempaqueta nada. Compruébelo con df -h /var.
  • /boot está lleno de kernels antiguos, lo que impide la siguiente actualización del kernel. Compruébelo con df -h /boot y muestre apt-config dump Unattended-Upgrade::Remove-Unused-Kernel-Packages para verificar si la limpieza está activada.

Si ejecuta apt manualmente mientras el temporizador está activo, obtiene Could not get lock /var/lib/dpkg/lock-frontend. Ese mensaje significa que unattended-upgrades está funcionando correctamente. Espere a que termine.

¿Cómo se comprueba cuándo falla una ejecución?

Empiece por los registros, porque existen tanto si configura otras opciones como si no:

sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.log
sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
journalctl -u apt-daily-upgrade.service --since -7d

El primer archivo es el registro de decisiones: qué se comprobó, qué se eligió y qué se instaló. El segundo contiene la salida sin procesar de dpkg. Ahí se muestra si falla el script postinst de un paquete. Si las actualizaciones se ejecutan mientras la máquina se apaga, aparece un registro de apagado independiente.

El correo es el método habitual de notificación:

Unattended-Upgrade::Mail "you@example.com";
Unattended-Upgrade::MailReport "on-change";

MailReport acepta always, on-change y only-on-error. only-on-error parece la opción más rigurosa, pero normalmente es la elección incorrecta en un servidor en el que nadie inicia sesión. Una máquina que ha dejado de actualizarse por completo tampoco envía errores. En ese caso, el silencio oculta por igual un sistema en buen estado y uno detenido. on-change envía un mensaje cada vez que se instala algo, por lo que el correo también demuestra que el temporizador sigue activo.

El correo sólo sale de la máquina si esta puede enviarlo. unattended-upgrades entrega el mensaje al sistema de correo local, por lo que necesita un MTA (agente de transferencia de correo), como postfix, o un cliente de retransmisión compatible con sendmail, como msmtp. Compruébelo con command -v sendmail y command -v mail. Si no hay ninguno de los dos, el informe no llega a ninguna parte, la actualización se completa y todo el fallo queda oculto. Tenga en cuenta también que la dirección IP nueva de un VPS no tiene reputación de envío. Por eso, el correo enviado directamente a un buzón público suele clasificarse como spam. Es más fiable retransmitirlo mediante un proveedor de correo que ya utilice que ejecutar su propio servidor para este fin.

Si prefiere no ejecutar ningún servicio de correo, supervise la marca de tiempo del registro mediante la herramienta de monitorización que utilice:

stat -c '%y %n' /var/log/unattended-upgrades/unattended-upgrades.log

Una marca de tiempo que no cambia durante una semana indica que el temporizador se detuvo, independientemente de lo que indique la configuración. Incluya esta comprobación junto con el resto de comprobaciones rutinarias de mantenimiento del servidor Linux.

¿Debe el servidor reiniciarse automáticamente?

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

Con Automatic-Reboot establecido en true, unattended-upgrades reinicia el sistema sin pedir confirmación, pero sólo cuando el archivo /var/run/reboot-required existe al terminar la ejecución. unattended-upgrades no crea ese archivo. Otro paquete debe crearlo y, en Debian, normalmente lo hace needrestart. No dé por hecho que existe. Compruébelo después de la próxima actualización del kernel:

ls -l /var/run/reboot-required /var/run/reboot-required.pkgs
uname -r
dpkg -l 'linux-image-*' | grep '^ii'

Si ese archivo nunca aparece en su equipo, Automatic-Reboot "true" nunca se ejecuta. Puede pasar meses creyendo que reinicia el sistema para aplicar las actualizaciones del kernel mientras sigue ejecutando el kernel antiguo. uname -r contra el paquete linux-image instalado más reciente lo confirma.

Automatic-Reboot-Time programa el reinicio para esa hora en lugar de ejecutarlo de inmediato. Si Automatic-Reboot-WithUsers está establecido en false, el reinicio se omite mientras haya alguien conectado. En un servidor que siempre tiene una sesión abierta, esto significa que nunca se reinicia.

La decisión depende de lo que ocurra al volver a arrancar, no del reinicio en sí. Un servicio iniciado manualmente no vuelve a iniciarse. Un volumen cifrado que necesita una frase de contraseña durante el arranque no se monta. Dos equipos que dependen entre sí pueden arrancar en el orden incorrecto. Active el reinicio automático en un servidor web sin estado cuya interrupción durante un minuto a las 02:00 sea aceptable. Déjelo desactivado cuando se necesite la intervención de una persona y configure una alerta para el archivo marcador, de modo que alguien elija el momento. Entre ambas opciones está needrestart, que reinicia los servicios que todavía utilizan una biblioteca actualizada y, por tanto, cubre todos los casos excepto el kernel. Su modo predeterminado pide confirmación antes de reiniciar, así que lea /etc/needrestart/needrestart.conf antes de utilizarlo en una ejecución desatendida.

¿Funciona igual en testing y unstable?

Todo lo anterior describe Debian stable, donde las correcciones de seguridad llegan desde un archivo independiente con su propia etiqueta. Esa estructura es la que permite expresar una configuración de «solo actualizaciones de seguridad». Las otras suites están construidas de otra forma, por lo que una configuración copiada de un servidor stable coincide menos de lo que espera su autor. Además, las actualizaciones automáticas en una suite de desarrollo implican cambios importantes de versión sin intervención. Aceptar eso es una decisión diferente. Si está valorando esa opción, usar Debian stable, testing o unstable en un servidor explica qué ofrece cada una. En el entorno de Red Hat, la misma tarea utiliza otra herramienta y otra terminología, y dnf-automatic en Rocky Linux y AlmaLinux la realiza con su propio temporizador y archivo de configuración.

Las actualizaciones automáticas reducen el intervalo entre la publicación de una corrección y su instalación. No indican qué sigue expuesto, por lo que debe combinarlas con una comprobación de CVE conocidas en el servidor. CVE significa common vulnerabilities and exposures y es el identificador público con el que se registra una corrección.

La comprobación de cinco minutos

  1. apt-config dump APT::Periodic muestra ambas claves con un valor distinto de cero.
  2. systemctl list-timers 'apt-daily*' muestra una hora de NEXT para ambos temporizadores.
  3. sudo unattended-upgrade --dry-run --debug muestra orígenes permitidos que incluyen el archivo de seguridad correspondiente a su nombre en clave.
  4. sudo systemctl start apt-daily-upgrade.service termina y la marca de tiempo de /var/log/unattended-upgrades/unattended-upgrades.log se actualiza.
  5. Una semana después, ese mismo registro incluye los paquetes que instaló.

Superar las cuatro primeras comprobaciones significa que la máquina está configurada. Superar la quinta significa que funciona.

FAQ

¿Por qué Debian instala unattended-upgrades pero lo deja desactivado?

El paquete formula una pregunta de debconf, unattended-upgrades/enable_auto_updates, y escribe /etc/apt/apt.conf.d/20auto-upgrades a partir de la respuesta. El instalador de Debian almacena false para esa pregunta, por lo que, cuando el paquete llega como parte de una tarea o como dependencia, queda configurado para no hacer nada. Ejecute sudo debconf-show unattended-upgrades para ver la respuesta almacenada y, después, sudo dpkg-reconfigure --priority=low unattended-upgrades para cambiarla. La prioridad baja es importante, porque con la prioridad predeterminada el comando termina sin mostrar la pregunta.

¿Cómo pruebo unattended-upgrades sin esperar al temporizador?

Ejecute sudo unattended-upgrade --dry-run --debug. El comando muestra los orígenes que aceptará y una línea Checking: por cada paquete actualizable, con el registro de origen de ese paquete adjunto. También muestra la lista de paquetes que instalaría, pero no instala nada. Para probar el flujo real, ejecute sudo systemctl start apt-daily-upgrade.service y, después, lea journalctl -u apt-daily-upgrade.service --since -1h junto con /var/log/unattended-upgrades/unattended-upgrades.log.

¿unattended-upgrades instala también actualizaciones normales además de correcciones de seguridad?

Sólo si un patrón lo indica. Una actualización de paquete se instala cuando el origen del que procede coincide con una entrada de Unattended-Upgrade::Origins-Pattern. El archivo de seguridad, la suite stable-updates y cualquier repositorio que haya añadido son entradas independientes. Muestre apt-config dump Unattended-Upgrade::Origins-Pattern en su propio equipo y compárelo con grep -H -E '^(Origin|Label|Suite|Codename):' /var/lib/apt/lists/*Release. Además, nunca cambia el sistema de una versión de Debian a otra.

¿Por qué la actualización no se ejecuta a la hora definida en el temporizador?

apt-daily-upgrade.timer establece RandomizedDelaySec además de OnCalendar, por lo que systemd elige un momento aleatorio dentro de esa ventana en lugar de ejecutarse a la hora indicada en el calendario. Esto distribuye la carga entre todos los equipos Debian que apuntan a los mismos mirrors. systemctl list-timers 'apt-daily*' muestra el momento que eligió realmente. Para cambiar la ventana, ejecute sudo systemctl edit apt-daily-upgrade.timer y proporciónele una línea OnCalendar= vacía seguida de su propio valor.

¿Debo activar el reinicio automático para las actualizaciones de seguridad?

Sólo cuando sea seguro reiniciar sin planificación. Unattended-Upgrade::Automatic-Reboot "true" reinicia sin confirmación cuando existe /var/run/reboot-required después de una ejecución. Ese marcador lo escribe otro paquete, normalmente needrestart, no unattended-upgrades. Confirme que el archivo aparece en su equipo después de actualizar el kernel antes de confiar en esta configuración. En un equipo que necesita una frase de contraseña durante el arranque o que ejecuta servicios iniciados manualmente por alguien, déjelo en false y genere una alerta cuando aparezca el archivo marcador, para que una persona elija el momento del reinicio.