Debian 13: El pinning de paquetes me salvó el servidor — cómo usar apt preferences sin caos

¿Te fue útil?

A las 02:13, un apt upgrade “inocente” puede convertir un servidor tranquilo en una escena del crimen de dependencias. Una librería salta de versión mayor, un kernel avanza, y de repente tu pila de almacenamiento está “funcionando como diseñado” mientras tu on-call entra en sobretiempo.

El pinning de paquetes es el movimiento de adulto que mantiene Debian predecible cuando debes mezclar fuentes: stable + security + stable-updates, además de backports y el ocasional repo de proveedor. Bien hecho, es aburrido. Mal hecho, es un FrankenDebian hecho a medida con un acompañamiento de downtime.

Qué es realmente el pinning (y qué no es)

El apt de Debian no “actualiza todo a lo más nuevo que encuentre” de forma simplista. Clasifica versiones mediante un conjunto de reglas y metadatos (orígenes, releases, prioridades) y luego intenta producir una solución consistente. El pinning es cómo anulas la clasificación por defecto.

El problema que resuelve el pinning

En producción quieres dos propiedades que se enfrentan:

  • Respuesta de seguridad: Quieres versiones parcheadas rápidamente.
  • Control de cambios: Quieres evitar nuevas versiones mayores sorpresa o nuevas cadenas de dependencias.

El pinning te permite decir “toma las actualizaciones de seguridad, pero no saltes a esa versión nueva del proveedor” o “extrae exactamente un paquete desde backports, no a toda su familia extendida”.

Lo que el pinning no es

  • No sustituye leer una actualización propuesta. Si aplicas actualizaciones a ciegas, el pinning es solo una venda más elegante.
  • No es un truco para el solucionador de dependencias. Si dos repos ofrecen pilas incompatibles, el pinning no puede negociar la paz; solo puede escoger un bando.
  • No es “hold”, aunque pueden funcionar juntos. Un hold congela un paquete por nombre. El pinning sesga la selección de versión según origen/release/versión.

Dónde vive el pinning

En Debian 13 usarás:

  • /etc/apt/preferences (archivo único legado)
  • /etc/apt/preferences.d/*.pref (la forma sensata: modular, auditable)

Prefiero preferences.d con una intención por archivo: “backports opt-in”, “repo proveedor limitado”, “no paquetes testing”, etc. Se lee como política, no como folclore.

Una frase para mantenerte honesto: “La esperanza no es una estrategia.” — idea parafraseada común en círculos de ingeniería/operaciones.

Broma #1: El pinning de paquetes es como poner barreras laterales en una bolera. Aún puedes tirar una bola a la canaleta, pero tendrás que esforzarte.

Hechos y contexto que cambian cómo haces pinning

Aquí hay datos concretos de historia y comportamiento que importan cuando diseñas una política apt. Son cortos en romance y largos en consecuencias.

  1. El pinning de APT es anterior a los contenedores. Antes del “simplemente publica tu propia imagen”, el pinning era cómo los administradores mezclaban parches de seguridad con sistemas base conservadores.
  2. “FrankenDebian” se volvió un término por una razón. Mezclar stable/testing/unstable (o repos de proveedores al azar) sin política suele producir incompatibilidades ABI silenciosas y agitación de dependencias.
  3. stable-updates existe para reducir la presión sobre las versiones puntuales. Está pensado para arreglos sensibles al tiempo que no deberían esperar al siguiente punto de versión.
  4. backports está diseñado para ser opt-in. Debian intencionalmente le da a backports una prioridad por defecto más baja para que stable siga siendo la opción por defecto.
  5. Las prioridades de pin tienen bordes afilados por diseño. Prioridades por encima de 1000 pueden forzar downgrades; por debajo de 0 pueden bloquear la instalación. Puedes dispararte en el pie con precisión matemática.
  6. Apt no solo conoce versiones; conoce orígenes. Campos de release como o= (Origin) y a= (Archive) a menudo importan más que las cadenas de versión.
  7. Los metadatos firmados del repositorio son la raíz de confianza, no el archivo de paquete. Si permites un repo, confías en su clave de firma y su índice; el pinning controla preferencia, no autenticidad.
  8. Las transiciones ocurren. Transiciones mayores de librerías (piensa en SSL, libc++, Python) se propagan por los grafos de dependencias; el pinning puede prevenir transiciones sorpresa… pero también puede bloquear actualizaciones de seguridad necesarias si eres descuidado.

El motor de decisión de apt: un modelo mental que puedes ejecutar en tu cabeza

Cuando apt elige qué instalar, esencialmente hace tres cosas:

  1. Recopila versiones candidatas de todas las fuentes configuradas (/etc/apt/sources.list, /etc/apt/sources.list.d/*.list).
  2. Asigna una Pin-Priority a cada versión usando valores por defecto + tus preferencias.
  3. Escoge la versión “mejor” instalable (mayor prioridad; si hay empate, la versión más alta), y luego resuelve dependencias.

Reglas de Pin-Priority que debes recordar

Estos son los umbrales que cambian el comportamiento. Memorízalos; son la diferencia entre política y caos.

  • > 1000: puede forzar la instalación incluso si implica downgrade.
  • 990–1000: prefiere esta versión incluso sobre las instaladas (típico para “target release”).
  • 500: prioridad normal para releases no-target.
  • 100: menor que la instalada; la versión instalada suele ganar.
  • 0: esencialmente “no instalar” (a menos que se solicite explícitamente, y aun así puede bloquearse según el emparejamiento exacto).
  • < 0: nunca instalar.

Target release: la pistola silenciosa

Si estableces APT::Default-Release a stable (o al nombre en clave de Debian 13), le estás diciendo a apt “esta release es 990.” Eso suele ser bueno. Pero también significa que cualquier otra release en 500 aún podría seleccionarse si el candidato de stable no es instalable (conflictos de dependencias) o si explícitamente pides -t.

El pinning no es solo “poner un número.” Es elegir el número más pequeño que haga el trabajo sin forzar downgrades o divergencia permanente.

Guion de diagnóstico rápido

Esto es lo que hago cuando una propuesta de actualización se ve mal o un sistema ya está derivando. Quieres señal rápida, no un debate filosófico con apt.

Primero: confirma qué cree apt que es el candidato

  • Elige un paquete problemático (a menudo el que tiene el salto de versión mayor).
  • Ejecuta apt-cache policy y mira: versión instalada, versión candidata y qué repo la suministra.

Segundo: pregunta “por qué” con una actualización simulada

  • apt -s dist-upgrade es tu detector de mentiras.
  • Mira por eliminaciones y paquetes “retenidos”. Esos son los primeros signos de alarma.

Tercero: identifica el repo que está tirando del grafo

  • apt-cache madison muestra versiones a través de repos.
  • apt-get -o Debug::pkgProblemResolver=yes -s dist-upgrade explica las elecciones de dependencias.

Cuarto: comprueba que tus reglas de pin realmente estén emparejando

  • La mayoría de fallos de pinning no son “prioridad mala”, son “sin coincidencia”. Origin equivocado. Nombre de release equivocado. Etiqueta equivocada.
  • Valida con la salida de apt-cache policy: las prioridades deben reflejar tus preferencias.

Quinto: decide si arreglas la política o haces un rescate puntual

  • Si el sistema ya está mezclado, puede que necesites un downgrade/alineado controlado.
  • Si es una necesidad puntual de paquete, pinnea solo ese paquete (o ese repo a baja prioridad) y sigue adelante.

Tareas prácticas (comandos + significado de la salida + decisiones)

Estas son las acciones reales que hago en servidores Debian. Cada tarea incluye: un comando ejecutable, un fragmento realista de salida, qué significa y la decisión que tomo a partir de ello.

Task 1: Lista tus fuentes APT configuradas (detecta repos sorpresa)

cr0x@server:~$ grep -Rhs '^[^#]' /etc/apt/sources.list /etc/apt/sources.list.d/*.list
deb http://deb.debian.org/debian trixie main contrib non-free non-free-firmware
deb http://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware
deb http://deb.debian.org/debian trixie-updates main contrib non-free non-free-firmware
deb http://deb.debian.org/debian trixie-backports main contrib non-free non-free-firmware
deb [signed-by=/etc/apt/keyrings/vendor.gpg] https://packages.vendor.example/debian stable main

Qué significa: Estás mezclando stable, security, updates, backports y un repo de proveedor. Eso es normal… si tienes política. Si no la tienes, apt se inventará una.

Decisión: Si hay un repo que no esperabas, desactívalo antes de hacer cualquier otra cosa. Si existe el repo del proveedor, planea pinnearlo bajo.

Task 2: Verifica Default-Release (evita targeting accidental)

cr0x@server:~$ apt-config dump | grep -E 'APT::Default-Release|Acquire::'
APT::Default-Release "trixie";
Acquire::Retries "3";

Qué significa: El sistema prefiere Debian 13 (se muestra el nombre en clave).

Decisión: Mantenlo configurado al nombre en clave de stable (o stable). Si está en blanco, hay más probabilidad de deriva cuando hay varios repos presentes.

Task 3: Actualiza listas de paquetes y vigila errores de repos

cr0x@server:~$ sudo apt update
Hit:1 http://deb.debian.org/debian trixie InRelease
Hit:2 http://security.debian.org/debian-security trixie-security InRelease
Hit:3 http://deb.debian.org/debian trixie-updates InRelease
Hit:4 http://deb.debian.org/debian trixie-backports InRelease
Get:5 https://packages.vendor.example/debian stable InRelease [3,215 B]
Reading package lists... Done
Building dependency tree... Done
All packages are up to date.

Qué significa: Los metadatos se obtuvieron correctamente. Si ves errores de firma, arregla la confianza primero; el pinning no te salva de un repo roto.

Decisión: Si algún repo falla de forma intermitente, considera aislarlo o usar un mirror. Metadatos inestables llevan a candidatos inconsistentes entre hosts.

Task 4: Inspecciona versiones candidatas y prioridades para un paquete

cr0x@server:~$ apt-cache policy openssl
openssl:
  Installed: 3.2.2-1
  Candidate: 3.2.3-1~deb13u1
  Version table:
     3.2.3-1~deb13u1 990
        990 http://security.debian.org/debian-security trixie-security/main amd64 Packages
 *** 3.2.2-1 100
        100 /var/lib/dpkg/status
     3.2.2-1+vendor1 500
        500 https://packages.vendor.example/debian stable/main amd64 Packages

Qué significa: El repo de seguridad tiene prioridad 990 (probablemente por Default-Release). El repo del proveedor está presente pero no gana.

Decisión: Esto es saludable. Si el proveedor tuviera prioridad por encima de 990, lo bajarías inmediatamente.

Task 5: Muestra todas las versiones disponibles a través de repos

cr0x@server:~$ apt-cache madison linux-image-amd64
linux-image-amd64 | 6.12.9-1 | http://deb.debian.org/debian trixie/main amd64 Packages
linux-image-amd64 | 6.12.12-1~deb13u1 | http://security.debian.org/debian-security trixie-security/main amd64 Packages
linux-image-amd64 | 6.13.5-1~bpo13+1 | http://deb.debian.org/debian trixie-backports/main amd64 Packages

Qué significa: Backports ofrece un kernel más nuevo. Eso es tentador para soporte de hardware y peligroso si no lo pretendías.

Decisión: Decide si los kernels están permitidos desde backports. Si no, pinnea backports bajo o pinnea solo el paquete de kernel que quieras controlar.

Task 6: Simula una actualización y lee las eliminaciones como un informe criminal

cr0x@server:~$ sudo apt -s dist-upgrade
Reading package lists... Done
Building dependency tree... Done
Calculating upgrade... Done
The following packages will be upgraded:
  libc6 openssl systemd
The following packages will be REMOVED:
  vendor-storage-agent
3 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
Inst libc6 [2.40-1] (2.40-2~deb13u1 Debian-Security:13/stable-security [amd64])
Remv vendor-storage-agent [2.1.0-4] [vendor-storage-agent:amd64 ]
Inst systemd [257-1] (257-2~deb13u1 Debian-Security:13/stable-security [amd64])
Inst openssl [3.2.2-1] (3.2.3-1~deb13u1 Debian-Security:13/stable-security [amd64])

Qué significa: Una actualización de libc central va a eliminar un agente del proveedor. Eso no es una “actualización”, es una solicitud de cambio.

Decisión: Para. Pinnea o la pila de dependencias del agente del proveedor (o el repo del proveedor) o planifica el reemplazo del agente. No aceptes eliminaciones silenciosas en servidores importantes.

Task 7: Activa el debug del resolvedor para ver el “por qué”

cr0x@server:~$ sudo apt-get -o Debug::pkgProblemResolver=yes -s dist-upgrade
Reading package lists... Done
Building dependency tree... Done
Starting pkgProblemResolver with broken count: 0
Investigating (0) vendor-storage-agent:amd64 < 2.1.0-4 @ii mK Ib >
  Conflicts: libc6 (>= 2.40-2~deb13u1)
  Removing vendor-storage-agent:amd64 rather than change libc6:amd64
Done

Qué significa: El agente del proveedor entra en conflicto con la libc de seguridad. Apt prefiere mantener libc actual y eliminar el agente.

Decisión: Tus opciones son: actualizar el repo del proveedor a un agente compatible, pinnear libc temporalmente (arriesgado), o eliminar/reemplazar deliberadamente el agente.

Task 8: Comprueba qué pins están actualmente en efecto

cr0x@server:~$ ls -1 /etc/apt/preferences.d
00-default-release.pref
10-backports-optin.pref
20-vendor-low.pref

Qué significa: Tienes una política estructurada, no un archivo misterioso único.

Decisión: Si no tienes estos, créalos. Si los tienes, ábrelos y confirma que coinciden con la realidad.

Task 9: Crea un pin sensato “backports opt-in”

cr0x@server:~$ sudo tee /etc/apt/preferences.d/10-backports-optin.pref >/dev/null <<'EOF'
Package: *
Pin: release a=trixie-backports
Pin-Priority: 100
EOF

Qué significa: Los paquetes de backports no se seleccionarán automáticamente sobre las versiones instaladas de stable. Aún puedes instalar desde backports explícitamente.

Decisión: Usa esto en sistemas de producción salvo que tengas una razón sólida para no hacerlo. “Nos gusta lo nuevo” no es una razón; es un rasgo de personalidad.

Task 10: Pinnea un repo de proveedor bajo para que no tome el control

cr0x@server:~$ sudo tee /etc/apt/preferences.d/20-vendor-low.pref >/dev/null <<'EOF'
Package: *
Pin: origin "packages.vendor.example"
Pin-Priority: 50
EOF

Qué significa: Los paquetes del proveedor están disponibles, pero apt no los elegirá a menos que los solicites explícitamente o que stable no ofrezca un candidato instalable.

Decisión: Esta es la postura por defecto para repos de proveedores. Aumenta la prioridad solo para paquetes específicos que realmente quieras de ellos.

Task 11: Pinnea un único paquete a backports (adopción quirúrgica)

cr0x@server:~$ sudo tee /etc/apt/preferences.d/30-zfs-from-backports.pref >/dev/null <<'EOF'
Package: zfs-dkms zfsutils-linux
Pin: release a=trixie-backports
Pin-Priority: 990
EOF

Qué significa: Solo los bits de ZFS se prefieren desde backports. Todo lo demás sigue priorizando stable.

Decisión: Haz esto cuando necesites una característica más reciente de driver/sistema de archivos pero no quieras deriva del sistema completo.

Task 12: Valida que el pin funcionó usando la salida policy

cr0x@server:~$ apt-cache policy zfsutils-linux
zfsutils-linux:
  Installed: 2.2.4-1
  Candidate: 2.2.6-1~bpo13+1
  Version table:
     2.2.6-1~bpo13+1 990
        990 http://deb.debian.org/debian trixie-backports/main amd64 Packages
 *** 2.2.4-1 100
        100 /var/lib/dpkg/status
     2.2.4-1 990
        990 http://deb.debian.org/debian trixie/main amd64 Packages

Qué significa: Para este paquete, backports tiene prioridad 990 y se convierte en candidato. Bien: eso es lo que pediste.

Decisión: Procede con la instalación si has verificado compatibilidad de kernel/módulos y tienes un plan de rollback.

Task 13: Instala desde backports explícitamente (incluso sin pins)

cr0x@server:~$ sudo apt -t trixie-backports install zfsutils-linux
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  libnvpair3linux libuutil3linux libzfs5linux libzpool5linux zfsutils-linux
The following packages will be upgraded:
  zfs-dkms
Need to get 4,812 kB of archives.
After this operation, 18.2 MB of additional disk space will be used.
Do you want to continue? [Y/n]

Qué significa: Apt está trayendo un conjunto coherente de paquetes desde backports para ZFS.

Decisión: En servidores de almacenamiento, programa esto. Reconstrucciones de módulos DKMS y reinicios no son “tareas en segundo plano”, no importa lo que diga tu calendario.

Task 14: Poner un paquete en hold cuando necesitas un congelado duro

cr0x@server:~$ sudo apt-mark hold linux-image-amd64
linux-image-amd64 set on hold.

Qué significa: Apt no actualizará este paquete automáticamente.

Decisión: Usa holds con moderación y rastréalos. Los holds son deuda: acumulan intereses en forma de parches de seguridad y correcciones perdidas.

Task 15: Audita los holds para no olvidar lo que congelaste

cr0x@server:~$ apt-mark showhold
linux-image-amd64

Qué significa: Tienes un hold de kernel en su lugar.

Decisión: Decide si el hold sigue justificado. Si es “temporal”, ponte un recordatorio que sea más difícil de ignorar que tu yo futuro.

Task 16: Muestra paquetes ya instalados de un origen específico (chequeo de deriva)

cr0x@server:~$ apt-cache policy | sed -n '1,120p'
Package files:
 100 /var/lib/dpkg/status
     release a=now
 990 http://security.debian.org/debian-security trixie-security/main amd64 Packages
     release o=Debian,a=trixie-security,n=trixie-security,l=Debian-Security,c=main,b=amd64
 990 http://deb.debian.org/debian trixie/main amd64 Packages
     release o=Debian,a=trixie,n=trixie,l=Debian,c=main,b=amd64
 100 http://deb.debian.org/debian trixie-backports/main amd64 Packages
     release o=Debian Backports,a=trixie-backports,n=trixie-backports,l=Debian Backports,c=main,b=amd64
  50 https://packages.vendor.example/debian stable/main amd64 Packages
     release o=Vendor,a=stable,n=stable,l=Vendor,c=main,b=amd64
Pinned packages:

Qué significa: Tus prioridades de pin son visibles a nivel de repositorio: security y stable en 990, backports en 100, proveedor en 50.

Decisión: Si estos números no coinciden con tu política deseada, arregla preferences antes de actualizar nada.

Task 17: Confirma un emparejamiento de pin usando campos “origin” y “release”

cr0x@server:~$ apt-cache policy | grep -E 'release o=|release a='
     release o=Debian,a=trixie-security,n=trixie-security,l=Debian-Security,c=main,b=amd64
     release o=Debian,a=trixie,n=trixie,l=Debian,c=main,b=amd64
     release o=Debian Backports,a=trixie-backports,n=trixie-backports,l=Debian Backports,c=main,b=amd64
     release o=Vendor,a=stable,n=stable,l=Vendor,c=main,b=amd64

Qué significa: Estas cadenas son las que tus reglas de pin deben coincidir. Adivinar es como los pins fallan silenciosamente.

Decisión: Usa estos valores exactos (especialmente origin y a=) en tus preferencias.

Task 18: Simula instalar un paquete del proveedor sin dejar que se propague

cr0x@server:~$ sudo apt -s install vendor-storage-agent
Reading package lists... Done
Building dependency tree... Done
The following packages will be installed:
  vendor-storage-agent
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Inst vendor-storage-agent (2.1.3-1 Vendor:stable [amd64])

Qué significa: Con el repo del proveedor pinneado bajo, apt solo instala lo que solicitaste; no sustituye proactivamente librerías centrales.

Decisión: Este es el resultado que quieres. Si la simulación muestra una pila de actualizaciones del proveedor, baja más la prioridad del proveedor o pinnea solo el paquete específico del proveedor.

Tres micro-historias corporativas desde la trinchera

1) Incidente causado por una suposición equivocada: “Las actualizaciones de seguridad no cambiarán dependencias”

Una empresa mediana ejecutaba una flota de servidores Debian que gestionaban artefactos de build internos e imágenes de contenedor. El backend de almacenamiento era aburrido: RAID, ext4 y un agente de monitorización del proveedor que insistía en que era “ligero”. El equipo tenía una ventana semanal de parches y una regla: aplicar las actualizaciones de seguridad rápido, porque a los auditores les encanta el cumplimiento calendarizado.

Una semana, una actualización de seguridad tiró de una nueva revisión menor de una librería central. No fue un salto de versión mayor, así que pasó la revisión humana. La suposición equivocada fue sutil: “el repo de seguridad no romperá el espacio de usuario”. Debian es conservador, pero “conservador” no es “nunca cambios de dependencias”, especialmente cuando los parches de seguridad requieren recompilar contra libs actualizadas.

El agente del proveedor tenía una restricción de dependencia estricta y no se había recompilado para la librería actualizada por seguridad. Apt hizo lo que hace apt: propuso eliminar el agente. Alguien vio “1 to remove” y pensó que era un paquete antiguo de kernel. Era lo que enviaba métricas al NOC.

Después de la actualización, nada estaba “caído”. Ese fue el problema. El NOC tenía un punto ciego: discos llenos, presión de inodos subió y un par de nodos de build empezaron a fallar pushes. El incidente lo descubrieron desarrolladores, no la monitorización. Eso es un fallo cultural con raíz técnica.

La solución no fue heroica. El equipo pinneó el repo del proveedor bajo, luego pinneó el paquete agente del proveedor lo bastante alto para permanecer instalable sin arrastrar librerías del proveedor sobre las de Debian. También añadieron una regla de revisión: la salida de actualización simulada debe mostrar cero eliminaciones salvo aprobación explícita. Dejaron de tratar las actualizaciones de seguridad como neutrales en dependencias.

2) Optimización que salió mal: “Pinneemos todo a backports por velocidad”

Un equipo de plataforma empresarial tenía una picazón de rendimiento. Su capa de terminación TLS estaba limitada por CPU, y alguien notó una librería crypto más nueva en backports con mejor rendimiento en CPUs modernas. La idea parecía razonable: traer la librería más nueva, obtener handshakes más rápidos y disfrutar de gráficos de latencia menores.

Crearon un pin amplio: backports con alta prioridad para todos los paquetes. Parecía limpio y consistente: un repo, una dirección, menos sorpresas. También convirtió silenciosamente a stable en “mayormente ignorado”, que es lo contrario de por qué ejecutas stable en producción.

La primera semana lució bien. Luego vino una reacción en cadena: una librería más nueva tiró de un componente toolchain más nuevo, que tiró de un runtime más nuevo, que tiró de un servicio del sistema más nuevo. El sistema seguía arrancando, pero aparecieron bugs de regresión en lugares que nadie conectó con “rendimiento TLS”. Un problema particularmente desagradable involucró un cambio en el orden de reinicio de servicios que interactuó con el timing de los montajes de almacenamiento. Un pequeño porcentaje de nodos arrancó sin montajes críticos, y las aplicaciones escribieron en la raíz. Ese es el tipo de error que crea capas arqueológicas en /.

El rollback fue peor que el cambio. Hacer downgrade de un sistema ampliamente actualizado es posible, pero es lento y más arriesgado que prevenir la deriva inicialmente. Terminaron reconstruyendo nodos en lugar de “arreglarlos” in situ, lo cual es honesto pero caro.

La lección: el pinning no es un control de rendimiento. Es una herramienta de política. Si necesitas una librería crypto nueva, pinnea esa librería (y solo el conjunto necesario) o usa una instalación dirigida con -t backports y revisión estricta. Backports puede ser genial; “todo desde backports” es básicamente una nueva pista de distribución.

3) Práctica aburrida pero correcta que salvó el día: “Un archivo de pin por intención, más una auditoría de deriva”

Un equipo de servicios financieros ejecutaba Debian en sistemas con mucho almacenamiento: servicios de archivos, gateways de objetos y coordinadores de backup. Su entorno era lo opuesto a lo fashion: hosts de larga vida, actualizaciones cuidadosas y una cultura documentada de “qué cambió”. También tenían una regla poco sexy: ningún host recibe un repo sin un archivo de pin en /etc/apt/preferences.d.

Pinnearon backports a 100 globalmente, luego allowlistaron una lista corta de paquetes a 990 cuando necesitaban soporte de hardware o fixes de sistema de archivos. Los repos de proveedor estaban pinneados a 50 por origin, con excepciones explícitas para dos paquetes. También establecieron Default-Release al nombre en clave de stable y lo incluyeron en su configuración base.

El momento de salvar el día llegó durante una respuesta urgente de seguridad. Una nueva actualización de seguridad apareció, y simultáneamente un repo de proveedor publicó un conjunto de paquetes que, por número de versión, parecían “más nuevos”. En un sistema menos disciplinado, apt podría haber derivado hacia paquetes del proveedor. En estos hosts, el repo del proveedor no estaba autorizado para ganar por defecto. La actualización se mantuvo dentro del ecosistema Debian, y los paquetes del proveedor permanecieron disponibles solo cuando se solicitaron explícitamente.

Aún hicieron trabajo: ejecutaron una actualización simulada, confirmaron que no había eliminaciones y desplegaron con un canario escalonado. Fue casi aburrido. Ese es el punto. Su herramienta de respuesta a incidentes más valiosa no fue una plataforma elegante; fue una política de selección de paquetes predecible y un hábito de auditoría.

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

1) Síntoma: apt quiere eliminar la mitad de tu sistema durante una actualización

Causa raíz: Tienes una fuente de paquetes en conflicto (a menudo un proveedor) con dependencias incompatibles, o estás tirando de backports/testing sin querer.

Solución: Identifica el paquete que dispara las eliminaciones vía apt -s dist-upgrade, luego mira apt-cache policy para ese paquete. Pinnea el repo ofensivo más bajo (ej., 50) y re-ejecuta la simulación.

2) Síntoma: paquetes de backports se instalan incluso cuando no los pediste

Causa raíz: Backports está pinneado demasiado alto, o Default-Release no está establecido y apt elige la versión más nueva cuando hay empate de prioridades.

Solución: Establece backports a Pin-Priority: 100 para Package: *, y configura APT::Default-Release al nombre en clave de stable.

3) Síntoma: tu archivo de pin “no hace nada”

Causa raíz: El selector Pin: no coincide con los metadatos reales del repo. Errores comunes: cadena origin equivocada; confundir a= (Archive) con n= (Codename).

Solución: Copia los valores exactos de las líneas release de apt-cache policy y úsalos en tu regla de pin.

4) Síntoma: apt se niega a hacer downgrade cuando necesitas revertir

Causa raíz: Tus pins no permiten downgrades (prioridad no > 1000), o no existe la versión antigua en ningún repo disponible.

Solución: Asegura que la versión antigua deseada exista en stable/security y establece un pin temporal para ese paquete en 1001 para permitir el downgrade, luego elimina el pin temporal después.

5) Síntoma: no puedes instalar un paquete del proveedor porque los paquetes de Debian “ganan”

Causa raíz: Pinneaste al proveedor bajo (bien), pero no solicitaste explícitamente versiones del proveedor y Debian provee un candidato válido.

Solución: Instala explícitamente por versión o por target release (si el repo del proveedor tiene una release distinta), o crea un pin estrecho solo para ese paquete del proveedor.

6) Síntoma: las actualizaciones de seguridad quedan bloqueadas (“kept back”) después de pinnear algo

Causa raíz: Pinneaste una dependencia (como libc, openssl, systemd) demasiado agresivamente, impidiendo que el repo de seguridad la actualice.

Solución: Elimina el pin para componentes centrales. Si debes congelar, usa un hold con tiempo limitado, con ticket y plan de rollback. Luego descongela.

7) Síntoma: servidores distintos seleccionan candidatos distintos

Causa raíz: La configuración de repos difiere (archivos sources), los archivos de pin difieren, o un host no ejecutó apt update y usa metadatos obsoletos. A veces un proxy/cache sirve vistas distintas.

Solución: Compara /etc/apt/sources.list* y /etc/apt/preferences.d entre hosts; asegura actualizaciones de metadatos consistentes; estandariza con gestión de configuración.

Listas de verificación / plan paso a paso (seguro para producción)

Línea base de política (haz esto antes de necesitarlo)

  1. Establece Default-Release al nombre en clave de stable en una configuración gestionada (o verifica que exista y se mantenga).
  2. Divide los pins por intención en /etc/apt/preferences.d, no en un archivo monolítico.
  3. Pinnea backports a 100 globalmente salvo que tengas una razón específica para dejarlo más alto.
  4. Pinnea repos de proveedor a 50 por origin como postura defensiva por defecto.
  5. Allowlista excepciones con pins estrechos: solo paquetes específicos obtienen 990 desde backports/proveedor.
  6. Escribe una regla “no eliminaciones sin aprobación” para actualizaciones, y aplícala en la revisión de cambios.

Antes de cualquier ventana de actualización

  1. Ejecuta sudo apt update y asegura metadatos de repos limpios.
  2. Ejecuta sudo apt -s dist-upgrade y revisa eliminaciones y expansiones grandes de dependencias.
  3. Para cualquier candidato sorprendente, ejecuta apt-cache policy pkg y confirma que la fuente y prioridad tienen sentido.
  4. Si tiras de backports, confirma que es deliberado y limitado a los paquetes pretendidos.

Cuando debes instalar desde backports (patrón seguro)

  1. Mantén backports a 100 globalmente.
  2. Agrega un pin estrecho para el/los paquete(s) que necesitas a 990 desde backports.
  3. Simula la instalación/actualización y revisa por actualizaciones colaterales.
  4. Instala primero en un nodo canario. Confirma salud del servicio y comportamiento de arranque (especialmente para cambios de kernel/módulos).
  5. Despliega gradualmente.

Cuando se requiere un repo de proveedor (patrón seguro)

  1. Pinnea la origin del proveedor a 50 para Package: *.
  2. Pinnea solo los paquetes del proveedor que realmente necesites más alto (990), y mantén visibles sus cadenas de dependencias.
  3. Prueba explícitamente que las librerías centrales sigan proveniendo de Debian a menos que tengas un contrato de soporte que exija lo contrario.
  4. Mantén una vía de desinstalación limpia. Los agentes de proveedor tienden a persistir de maneras extrañas.

Broma #2: APT felizmente resolverá tu problema de dependencias desinstalando tu aplicación. Es como despedir al cliente para mejorar las métricas de satisfacción del cliente.

Preguntas frecuentes

1) ¿Debo usar pinning o apt-mark hold?

Usa pinning para política (“preferir seguridad de Debian sobre proveedor”, “backports opt-in”). Usa holds para congelos cortos y explícitos (“no cambiar kernel esta semana”). Los holds deben tener límite temporal.

2) ¿Qué números de Pin-Priority debería usar realmente?

Valores sensatos comunes: stable/security con el valor por defecto (a menudo 990 con Default-Release), backports a 100 globalmente, proveedor a 50 globalmente. Usa 990 para paquetes específicos que quieras de backports/proveedor. Usa >1000 solo para downgrades forzados temporales.

3) ¿Puedo pinear por nombre en clave vs por archive?

Sí, pero sé consistente. Pinear por release a=trixie-backports suele ser estable. Pinear por n= puede estar bien, pero verifica qué contiene realmente el metadata del repo usando apt-cache policy.

4) ¿Por qué apt aún elige a veces un repo de “menor prioridad”?

Porque el candidato de mayor prioridad puede no ser instalable debido a dependencias. Apt elegirá una solución instalable. Por eso la salida del debug del resolvedor es valiosa: muestra qué restricciones forzaron la decisión.

5) ¿Cómo evito crear accidentalmente un FrankenDebian?

No agregues repos testing/unstable a servidores stable. Si debes añadir un repo no Debian, pinnealo bajo por origin y allowlista solo paquetes específicos. Y siempre simula actualizaciones antes de aplicarlas.

6) ¿El pinning es suficiente para mantener seguros los repos de terceros?

No. El pinning controla preferencia, no confianza. Aún necesitas gestión adecuada de keyrings, limpieza de repos y una razón para incluir el repo.

7) ¿Cuál es la diferencia entre apt upgrade y apt full-upgrade con pins?

apt upgrade evita eliminaciones y cambios complejos, a menudo dejando paquetes “kept back”. apt full-upgrade (o dist-upgrade) permite eliminaciones para satisfacer dependencias. Los pins afectan a ambos, pero full-upgrade revela el costo real de tu política actual.

8) ¿Puedo pinear conjuntos enteros de dependencias de forma segura?

Puedes, pero es fácil pasarse. Prefiere pins estrechos: el paquete que necesitas más el conjunto mínimo que requiere. Si pineas un conjunto amplio, en efecto estás optando por una pista de release diferente para ese subsistema.

9) ¿Cómo recupero si ya actualicé desde el repo equivocado?

Primero, para de actualizar. Añade pins para preferir nuevamente Debian stable/security, luego simula una ruta de downgrade. Si el downgrade es complicado, considera reconstruir el host (a menudo más seguro) en lugar de hacer downgrades in situ complejos de librerías centrales.

10) ¿Debería pinear kernels?

Si necesitas control estricto de kernel (drivers, DKMS, módulos de almacenamiento), sí—o pon en hold el paquete meta temporalmente o pinea las fuentes del kernel. Pero no olvides las implicaciones de seguridad: los congelamientos de kernel deben ser cortos y deliberados.

Siguientes pasos que realmente deberías hacer

Si gestionas servidores Debian 13 que importan, haz esto en orden:

  1. Haz inventario de repos en toda la flota y elimina todo lo que no puedas justificar.
  2. Establece APT::Default-Release al nombre en clave de Debian 13 de forma consistente.
  3. Crea /etc/apt/preferences.d/10-backports-optin.pref y mantén backports en 100 globalmente.
  4. Pinnea cualquier repo de proveedor a 50 por origin, luego allowlista solo los paquetes que realmente necesites.
  5. Haz que apt -s dist-upgrade sea un paso preflight obligatorio. No hay eliminaciones sin aprobación.
  6. Una vez al mes, audita los holds (apt-mark showhold) y elimina los que hayan perdido su justificación.

La recompensa es aburrida en el mejor sentido: las actualizaciones se vuelven rutinarias, la deriva se vuelve visible y apt deja de sorprenderte a las 02:13. Tus servidores seguirán rompiéndose a veces—los servidores son así—pero no será porque dejaste al gestor de paquetes improvisar.

← Anterior
Docker macvlan: No puedo alcanzar el contenedor — Soluciona la clásica trampa de enrutamiento
Siguiente →
Debian 13: /etc/pve parece vacío tras reinicio — por qué fallan los montajes y cómo recuperar

Deja un comentario