Version-Pinning

Siehe auch

Als Version-Pinning wird das Festnageln einzelner Pakete oder eines ganzen Betriebssystems auf eine bestimmte Version bezeichnet. Typische Einsatzgebiete sind Applikationen, die mit neueren Libraries brechen, Cluster-Knoten, die während eines Rolling-Upgrades bewusst auf einer älteren Minor-Version bleiben sollen, sowie Test- und Produktiv-Systeme, die zwischen Freeze-Fenstern identische Paketstände vorhalten müssen. Auch regulatorische Vorgaben (Common Criteria, ISO 27001) führen dazu, dass Maschinen nicht automatisch upgraden dürfen.

Gepinnte Pakete erhalten in der Regel keine Security-Updates mehr. Pinning ist daher immer eine bewusste Abwägung zwischen Stabilität und Sicherheit und sollte dokumentiert, terminiert und regelmässig überprüft werden.

Begriffe
  • Hold: Begriff aus der Debian-Welt (apt-mark hold). Das Paket bleibt auf der aktuellen Version, Upgrades und Entfernung werden blockiert.

  • Pin-Priority: Gewichtung einer APT-Pin-Regel. Werte über 1000 erlauben Downgrades, Werte unter 0 verhindern die Installation komplett.

  • Release-Pinning: Festnageln des gesamten Betriebssystems auf eine Minor-Version.

  • Vault / Archive: Repositories mit historischen Paketständen. Auf RHEL-Klonen unter vault.rockylinux.org bzw. repo.almalinux.org/vault, bei Debian unter snapshot.debian.org, bei Ubuntu unter old-releases.ubuntu.com.

  • Versionlock: DNF-Plugin, das einzelne Pakete auf eine NEVRA-Kombination festnagelt.

RHEL 10, Rocky Linux, AlmaLinux

Einzelne Pakete pinnen

Das python3-dnf-plugin-versionlock-Paket stellt den Mechanismus bereit, um einzelne Pakete auf eine bestimmte Version festzuhalten. Beispiel: ansible-core soll nicht über Version 2.16.3 hinaus upgraden:

dnf --assumeyes install python3-dnf-plugin-versionlock
dnf --assumeyes install ansible-core-2.16.3-1.el10

dnf versionlock add ansible-core
dnf versionlock list
dnf versionlock delete ansible-core

Die Locks werden in /etc/dnf/plugins/versionlock.list abgelegt und lassen sich dort auch manuell pflegen. Wildcards sind erlaubt:

/etc/dnf/plugins/versionlock.list
ansible-core-0:2.16.3-1.el10.*
kernel-0:6.11.0-*

Die härtere Variante ist exclude in der DNF-Konfiguration. Damit wird selbst ein manuelles dnf install blockiert:

/etc/dnf/dnf.conf
exclude=iptables* kernel*

RHEL auf eine Minor-Version pinnen

Subscription-basiertes RHEL erlaubt das Pinning auf eine bestimmte Minor-Version ausschliesslich auf registrierten Systemen. Auf Rocky Linux und AlmaLinux existiert dieser Mechanismus nicht; dafür siehe den nächsten Abschnitt.

subscription-manager release --list
subscription-manager release --show
subscription-manager release --set=10.0

dnf clean all
subscription-manager repos
dnf update

Zurücksetzen auf „immer neueste Minor-Version“:

subscription-manager release --unset

Für Extended Update Support (EUS) müssen zusätzlich die passenden *-eus-*-Repos aktiviert werden.

Rocky Linux und AlmaLinux auf eine Minor-Version pinnen

Beide Distributionen bieten Vault-Repositories mit Minor-Version-Snapshots. Der Trick besteht darin, $releasever in den Repo-Definitionen durch eine feste Version zu ersetzen und auf das Vault umzubiegen.

Rocky Linux, Beispiel 10.0:

sed --in-place=.bak \
    --expression='s|^mirrorlist=|#mirrorlist=|g' \
    --expression='s|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://dl.rockylinux.org/vault|g' \
    --expression='s|\$releasever|10.0|g' \
    /etc/yum.repos.d/rocky*.repo

dnf clean all
dnf makecache

AlmaLinux, Beispiel 10.0:

sed --in-place=.bak \
    --expression='s|^mirrorlist=|#mirrorlist=|g' \
    --expression='s|^# baseurl=https://repo.almalinux.org/almalinux|baseurl=https://repo.almalinux.org/vault|g' \
    --expression='s|\$releasever|10.0|g' \
    /etc/yum.repos.d/almalinux*.repo

dnf clean all
dnf makecache

Bemerkung

Vor dem Umbiegen der Repos unbedingt ein Backup der *.repo-Dateien ziehen. Zum Zurückspringen auf die jeweils neueste Minor-Version reichen die *.repo.bak-Dateien.

Debian und Ubuntu

Einzelne Pakete mit apt-mark hold pinnen

Der einfachste Weg, ein Paket nicht mehr durch apt upgrade oder Unattended-Upgrades anfassen zu lassen:

apt-mark hold nginx
apt-mark showhold
apt-mark unhold nginx

Ein hold verhindert Upgrades, Installationen und Entfernung durch Paket-Abhängigkeiten. Ein manuelles apt install --only-upgrade nginx bricht mit einer Warnung ab. Die Marken werden in der dpkg-Datenbank unter /var/lib/dpkg/status gespeichert.

Einzelne Pakete mit APT-Pinning pinnen

Feingranular und für Kombinationen wie „dieses Paket genau in dieser Version“ oder „dieses Paket nur aus jenem Repo“ eignet sich APT-Pinning über /etc/apt/preferences.d/. Jede Pin-Regel besteht aus drei Feldern:

  • Package: Paketname (Glob erlaubt)

  • Pin: Bedingung (Version, Release, Origin)

  • Pin-Priority: Priorität (siehe unten)

Beispiel: Docker-CE auf Version 24.0.7 festhalten:

/etc/apt/preferences.d/docker-ce
Package: containerd.io docker-ce docker-ce-cli
Pin: version 5:24.0.7-1~debian.12~bookworm
Pin-Priority: 1001

Priority-Werte:

  • < 0: Paket nie installieren.

  • 100: installiert, aber Upgrade nur via Default-Kandidat.

  • 500: Default für reguläre Repos.

  • 990: Default für das Ziel-Release (APT::Default-Release).

  • 1000: installieren, nie automatisch upgraden.

  • > 1000: installieren und auch Downgrades erlauben.

Prüfen, welcher Kandidat tatsächlich gewählt wird:

apt-cache policy docker-ce

Debian auf ein Release pinnen

Debian unterstützt mehrere Suites parallel (stable, testing, unstable). Um eine Maschine fix auf bookworm festzunageln und Pakete bevorzugt aus dieser Suite zu ziehen, auch wenn später trixie aktiv wird:

/etc/apt/apt.conf.d/99default-release
APT::Default-Release "bookworm";
/etc/apt/preferences.d/99pin-bookworm
Package: *
Pin: release n=bookworm
Pin-Priority: 990

Package: *
Pin: release n=trixie
Pin-Priority: 100

Einzelne Pakete aus dem unerwünschten Release lassen sich trotzdem per apt install -t trixie paketname explizit ziehen.

Debian zeitpunktgenau pinnen via snapshot.debian.org

Debian bietet unter https://snapshot.debian.org einen zeitpunktgenauen Archiv-Server an. Beispiel: ein System auf den Paketstand vom 2026-01-15 festnageln:

/etc/apt/sources.list
deb [check-valid-until=no] https://snapshot.debian.org/archive/debian/20260115T000000Z bookworm main contrib non-free non-free-firmware
deb [check-valid-until=no] https://snapshot.debian.org/archive/debian-security/20260115T000000Z bookworm-security main contrib non-free non-free-firmware
apt update
apt --assume-yes upgrade

Das entspricht dem, was der Vault für CentOS/RHEL war: historische Pakete in exakt diesem Stand, inklusive Security-Updates bis zum Stichtag.

Ubuntu auf ein Release pinnen

Ubuntu kennt drei relevante Mechanismen.

Automatische Release-Upgrades deaktivieren:

/etc/update-manager/release-upgrades
Prompt=never

Wirkt auf do-release-upgrade. Alternativen: lts (nur LTS auf LTS) und normal.

Unattended-Upgrades auf bestimmte Pakete einschränken:

/etc/apt/apt.conf.d/51unattended-upgrades-custom
Unattended-Upgrade::Package-Blacklist {
    "docker-ce";
    "linux-.*";
};

Phased Updates deaktivieren. Ubuntu rollt Updates stufenweise über Phased-Update-Percentage aus:

/etc/apt/apt.conf.d/99-no-phased-updates
APT::Get::Always-Include-Phased-Updates "false";
Update-Manager::Always-Include-Phased-Updates "false";

Ubuntu zeitpunktgenau pinnen

Nach dem EOL eines Ubuntu-Releases wandern die Pakete nach https://old-releases.ubuntu.com. Die Sources-Einträge werden entsprechend umgebogen:

sed --in-place=.bak \
    --expression='s|archive.ubuntu.com|old-releases.ubuntu.com|g' \
    --expression='s|security.ubuntu.com|old-releases.ubuntu.com|g' \
    /etc/apt/sources.list

apt update

Canonical betreibt seit 2024 unter https://snapshot.ubuntu.com einen zeitpunktgenauen Snapshot-Dienst, siehe https://ubuntu.com/server/docs/about-apt-snapshots.

Cheat Sheet

# RHEL 10 / Rocky / Alma
dnf versionlock add ansible-core
dnf versionlock delete ansible-core
dnf versionlock list
subscription-manager release --set=10.0   # nur RHEL

# Debian / Ubuntu
apt --assume-yes install --only-upgrade nginx   # respektiert hold
apt-cache policy docker-ce
apt-mark hold nginx
apt-mark showhold
apt-mark unhold nginx

Troubleshooting

apt-mark hold wird ignoriert

Unattended-Upgrades und die meisten Drittanbieter-Tools (cloud-init, landscape) respektieren hold. Ein dist-upgrade mit --allow-change-held-packages hebt den Schutz hingegen auf. Details in /var/log/apt/history.log.

dnf versionlock: No package matches

Der Paketname ist falsch geschrieben oder das Paket in keinem aktivierten Repo. Prüfung mit dnf list --installed NAME. Versionlock-Einträge müssen exakt auf den Installations-NEVRA passen.

Package has no installation candidate (nach Release-Pinning)

Die Pin-Priority ist zu niedrig oder das Paket liegt gar nicht im gepinnten Release. Mit apt-cache policy PAKETNAME nachvollziehen, welche Quellen mit welcher Priorität bewertet werden.

subscription-manager release –set schlägt fehl

Entweder ist die Subscription nicht aktiv (subscription-manager status), oder die gewünschte Minor-Version liegt ausserhalb des Lifecycle-Fensters. Für ältere Versionen wird EUS oder ELS benötigt.