Debian 13: actualización APT fallida — revertir un paquete sin derrumbe en cadena

¿Te fue útil?

Actualizaste una máquina Debian 13, un paquete salió mal y ahora el sistema parece estar protagonizando una tragedia: servicios que se reinician, errores de símbolos extraños, quizá incluso una unidad que no arranca si tuviste mala suerte. No quieres un rollback completo. Quieres que un paquete vuelva a su estado anterior. Tampoco quieres que APT “ayude” degradando la mitad de tu pila, porque ya viste esa película y el final siempre toma horas extra.

Este es el método de grado producción: identificar exactamente qué cambió, elegir la versión correcta, degradarla con impacto controlado en las dependencias y luego fijarla/retenerla hasta que estés listo. En el camino hablaremos de snapshots, aristas de dependencias y por qué “simplemente apt install el .deb viejo” es la manera de convertirte en una advertencia.

Reglas básicas: qué significa realmente “revertir un paquete” en Debian

Debian no tiene un botón integrado de “rollback de paquete” porque APT no es una máquina del tiempo; es un solucionador de dependencias. Revertir un único paquete es posible, pero estás negociando con relaciones:

  • Dependencias: el paquete que quieres puede requerir una biblioteca más nueva de la que esperaba la versión antigua, o al revés.
  • Compatibilidad ABI: las bibliotecas y componentes que interactúan con el kernel tienen promesas de compatibilidad… hasta que no las tienen, o tu aplicación usa un caso límite.
  • Estado del repositorio: la versión que quieres debe estar disponible desde una fuente configurada o en la caché local.
  • Política: APT elegirá “el mejor” candidato según pins, origen, prioridad y suite. Si no estableces política, obtendrás intuiciones aleatorias.

El objetivo no es “forzar la instalación de un .deb viejo”. El objetivo es: degradar un paquete a una versión conocida buena, evitando una cascada incontrolada de degradaciones o eliminaciones.

Segundo objetivo: hacer que el sistema se explique a sí mismo. Si no puedes predecir lo que APT hará, no estás revirtiendo, estás apostando.

Broma #1: APT es como un becario muy confiado: rápido, servicial y absolutamente capaz de reorganizar toda tu casa para encontrar la grapadora.

Guía de diagnóstico rápido

Cuando estás bajo presión, no empieces con “intenta degradaciones al azar”. Comienza con las comprobaciones mínimas que revelan la forma de las dependencias y el empaquetado del incidente.

Primero: identifica qué cambió y qué está roto ahora

  • ¿Qué versión del paquete está instalada ahora?
  • ¿Qué versión estaba instalada antes?
  • ¿Qué servicio o binario falla y por qué (símbolos, configuración, permisos, ABI)?
  • ¿Está dpkg en un estado medio configurado?

Segundo: determina si el rollback es factible sin reacción en cadena

  • ¿Depende el paquete objetivo de bibliotecas que ahora son más nuevas de lo que la versión antigua espera?
  • ¿Forzará su degradación la degradación de bibliotecas que otras aplicaciones necesitan?
  • ¿Sigue estando disponible la versión antigua en tus repos configurados o en la caché?

Tercero: aplica un rollback controlado

  • Simula con APT e inspecciona los cambios propuestos.
  • Degrada con selección explícita de versión.
  • Pin/hold para evitar que se vuelva a actualizar.
  • Ejecuta una verificación mínima: estado del servicio, logs y una consulta de sanidad.

Cuarto: evitar recurrencias

  • Snapshot antes de las actualizaciones (sistema de archivos o snapshot de VM).
  • Realiza actualizaciones por fases (un host canario primero).
  • Registra las diferencias de versión en control de cambios, no en la memoria de alguien.

Hechos y contexto que hacen menos misterioso el comportamiento de APT

Esto no son respuestas para la noche de trivial. Son el modelo mental que necesitas cuando APT empieza a sugerir “eliminar 37 paquetes” y lo llama una característica.

  1. APT es un resolvedor, dpkg es el instalador. APT decide lo que debe pasar; dpkg ejecuta, rastrea el estado y puede quedarse a medias si algo interrumpe.
  2. “Depends” es estricto, “Recommends” es (mayormente) opcional. Debian históricamente trató Recommends como opcional; luego APT por defecto los instaló, lo que sorprende a quienes aprendieron Debian en eras anteriores.
  3. Las dependencias versionadas son comunes en las pilas centrales. Las bibliotecas suelen requerir “>= x.y” y a veces “<< x.z” (raro, pero picante). Esas restricciones dictan hasta dónde puedes retroceder.
  4. Las prioridades de pin controlan la selección de candidatos. No es magia: los pins crean un orden parcial; APT elige la versión con mayor prioridad que cumpla dependencias.
  5. “stable” de Debian es conservador; “testing” avanza. Si tu sistema Debian 13 tira de suites mixtas o repos de terceros, en la práctica estás ejecutando una distribución personalizada.
  6. Las degradaciones están soportadas, pero no son sin fricción. APT las hará, pero muchos mantenedores prueban principalmente actualizaciones hacia adelante. Estás nadando corriente arriba.
  7. Los scripts de mantenedor pueden cambiar el estado fuera de archivos. postinst puede habilitar servicios, crear usuarios, migrar datos o reescribir configuraciones. Revertir un paquete no siempre revierte esos efectos colaterales.
  8. “apt-get” vs “apt” no es solo sensaciones. El comando más nuevo apt es más amigable para humanos; apt-get es estable para scripts. En un incidente, prefiere la previsibilidad.
  9. Debian tiene multiarch desde hace años. Un mismo nombre de paquete puede tener múltiples arquitecturas instaladas (como :amd64 y :i386), y eso puede complicar los rollbacks de “un paquete”.

Las 12+ tareas prácticas: comandos, salidas y decisiones

Cada tarea incluye: un comando ejecutable, salida de ejemplo, lo que significa y la decisión que tomas a partir de ello. No necesitarás todas, pero debes saber cuál responde a cada pregunta.

Task 1: Confirm dpkg isn’t half-configured

cr0x@server:~$ sudo dpkg --audit
The following packages are only half configured, probably due to problems configuring them the first time.
 libssl3:amd64

Qué significa: Tu sistema no está en un estado de paquetes limpio. Revertir mientras dpkg está a medias es la forma de obtener “funciona en mi terminal” seguido de un reinicio lleno de remordimientos.

Decisión: Arregla el estado de dpkg primero: ejecuta sudo dpkg --configure -a y resuelve errores antes de intentar degradaciones.

Task 2: Get the installed version and the candidate version

cr0x@server:~$ apt-cache policy libssl3
libssl3:
  Installed: 3.3.1-1
  Candidate: 3.3.2-1
  Version table:
     3.3.2-1 500
        500 http://deb.debian.org/debian trixie/main amd64 Packages
 *** 3.3.1-1 100
        100 /var/lib/dpkg/status

Qué significa: Installed difiere de Candidate. Puedes degradar/actualizar según lo disponible. La Version table muestra de dónde provienen las versiones y sus prioridades de pin.

Decisión: Si la versión que quieres no aparece, tendrás que añadir un repositorio que la provea o buscarla en la caché local.

Task 3: Find what upgraded recently (APT history)

cr0x@server:~$ sudo zgrep -h "Start-Date\|Upgrade:" /var/log/apt/history.log*
Start-Date: 2025-12-29  02:13:41
Upgrade: nginx:amd64 (1.26.1-2, 1.26.2-1), nginx-common:amd64 (1.26.1-2, 1.26.2-1)
End-Date: 2025-12-29  02:14:12

Qué significa: Esto te dice qué cambió realmente, no lo que crees que cambió.

Decisión: Si el paquete problemático está en esa lista, el rollback es una hipótesis válida. Si no, podrías estar persiguiendo lo incorrecto (por ejemplo, una actualización de biblioteca).

Task 4: Check dpkg logs for maintainer script failures

cr0x@server:~$ sudo grep -E "install |upgrade |configure " /var/log/dpkg.log | tail -n 8
2025-12-29 02:13:45 upgrade nginx:amd64 1.26.1-2 1.26.2-1
2025-12-29 02:13:46 status half-configured nginx:amd64 1.26.2-1
2025-12-29 02:13:47 status installed nginx:amd64 1.26.2-1

Qué significa: Si ves “half-configured” que nunca se resuelve, probablemente tengas un problema en postinst (sintaxis de config, permisos, fallo en recarga de systemd).

Decisión: Si un script de mantenedor falló, el rollback podría ayudar, pero arreglar la configuración puede ser más rápido y seguro que degradar.

Task 5: Inspect why a package is installed and who depends on it

cr0x@server:~$ apt-cache rdepends --installed nginx | head -n 12
nginx
Reverse Depends:
  nginx-extras
  nginx-full
  myapp-web

Qué significa: Revertir nginx afectará a cualquier cosa que dependa de él.

Decisión: Si un paquete interno crítico depende de una versión mínima de nginx, revertir nginx puede forzar también la reversión de ese paquete. Decide si es aceptable.

Task 6: Show dependency constraints (the ones that bite)

cr0x@server:~$ apt-cache show nginx | sed -n '1,80p'
Package: nginx
Version: 1.26.2-1
Depends: nginx-common (= 1.26.2-1), libc6 (>= 2.38), libpcre2-8-0 (>= 10.34)

Qué significa: Dependencias bloqueadas por versión ((= 1.26.2-1)) significan que no puedes revertir nginx solo; debes revertir también el paquete emparejado.

Decisión: Planifica el rollback al nivel del “conjunto de paquetes fuente” cuando veas dependencias de igualdad estricta.

Task 7: Check what versions are available for downgrade

cr0x@server:~$ apt list -a nginx 2>/dev/null | sed -n '1,6p'
nginx/trixie 1.26.2-1 amd64
nginx/trixie 1.26.1-2 amd64

Qué significa: El repositorio ofrece ambas versiones. Bien: puedes pedirle a APT una versión exacta sin buscar .debs.

Decisión: Si la versión deseada falta, detente y arregla el problema de disponibilidad primero (suite del repositorio, snapshot o caché).

Task 8: Dry-run the downgrade and inspect the blast radius

cr0x@server:~$ sudo apt-get -s install nginx=1.26.1-2 nginx-common=1.26.1-2
Reading package lists... Done
Building dependency tree... Done
The following packages will be DOWNGRADED:
  nginx nginx-common
0 upgraded, 0 newly installed, 2 downgraded, 0 to remove and 0 not upgraded.
Inst nginx [1.26.2-1] (1.26.1-2 Debian:13.0/trixie [amd64])
Inst nginx-common [1.26.2-1] (1.26.1-2 Debian:13.0/trixie [amd64])

Qué significa: Resultado perfecto: solo los paquetes objetivo se degradan. Sin eliminaciones, sin degradaciones sorpresa de bibliotecas.

Decisión: Procede si la simulación es limitada. Si APT quiere eliminar paquetes o degradar librerías centrales, no procedas sin un plan (pinning, versión alternativa o rollback por snapshot).

Task 9: Execute the downgrade with explicit versions

cr0x@server:~$ sudo apt-get install nginx=1.26.1-2 nginx-common=1.26.1-2
Reading package lists... Done
Building dependency tree... Done
The following packages will be DOWNGRADED:
  nginx nginx-common
Need to get 0 B/1,233 kB of archives.
After this operation, 0 B of additional disk space will be used.
Do you want to continue? [Y/n] y
dpkg: warning: downgrading nginx:amd64 from 1.26.2-1 to 1.26.1-2

Qué significa: Dpkg está degradando; este comportamiento está soportado.

Decisión: Vigila errores de scripts de mantenedor. Si ocurren, captura logs inmediatamente y decide si arreglar la configuración, volver a ejecutar la configuración o revertir con snapshots.

Task 10: Verify the service and surface errors quickly

cr0x@server:~$ systemctl status nginx --no-pager -l
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-12-29 02:21:06 UTC; 12s ago
       Docs: man:nginx(8)

Qué significa: El servicio está arriba. No te quedes ahí: el estado no es corrección, solo es un pulso.

Decisión: Si no está activo, inspecciona los logs del journal a continuación.

Task 11: Read the journal for the package’s failure mode

cr0x@server:~$ sudo journalctl -u nginx -b --no-pager -n 30
Dec 29 02:20:58 server nginx[1422]: nginx: [emerg] unknown directive "http2_push_preload" in /etc/nginx/conf.d/site.conf:12
Dec 29 02:20:58 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE

Qué significa: Esto no es un problema binario/ABI. Es una discrepancia de configuración en directivas. Revertir podría “arreglarlo”, pero la solución real es reconciliar la configuración con la sintaxis soportada.

Decisión: Decide si revertir la configuración o ajustar la configuración para la nueva versión. Degradar un servidor web para acomodar configuración obsoleta suele ser la colina equivocada para morir.

Task 12: Verify shared library / symbol errors (classic post-upgrade pain)

cr0x@server:~$ /usr/bin/myapp-web
/usr/bin/myapp-web: symbol lookup error: /lib/x86_64-linux-gnu/libssl.so.3: undefined symbol: EVP_MD_get_type

Qué significa: Mismatch de ABI. Tu binario espera un símbolo que no está presente en la versión de la biblioteca instalada actualmente (o viceversa).

Decisión: Identifica qué paquete provee la biblioteca y elige un par de versiones compatibles (o recompila la app). Revertir solo el paquete de la aplicación puede no ayudar si la biblioteca cambió.

Task 13: Map a file to its owning package (when you only know the broken .so)

cr0x@server:~$ dpkg -S /lib/x86_64-linux-gnu/libssl.so.3
libssl3:amd64: /lib/x86_64-linux-gnu/libssl.so.3

Qué significa: El símbolo roto está en libssl3. Ese es el objetivo de rollback, o la app necesita ser recompilada contra el nuevo ABI.

Decisión: Revisa las versiones disponibles de libssl3 y quién depende de ella antes de degradar una biblioteca central de criptografía.

Task 14: Inspect who depends on a core library before touching it

cr0x@server:~$ apt-cache rdepends --installed libssl3 | head -n 20
libssl3
Reverse Depends:
  openssh-client
  curl
  nginx
  myapp-web

Qué significa: Degradar libssl3 podría afectar múltiples paquetes críticos. Aquí es donde “revertir un paquete” se convierte en “cambiar la base”.

Decisión: Si la lista de reverse-dep incluye herramientas centrales sensibles (ssh, curl), prefiere recompilar la app o aislarla en contenedor en vez de degradar la biblioteca del sistema.

Task 15: Find cached .debs already on the box (when repos moved on)

cr0x@server:~$ ls -1 /var/cache/apt/archives | grep -E '^nginx_'
nginx_1.26.1-2_amd64.deb
nginx_1.26.2-1_amd64.deb

Qué significa: Puede que tengas el .deb exacto que necesitas sin cambiar repositorios. Útil para rollback rápido durante un incidente.

Decisión: Si instalas desde caché, aún prefiere APT con versión explícita para mantener la coherencia de dependencias.

Task 16: See what APT would remove if you attempt a downgrade (red flag)

cr0x@server:~$ sudo apt-get -s install libssl3=3.3.0-2
Reading package lists... Done
Building dependency tree... Done
The following packages have unmet dependencies:
 openssh-client : Depends: libssl3 (>= 3.3.1-1) but 3.3.0-2 is to be installed
E: Unable to correct problems, you have held broken packages.

Qué significa: La degradación es incompatible con otros paquetes instalados. APT se niega, lo cual es un regalo.

Decisión: No lo fuerces con dpkg. O bien reviertes también los paquetes dependientes (si es aceptable), o eliges otra estrategia (recompilar la app, contenedor o rollback por snapshot).

Elegir el objetivo del rollback: versión, origen y alcance

Revertir “el paquete que se rompió” suele ser incorrecto porque la rotura visible es solo el primer dominó. La causa real típicamente es una de estas:

  • Cambio de ABI en bibliotecas (openssl, libc, zlib, libstdc++): obtienes errores de búsqueda de símbolos o caídas.
  • Cambio en el esquema de configuración (nginx, unidades systemd, configuraciones de bases de datos): el servicio no arrancará, los logs indican directivas desconocidas o valores inválidos.
  • Cambio de comportamiento en herramientas (empaquetado Python, herramientas Node, cambios por defecto en openssh): tus scripts fallan silenciosamente o se comportan distinto.
  • Desajuste interfaz kernel/userspace (drivers, herramientas eBPF): particularmente con módulos fuera del árbol o agentes de proveedores.

Decide: ¿reviertes la app, la biblioteca o ambas?

Mi sesgo: revertir la aplicación antes de tocar el plumbing del SO. Degradar paquetes de aplicación tiende a ser localizado. Degradar bibliotecas de criptografía y libc es cómo expandes el incidente a “por qué no podemos sshear más”.

Pero a veces la app está bien y la regresión está en la biblioteca. Entonces tienes tres opciones prácticas:

  1. Avanzar con la actualización (preferido cuando existe una versión fija). Si el bug está en 1.2.3 y 1.2.4 lo corrige, el rollback es una distracción.
  2. Recompilar la app contra el nuevo ABI si controlas el build. Esto evita degradaciones del sistema.
  3. Degradar la biblioteca solo si (a) el repositorio ofrece un conjunto compatible y (b) las dependencias inversas lo toleran.

Decide: ¿qué repositorio “posee” la versión que quieres?

En el mundo Debian, tus versiones disponibles dependen de tus fuentes configuradas y sus prioridades. Mezclar suites (stable/testing/unstable) es posible, pero es como mezclar combustibles con un encogimiento de hombros.

Usa apt-cache policy y apt list -a para ver lo que está realmente disponible. Si la versión no está disponible, no puedes degradar limpiamente con APT sin cambiar tus fuentes o usar paquetes en caché.

Degradar de forma segura: minimizar la zona afectada

Este es el flujo de trabajo que te mantiene fuera del infierno de dependencias:

  1. Simula la degradación con apt-get -s.
  2. Inspecciona la lista de acciones: paquetes degradados, paquetes eliminados, paquetes nuevos instalados.
  3. Degrada con versiones explícitas para el conjunto de paquetes (a menudo incluye -common o -data).
  4. Inmediatamente pin/hold los paquetes para evitar que APT los “arregle” en la siguiente actualización.
  5. Verifica el comportamiento en tiempo de ejecución: servicio, logs y una petición/consulta real.

Simula en serio

La simulación no es opcional. En producción, no “pruebas” operaciones de paquetes. Las predices.

Si APT quiere eliminar paquetes, lee la lista cuidadosamente. La eliminación puede ser racional (conflictos), pero también es cómo terminas quitando tu agente de monitorización y luego pasas dos horas “debuggeando un problema de rendimiento” sin gráficas.

Sabe cuándo detenerte y usar un snapshot

Si el rollback requiere degradar componentes centrales como libc6, systemd, openssl o el kernel, ya no estás haciendo un “rollback de un paquete”. Estás haciendo un retroceso parcial de la distribución. Ahí es donde los snapshots de sistema de archivos/VM brillan: restauran un estado coherente del sistema.

Broma #2: El rollback más rápido es el snapshot que hiciste ayer. El segundo más rápido es el que puedes explicar a tu yo futuro sin llorar.

Pinning y hold: evitar que APT “arregle” tu arreglo

Degradar es el paso uno. Mantenerlo degradado es el paso dos. El paso dos es donde la gente falla silenciosamente y luego se sorprende en la siguiente ventana de actualizaciones desatendidas.

Usa un hold para contención inmediata

Un hold es contundente, rápido y reversible. Evita actualizaciones de ese paquete.

cr0x@server:~$ sudo apt-mark hold nginx nginx-common
nginx set on hold.
nginx-common set on hold.

Significado: Estos paquetes no se actualizarán hasta que los quites del hold.

Decisión: Usa holds para contención de incidentes. Luego implementa pinning si necesitas una política de más duración.

Usa APT pinning cuando necesites política, no un parche

El pinning es mejor cuando manejas repositorios mixtos o cuando quieres permitir actualizaciones en general pero forzar que un paquete específico se mantenga en una versión elegida.

Crea un archivo de preferences, por ejemplo:

cr0x@server:~$ sudo tee /etc/apt/preferences.d/nginx-rollback.pref >/dev/null <<'EOF'
Package: nginx nginx-common
Pin: version 1.26.1-2
Pin-Priority: 1001
EOF

Significado: Prioridad > 1000 le indica a APT que puede seleccionar esa versión incluso si es una degradación.

Decisión: Usa pins de alta prioridad con moderación. Estás sobreescribiendo al resolvedor; hazlo con un comentario en control de cambios y un recordatorio para quitarlo después.

Confirma que el pin está activo

cr0x@server:~$ apt-cache policy nginx | sed -n '1,12p'
nginx:
  Installed: 1.26.1-2
  Candidate: 1.26.1-2
  Version table:
     1.26.2-1 500
        500 http://deb.debian.org/debian trixie/main amd64 Packages
 *** 1.26.1-2 1001
        500 http://deb.debian.org/debian trixie/main amd64 Packages
        100 /var/lib/dpkg/status

Significado: Candidate coincide con tu versión pineada. Eso es lo que quieres.

Decisión: Si Candidate sigue siendo la versión más nueva, tu archivo de preferencias está mal (nombre de paquete incorrecto, cadena de versión equivocada o otra prioridad de pin lo supera).

Tres mini-historias corporativas desde la trinchera

1) Incidente causado por una suposición equivocada: “Es solo el paquete de la app”

El equipo ejecutaba un conglomerado de nodos web Debian con un pequeño servicio Go delante de un proxy que terminaba TLS. Tras una actualización rutinaria, las comprobaciones de salud empezaron a fallar en algunos hosts y luego más. El error al que todos se aferraron estaba en los logs de la app: fallos en el handshake TLS. Así que la suposición se formó rápidamente: “la actualización de la app rompió TLS”.

Alguien revirtió el paquete de la app en dos hosts. Sin cambio. Alguien más revirtió el proxy. Sigue roto. El comandante del incidente empezó a empujar rollbacks más amplios, uno a uno, porque los sistemas seguían accesibles y el panel de negocio no. La ventana de actualización se convirtió en una ruleta.

La causa real fue un desajuste de bibliotecas introducido por una actualización parcial: un host se reinició a mitad de la actualización (evento de energía en una fila de rack), dejando dpkg en estado inconsistente. Algunos nodos tenían la nueva biblioteca de criptografía y un paquete dependiente antiguo; otros tenían lo contrario. El proxy estaba bien, la app estaba bien. La alineación ABI no lo estaba.

Cuando finalmente miraron dpkg --audit y el log de dpkg, fue obvio. La solución no fue “revertir la app”. Fue “finalizar la actualización limpiamente” en los nodos medio actualizados y luego reiniciar servicios. La lección fue dura: el mensaje de error apuntaba a TLS, pero el modo de fallo era el estado del empaquetado.

Después añadieron una regla: ninguna implementación automatizada procede a menos que dpkg esté limpio y la última transacción APT haya terminado. Fue aburrido. También evitó una repetición.

2) Optimización que salió mal: “Aceleremos actualizaciones mezclando suites”

Un grupo de plataforma quería funciones más nuevas en un componente —pongamos un proxy inverso o un driver de base de datos— sin esperar el ritmo de stable. Hicieron lo que mucha gente inteligente hace bajo presión: añadieron la suite testing a sources.list y la pinaron “baja”. La intención era escoger paquetes puntualmente. La realidad fue que los grafos de dependencia no respetan la intención.

Funcionó durante meses. Luego una actualización rutinaria jaló una biblioteca más nueva desde testing porque tenía mayor prioridad de pin de lo esperado para el origen de ese paquete (una regla sutil de preferencia). El proxy se actualizó, sus módulos arrastraron una dependencia de biblioteca más estricta y de repente varios otros paquetes fueron elegibles para actualización. APT hizo su trabajo: encontró una solución consistente. La solución simplemente no era consistente con la seguridad operativa.

Dos semanas después, intentaron revertir “el paquete que actualizamos desde testing”. APT propuso degradar la biblioteca, lo que implicaba degradar otros paquetes que ya esperaban la versión más nueva. El rollback se convirtió en un tira y afloja entre suites. Cada “arreglo” hacía la siguiente actualización más difícil.

La reparación eventual no fue heroica. Eliminó la suite mixta, volvió a una sola suite más backports controlados y usó pins explícitos con fecha de expiración (sí, literalmente un ticket recordando quitar el pin). La mejora fue real: las actualizaciones volvieron a ser previsibles. La “optimización” había cambiado velocidad a corto plazo por inestabilidad a largo plazo.

3) Práctica aburrida pero correcta que salvó el día: snapshots y un host canario

Un sistema vinculado a finanzas tenía demandas estrictas de uptime y control de cambios rígido. El equipo no era llamativo. Eran cuidadosos. Antes de cualquier actualización, su proceso era: snapshot, actualizar un canario, ejecutar pruebas de humo y luego proceder. Todos se burlaban del papeleo hasta el día en que importó.

Una actualización a Debian 13 introdujo una regresión en un paquete usado para generar PDFs. El servicio arrancó, pero la salida era sutilmente incorrecta para ciertas fuentes. Si piensas “a quién le importa”, los auditores sí. El canario lo detectó porque la prueba de humo incluyó generar un documento representativo y hashearlo. No una prueba unitaria; una prueba del mundo real.

En lugar de entrar en pánico, fijaron esa versión del paquete, revirtieron solo ese paquete en el canario, confirmaron la corrección de la salida y luego aplicaron el mismo rollback a los nodos de producción. Sin cascada. Sin eliminaciones aleatorias. Sin drama.

Mientras tanto, abrieron un issue interno para evaluar la versión nueva y decidir si parchear la configuración o esperar una compilación fija. El snapshot nunca necesitó ser restaurado, pero saber que existía cambió por completo la postura ante el incidente. La calma vence a la astucia.

Errores comunes: síntomas → causa raíz → solución

Esta sección es donde los incidentes dejan de repetirse. Trátala como una lista de comprobación de trampas.

1) “APT quiere eliminar la mitad del sistema”

Síntomas: Al intentar una degradación, APT propone eliminar grandes porciones (entorno de escritorio, pila Python, base de datos).

Causa raíz: Estás intentando instalar una versión que entra en conflicto con el conjunto de dependencias actualmente instalado; a menudo causado por suites mixtas, repos de terceros o dependencias bloqueadas por versión.

Solución: Para. Simula e inspecciona. Pinea la versión específica que quieres y asegúrate de que el conjunto de dependencias correspondiente exista en la misma suite del repositorio. Si están involucradas librerías centrales, prefiere rollback por snapshot o actualización hacia adelante.

2) “Dependencias incumplidas, paquetes retenidos rotos”

Síntomas: APT falla con dependencias incumplidas; dpkg no puede corregir problemas.

Causa raíz: Tienes una actualización parcial, pins rotos o prioridades de repositorio en conflicto. A veces un paquete está en hold y bloquea la ruta de actualización/degradación requerida.

Solución: Comprueba holds con apt-mark showhold. Valida prioridades de pin con apt-cache policy. Repara el estado de dpkg con dpkg --configure -a y apt-get -f install si procede.

3) “El servicio no arranca tras la actualización; revertir lo ‘arregla’”

Síntomas: La unidad systemd falla; los logs muestran directiva desconocida u opción de configuración inválida.

Causa raíz: Deriva de configuración. Tu config depende de un comportamiento eliminado o cambiado en la nueva versión. Revertir restaura el parser antiguo, no la corrección.

Solución: Actualiza la configuración para que sea compatible con la versión actual, o gestiona configuraciones versionadas explícitamente. Usa journalctl para identificar la línea y la directiva exacta. Revertir solo como medida temporal de contención.

4) “Error de búsqueda de símbolos”

Síntomas: Ejecutables fallan con errores de símbolo indefinido en bibliotecas compartidas.

Causa raíz: Desajuste de ABI entre binario y bibliotecas; común con binarios compilados localmente o agentes proporcionados por proveedores.

Solución: Prefiere recompilar/reinstalar el binario para la nueva biblioteca. Si debes degradar una biblioteca, verifica dependencias inversas y evita degradar herramientas centrales de seguridad.

5) “La degradación tuvo éxito, pero la próxima actualización lo rompe otra vez”

Síntomas: Todo funciona después de la degradación, luego las actualizaciones desatendidas devuelven la versión mala.

Causa raíz: No se aplicó hold o pin; APT sigue considerando la versión más nueva como candidata.

Solución: Usa apt-mark hold para contención inmediata, luego implementa pinning con /etc/apt/preferences.d/ para control más duradero.

6) “dpkg bloqueado, actualizaciones atascadas”

Síntomas: APT dice que el lock está tomado; las operaciones fallan.

Causa raíz: Otro proceso apt/dpkg está en ejecución (unattended-upgrades, apt-daily), o un proceso anterior falló dejando el lock pero el estado dpkg aún está en curso.

Solución: Comprueba procesos en ejecución, no borres archivos de lock a la ligera. Detén timers si es necesario y luego repara el estado de dpkg.

Listas de verificación / plan paso a paso

Checklist A: Contener el incidente (5–15 minutos)

  1. Confirma qué está roto (¿servicio caído? ¿error de binario? ¿salida incorrecta?).
  2. Comprueba el estado de dpkg (dpkg --audit). Repara si es necesario.
  3. Identifica qué cambió (apt history, tail del log de dpkg).
  4. Decide si el rollback es apropiado (problema de config vs problema de ABI vs regresión genuina).
  5. Simula la degradación para medir la zona afectada (apt-get -s install pkg=ver).

Checklist B: Revertir un paquete sin daños colaterales

  1. Lista versiones disponibles: apt list -a package.
  2. Comprueba dependencias: apt-cache show package.
  3. Comprueba dependencias inversas: apt-cache rdepends --installed package.
  4. Simula la degradación con versiones explícitas para todos los paquetes fuertemente acoplados (a menudo -common, -data).
  5. Ejecuta la degradación con versiones explícitas.
  6. Hold o pin inmediatamente.
  7. Verifica servicio y logs.

Checklist C: Prevenir el siguiente colapso en cadena

  1. Elimina suites mixtas a menos que tengas una política explícita para ellas.
  2. Usa upgrades canario y pruebas de humo que reflejen cargas reales.
  3. Snapshot antes de upgrades (VM, LVM, btrfs, ZFS—lo que tengas).
  4. Registra pins y holds como medidas temporales con responsables y fechas de expiración.

Preguntas frecuentes

1) ¿Puedo degradar un paquete con dpkg directamente?

Puedes, pero usualmente no deberías. Dpkg no resuelve dependencias. Si instalas un .deb viejo que entra en conflicto con dependencias instaladas, crearás un estado de sistema roto que APT luego tendrá que desenredar. Prefiere apt-get install pkg=version para mantener la resolución de dependencias coherente.

2) ¿Por qué APT quiere degradar muchos otros paquetes?

Porque la versión solicitada cambia las restricciones de dependencias. Si la versión antigua requiere librerías antiguas o entra en conflicto con las nuevas, APT intenta encontrar un conjunto consistente. El solucionador está haciendo su trabajo; le estás pidiendo resolver un problema más difícil de lo que pretendías. Esa es tu señal para simular, inspeccionar y quizá cambiar de estrategia.

3) ¿Cuál es la diferencia entre hold y pin?

Un hold bloquea cambios a un paquete (actualización/degradación) a menos que explícitamente lo deshagas. El pin influye en la selección del candidato y puede ser tan quirúrgico o tan peligroso como lo hagas. Los holds son excelentes para contención rápida; los pins son para política.

4) ¿Cómo veo si un paquete está en hold?

cr0x@server:~$ apt-mark showhold
nginx
nginx-common

Si un paquete que necesitas mover está en hold, ese hold puede ser la razón por la que APT dice “held broken packages”. Des-házlo con deliberación, no impulsivamente.

5) ¿Qué pasa si la versión antigua ya no está en mis repositorios?

Primero comprueba /var/cache/apt/archives. Si no está ahí, necesitas un repositorio que provea la versión (por ejemplo, un mirror interno controlado o un servicio de snapshots). Evita .debs aleatorios de Internet; la cadena de integridad y el cierre de dependencias importan.

6) ¿Es seguro revertir bibliotecas como libssl o libc?

A veces, pero rara vez es la mejor primera opción. Esas bibliotecas tienen muchas dependencias y son sensibles desde el punto de vista de seguridad. Si una sola app se rompe por una actualización de biblioteca, preferible recompilar esa app o aislarla (contenedor, chroot) en vez de degradar la criptografía del sistema o libc.

7) ¿Cómo sé qué paquete provee un objeto compartido que falla?

Usa dpkg -S /path/to/file. Eso mapea un archivo al paquete que lo contiene. Luego puedes inspeccionar versiones y decidir si el paquete de la biblioteca es tu verdadero objetivo de rollback.

8) ¿Y si la falla se debe a un cambio de configuración y no al binario?

Entonces el rollback es una muleta temporal. Arregla la configuración para que sea compatible con la nueva versión del paquete. Usa journalctl -u service para la directiva/línea exacta. También revisa los nuevos configs por defecto en /usr/share/doc o las preguntas de conffile en /etc que pudiste haber ignorado durante la actualización.

9) ¿Debería usar apt o apt-get durante incidentes?

Yo uso apt-get para trabajo en incidentes porque su interfaz es estable y predecible, especialmente para simulaciones (-s) y repetibilidad en scripts. apt está bien, pero la amabilidad no es lo mismo que control.

10) ¿Cómo audito lo que APT cambió anoche?

Usa /var/log/apt/history.log y /var/log/dpkg.log. Te dicen lo que APT planificó y lo que dpkg realmente hizo. Si esos dos difieren, es una pista (interrupción, fallos de scripts de mantenedor o intervención manual).

Conclusión: siguientes pasos que puedes hacer hoy

Revertir un paquete en Debian 13 sin un colapso de dependencias no es magia negra. Es política, simulación y contención. Tu playbook es:

  1. Deja dpkg limpio antes de tocar cualquier otra cosa.
  2. Prueba qué cambió mediante logs, no por memoria.
  3. Simula la degradación y rechaza grandes zonas afectadas.
  4. Degrada con versiones explícitas para paquetes fuertemente acoplados.
  5. Retén/pinea inmediatamente y luego verifica con comprobaciones de carga reales.
  6. Después del incendio, elimina repos mixtos ad-hoc y adopta snapshots + canarios.

Una cita que vale la pena tener pegada en el monitor, porque es tan cierta en empaquetado como en cualquier otro sitio: La esperanza no es una estrategia. — Edsger W. Dijkstra

Si no haces nada más: comienza a tomar snapshots antes de las actualizaciones y siempre simula degradaciones. Eso por sí solo te salvará del próximo momento “APT sugirió eliminar mi stack de monitorización”, que es una forma singularmente moderna de ceguera autoinfligida.

← Anterior
Correo electrónico: Inundación de spam entrante — sobrevive al ataque sin bloquear usuarios reales
Siguiente →
Caps Lock y la rabia de las contraseñas: la tecla más pequeña con el caos más grande

Deja un comentario