APT-Paketmanagement im Detail: Repos, Pins, Cache
$
/etc
Linux · Paketmanagement · APT · DevOps
APT-Paketmanagement im Detail
Repos, Pins, Cache

APT verwaltet Softwarepakete auf Debian und Ubuntu Servern, doch die meisten Admins nutzen nur einen Bruchteil seiner Möglichkeiten. Dieser Artikel erklärt, wie APT Abhängigkeiten auflöst, warum apt, apt-get und dpkg unterschiedliche Aufgaben übernehmen, wie Pinning ungewollte Upgrades verhindert, wie Drittanbieter-Repositories sicher eingebunden werden und wie der Paket-Cache sauber bleibt.

15 Min. Lesezeit apt · apt-get · dpkg · sources.list · Pinning Debian · Ubuntu · Linux

1. Wie APT Pakete auflöst und installiert

Bevor APT ein einziges Paket installiert, braucht es aktuelle Informationen darüber, welche Pakete in welcher Version in den konfigurierten Repositories verfügbar sind. Der Befehl apt update lädt für jede in /etc/apt/sources.list und /etc/apt/sources.list.d/ eingetragene Quelle eine komprimierte Paketliste herunter und speichert sie entpackt in /var/lib/apt/lists/. Diese lokalen Indizes enthalten für jedes verfügbare Paket Metadaten wie Version, Abhängigkeiten, Dateigröße und Prüfsumme, aber noch keine tatsächlichen Programmdateien. Ohne ein aktuelles apt update arbeitet jeder nachfolgende Befehl mit veralteten Informationen, was zu Fehlern wie 404-Antworten beim Download oder falsch aufgelösten Versionsnummern führen kann.

Erst beim eigentlichen apt install paketname beginnt die Abhängigkeitsauflösung. APT liest die Felder Depends, Recommends, Suggests, Conflicts und Provides aus dem Paketindex und berechnet, welche zusätzlichen Pakete installiert, entfernt oder aktualisiert werden müssen, damit alle Bedingungen gleichzeitig erfüllt sind. Virtuelle Pakete wie mail-transport-agent, die von mehreren konkreten Paketen wie postfix oder exim4 bereitgestellt werden, machen diese Auflösung zusätzlich komplex, weil APT zwischen mehreren gültigen Kandidaten wählen muss. Mit apt install --simulate paketname lässt sich der komplette Installationsplan vorab prüfen, ohne dass tatsächlich etwas verändert wird, was besonders vor Änderungen an Produktionssystemen unverzichtbar ist.


#!/usr/bin/env bash
# Refresh package indexes, then simulate an install without changing anything
$ sudo apt update
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Get:2 http://archive.ubuntu.com/ubuntu noble-updates InRelease [126 kB]
Get:3 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Fetched 252 kB in 1s (211 kB/s)
Reading package lists... Done

$ apt install --simulate php8.4-fpm
Inst php8.4-common (8.4.6-1+ubuntu24.04.1 Ondrej PHP PPA)
Inst php8.4-fpm (8.4.6-1+ubuntu24.04.1 Ondrej PHP PPA)
Inst php8.4-opcache (8.4.6-1+ubuntu24.04.1 Ondrej PHP PPA)
Conf php8.4-fpm (8.4.6-1+ubuntu24.04.1 Ondrej PHP PPA)

# Show which candidate version would actually be picked, and why
$ apt-cache policy php8.4-fpm
php8.4-fpm:
  Installed: (none)
  Candidate: 8.4.6-1+ubuntu24.04.1
  Version table:
     8.4.6-1+ubuntu24.04.1 500
        500 https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble/main amd64 Packages

2. apt, apt-get und dpkg: die Schichtenarchitektur verstehen

Ganz unten in der Werkzeugkette steht dpkg, das direkt mit einzelnen .deb-Dateien arbeitet. dpkg -i paket.deb installiert eine lokal vorliegende Paketdatei und trägt sie in die zentrale Statusdatenbank /var/lib/dpkg/status ein, löst dabei aber keine Abhängigkeiten auf und lädt nichts aus dem Netz nach. Schlägt eine Abhängigkeit fehl, bricht dpkg mit einer Fehlermeldung ab und hinterlässt das Paket im Zustand half-configured. Genau diese Lücke schließt die Ebene darüber: apt-get und apt-cache als klassische, seit Jahrzehnten stabile Kommandozeilenwerkzeuge, die Repositories kennen, Abhängigkeiten automatisch nachziehen und den kompletten Installationsplan berechnen, bevor dpkg im Hintergrund die eigentliche Arbeit übernimmt.

Seit APT 1.1 bündelt der Befehl apt die am häufigsten gebrauchten Funktionen von apt-get und apt-cache in einem einzigen, benutzerfreundlicheren Frontend mit Fortschrittsbalken, farbiger Ausgabe und sinnvolleren Voreinstellungen. Für den interaktiven Alltag ist apt daher die richtige Wahl. In Skripten und Automatisierung warnt die apt-Manpage jedoch ausdrücklich: Die Kommandozeilenschnittstelle von apt gilt als instabil und kann sich zwischen Versionen ändern, während apt-get und apt-cache seit Jahrzehnten eine stabile, unveränderte Schnittstelle bieten. Deployment-Skripte und CI-Pipelines sollten deshalb konsequent apt-get und apt-cache verwenden, niemals apt.

3. Repository-Quellen: sources.list und sources.list.d im Detail

Die klassische Konfigurationsdatei /etc/apt/sources.list folgt dem einzeiligen Format deb URI Suite Komponente1 Komponente2. Das Schlüsselwort deb markiert eine Binärpaket-Quelle, deb-src eine Quellcode-Quelle. Die URI verweist auf den Repository-Server, die Suite ist meist der Codename der Distribution wie noble oder bookworm, ergänzt um Suffixe wie -security oder -updates für getrennte Sicherheits- und Aktualisierungs-Pockets. Die Komponenten wie main, universe, restricted und multiverse bei Ubuntu trennen Pakete nach Lizenzstatus und Support-Umfang, wobei nur main und restricted offiziellen Canonical-Support genießen.

Zusätzliche Quellen gehören nicht in die Hauptdatei, sondern als eigene .list-Dateien nach /etc/apt/sources.list.d/, damit jedes Paket-Repository unabhängig hinzugefügt und entfernt werden kann. Seit APT 2.4 unterstützt das System zusätzlich das neuere, schlüsselbasierte DEB822-Format mit der Dateiendung .sources, das mehrzeilige, gut lesbare Blöcke mit expliziten Feldern wie Types, URIs, Suites, Components und Signed-By verwendet. Ubuntu 24.04 nutzt dieses Format standardmäßig für die System-Repositories. Der Vorteil gegenüber dem alten Einzeiler-Format: Der Signierschlüssel wird direkt im Repository-Eintrag referenziert, statt implizit systemweit vertraut zu werden, was Third-Party-Quellen deutlich sicherer macht.


# /etc/apt/sources.list.d/php.sources
# DEB822 format, introduced with APT 2.4, default on Ubuntu 24.04+
Types: deb
URIs: https://ppa.launchpadcontent.net/ondrej/php/ubuntu
Suites: noble
Components: main
Signed-By: /etc/apt/keyrings/ondrej-php.gpg

# The legacy one-line equivalent in a .list file looked like this:
# deb [signed-by=/etc/apt/keyrings/ondrej-php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main

4. APT-Pinning: Pakete gezielt fixieren und Upgrades verhindern

APT-Pinning steuert über numerische Prioritäten, welche verfügbare Version eines Pakets bei einer Installation oder einem Upgrade gewählt wird, unabhängig davon, welches Repository die neueste Version anbietet. Konfiguriert wird das über Dateien in /etc/apt/preferences.d/, die aus Blöcken mit Package, Pin und Pin-Priority bestehen. Priorität 1000 erzwingt sogar ein Downgrade auf die angegebene Version, Priorität 990 entspricht typischerweise der Ziel-Suite, Priorität 500 ist der Standardwert für alle normal konfigurierten Quellen, Werte unter 0 verhindern die Installation komplett. Damit lässt sich zum Beispiel eine bestimmte PHP- oder MariaDB-Version dauerhaft fixieren, während der Rest des Systems normal aktualisiert wird.

Für einfachere Fälle genügt oft apt-mark hold paketname, das ein bereits installiertes Paket vollständig von Upgrades ausschließt, ohne eine Prioritätsdatei anzulegen. Der Unterschied ist entscheidend: apt-mark hold blockiert jede Aktualisierung des Pakets komplett, während Pinning granular eine bestimmte Version oder ein bestimmtes Repository bevorzugt und trotzdem Sicherheitsupdates innerhalb der gepinnten Version zulässt, wenn die Pin-Regel entsprechend eng formuliert ist. Bei Magento-Servern ist das besonders relevant für PHP-Minor-Versionen und die MySQL- beziehungsweise MariaDB-Version, weil ein automatisches Major-Upgrade Kompatibilitätsprobleme mit der Magento-Codebasis auslösen kann, die erst bei einem gezielten, geplanten Upgrade behoben werden sollen.


# /etc/apt/preferences.d/php-pin.pref
# Pin PHP 8.4 packages to the Ondrej PPA, block accidental version jumps

Package: php8.4-*
Pin: origin ppa.launchpadcontent.net
Pin-Priority: 900

# Never allow the experimental PHP 8.5 packages to be installed automatically
Package: php8.5-*
Pin: release *
Pin-Priority: -1

# Force MariaDB to stay on the 10.11 LTS branch, even if 11.x becomes candidate
Package: mariadb-server mariadb-client
Pin: version 1:10.11.*
Pin-Priority: 1001

5. Third-Party-Repositories sicher einbinden

Der Befehl apt-key add galt lange als Standardweg, um den Signierschlüssel eines Drittanbieter-Repositories systemweit zu vertrauen, ist aber seit Debian 11 und Ubuntu 21.10 offiziell veraltet und wird in kommenden Versionen entfernt. Das Problem: Ein per apt-key importierter Schlüssel gilt automatisch für alle Repositories im System, nicht nur für das eine, das ihn tatsächlich braucht. Ein kompromittierter Drittanbieter-Schlüssel könnte damit theoretisch Pakete für jede beliebige Quelle signieren. Der sichere, moderne Weg lagert Schlüssel als eigene Datei in /etc/apt/keyrings/ ab, importiert mit gpg --dearmor aus der offiziellen Quelle, und referenziert diese Datei explizit über das Feld Signed-By im Repository-Eintrag.

Grundsätzlich gilt: Ein Schlüssel sollte niemals blind über eine curl ... | sudo bash-Kette eingebunden werden, ohne den heruntergeladenen Schlüssel-Fingerprint gegen die offizielle Dokumentation des Anbieters zu prüfen, etwa mit gpg --show-keys --with-fingerprint datei.asc. Nach dem Hinzufügen einer neuen Quelle sollte immer zuerst apt update isoliert für diese eine Quelle laufen, um Fehler frühzeitig zu erkennen, bevor ein globales Upgrade fremde, ungeprüfte Pakete einspielt. Repositories, die nach Projektende oder Abkündigung nicht mehr aktiv gepflegt werden, sollten zeitnah wieder aus /etc/apt/sources.list.d/ entfernt werden, weil veraltete Signierschlüssel und tote Endpunkte sonst zu stillen Sicherheitslücken werden.


#!/usr/bin/env bash
set -euo pipefail

# Download the vendor key and verify its fingerprint before trusting it
curl -fsSL https://packages.ondrej.dev/apt/gpg.key -o /tmp/ondrej.asc
gpg --show-keys --with-fingerprint /tmp/ondrej.asc

# Expected fingerprint (compare against the vendor's published documentation)
# 4F4EA0AAE5267A6C41AD8AF52930147C0357222E

# Convert to binary keyring format, store in a dedicated, package-specific location
mkdir -p /etc/apt/keyrings
gpg --dearmor -o /etc/apt/keyrings/ondrej-php.gpg /tmp/ondrej.asc
chmod 644 /etc/apt/keyrings/ondrej-php.gpg
rm -f /tmp/ondrej.asc

# Update only this one source first, to catch errors before a full upgrade
apt-get update -o Dir::Etc::sourcelist="sources.list.d/php.sources" \
                -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0"

6. Der APT-Cache: Funktionsweise und Speicherort

APT unterhält zwei völlig unterschiedliche Caches, die häufig verwechselt werden. Der erste liegt in /var/lib/apt/lists/ und enthält die heruntergeladenen Paketindizes aus apt update, also Metadaten über verfügbare Versionen, aber keine ausführbaren Programme. Der zweite liegt in /var/cache/apt/archives/ und enthält die tatsächlich heruntergeladenen .deb-Dateien jedes installierten oder aktualisierten Pakets. APT löscht diese Archivdateien nach einer erfolgreichen Installation standardmäßig nicht automatisch, sondern behält sie für den Fall, dass ein Paket erneut installiert, auf eine ältere Version zurückgesetzt oder offline auf einem anderen System benötigt wird.

Auf langlebigen Servern, die über Jahre regelmäßig aktualisiert werden, kann dieser Archiv-Cache mehrere Gigabyte erreichen, insbesondere bei Systemen mit vielen großen Paketen wie Datenbank-Servern oder Kernel-Images, von denen jede installierte Version separat vorgehalten wird. Mit du -sh /var/cache/apt/archives lässt sich die aktuelle Größe schnell prüfen. In Docker-Images ist dieser Cache besonders unerwünscht, weil er die Image-Größe unnötig aufbläht, weshalb Dockerfiles typischerweise rm -rf /var/lib/apt/lists/* direkt nach dem apt-get install-Befehl in derselben Layer-Anweisung ausführen, um den Index-Cache gar nicht erst im finalen Image zu belassen.

7. Cache aufräumen: apt clean, autoclean, autoremove

Die drei Aufräum-Befehle von APT unterscheiden sich in Umfang und Sicherheit erheblich, werden aber oft synonym verwendet. apt clean löscht sämtliche .deb-Dateien aus /var/cache/apt/archives/ restlos, unabhängig davon, ob die enthaltene Version noch aktuell oder installiert ist. apt autoclean ist vorsichtiger und entfernt ausschließlich Archivdateien von Paketversionen, die nicht mehr aus dem konfigurierten Repository heruntergeladen werden können, weil sie durch eine neuere Version ersetzt wurden. Für Server mit begrenztem Speicherplatz und regelmäßigen Backups ist autoclean als Cronjob die risikoärmere Wahl, weil aktuell installierbare Versionen im Cache erhalten bleiben.

apt autoremove löst ein anderes Problem: Es entfernt Pakete, die ursprünglich als Abhängigkeit eines anderen Pakets automatisch installiert wurden, inzwischen aber von keinem installierten Paket mehr benötigt werden, etwa alte Kernel-Versionen nach mehreren Kernel-Updates. Mit dem Zusatz --purge werden dabei zusätzlich die Konfigurationsdateien in /etc entfernt, nicht nur die Programmdateien, was bei sensiblen Diensten vorher geprüft werden sollte. Eine sinnvolle Kombination für einen wöchentlichen Wartungs-Cronjob ist apt-get autoremove --purge -y && apt-get autoclean -y, das verwaiste Abhängigkeiten und veraltete Cache-Dateien entfernt, ohne noch installierbare, aktuelle Paketversionen im Archiv-Cache zu löschen.


# ansible/playbooks/apt-maintenance.yaml
# Weekly fleet-wide cache hygiene, orphan removal and drift reporting
- name: APT maintenance across the server fleet
  hosts: magento_servers
  become: true
  tasks:
    - name: Remove orphaned automatically-installed packages
      apt:
        autoremove: true
        purge: true

    - name: Remove outdated archive files, keep currently installable ones
      apt:
        autoclean: true

    - name: Report current archive cache size
      command: du -sh /var/cache/apt/archives
      register: cache_size
      changed_when: false

    - name: Fail loudly if the cache still exceeds 1 GiB after cleanup
      fail:
        msg: "APT cache too large: {{ cache_size.stdout }}"
      when: "'G' in cache_size.stdout and (cache_size.stdout.split('G')[0] | float) > 1.0"

8. Typische Fehler und wie man sie erkennt

Die Meldung E: Unmet dependencies erscheint, wenn ein installiertes oder zur Installation vorgesehenes Paket eine Abhängigkeit benötigt, die im aktuellen Systemzustand nicht erfüllbar ist, häufig nach manuellem dpkg -i einer inkompatiblen Paketdatei oder nach einem abgebrochenen Upgrade. Der Befehl apt --fix-broken install berechnet einen Reparaturplan, der fehlende Abhängigkeiten nachinstalliert oder inkompatible Pakete entfernt, um einen konsistenten Zustand wiederherzustellen. Wurde ein Upgrade durch einen Systemabsturz oder ein Ctrl-C unterbrochen, meldet APT häufig dpkg was interrupted, was sich mit sudo dpkg --configure -a beheben lässt, das alle halbfertig konfigurierten Pakete zu Ende konfiguriert.

Ein zweites häufiges Rätsel: Ein Paket wird trotz apt upgrade nicht aktualisiert, obwohl eine neuere Version im Repository verfügbar ist. Die Ursache ist meist ein vergessener Hold-Status oder eine zu aggressive Pin-Regel. apt-mark showhold listet alle gehaltenen Pakete auf einen Blick, apt-cache policy paketname zeigt zusätzlich die effektive Priorität aus allen greifenden Pin-Regeln inklusive der jeweiligen Quelle. Bei tiefergehenden Auflösungsproblemen liefert apt-get install paketname -o Debug::pkgProblemResolver=true eine detaillierte Ausgabe des internen Resolver-Algorithmus, die zeigt, welche Kandidaten aus welchem Grund verworfen wurden, was bei komplexen Konfliktketten oft der einzige Weg zur eigentlichen Ursache ist.

9. APT-Werkzeuge im Vergleich

Die Wahl zwischen den verschiedenen APT-Werkzeugen und -Mustern hat direkte Auswirkungen auf Sicherheit, Skriptierbarkeit und Nachvollziehbarkeit im Serverbetrieb. Die folgende Tabelle fasst die wichtigsten Entscheidungen zusammen, die in der Praxis regelmäßig falsch getroffen werden.

Aufgabe Unsicher / Riskant Empfohlenes Muster Vorteil
Paket in Skripten installieren apt install (instabile CLI) apt-get install Stabile, seit Jahrzehnten unveränderte Schnittstelle
Paketversion sperren apt-mark hold ohne Dokumentation Pin-Priority in preferences.d Granular, nachvollziehbar, versionierbar
Fremdschlüssel einbinden apt-key add (deprecated) Signed-By Keyring in /etc/apt/keyrings Vertrauen gilt nur der einen Quelle
Cache leeren rm -rf /var/cache/apt/archives/* apt-get clean / autoclean APT-Status bleibt konsistent
Abhängigkeitsfehler beheben dpkg -i --force-depends apt --fix-broken install Berechnet einen konsistenten Reparaturplan

In der Praxis zeigt sich: Fast jede unsichere Spalte in der Tabelle entspricht einem Muster, das kurzfristig funktioniert, aber langfristig zu inkonsistenten oder schwer nachvollziehbaren Systemzuständen führt. Wer APT-Kommandos konsequent nach den empfohlenen Mustern einsetzt und Repository- sowie Pin-Konfiguration versioniert in einem Konfigurationsmanagement wie Ansible pflegt, reduziert Drift zwischen Servern erheblich und macht jede Paketentscheidung im Nachhinein nachvollziehbar.

Mironsoft

Server-Absicherung, Paketmanagement und Deployment-Infrastruktur für Magento-Hosting

Reproduzierbare Server-Umgebungen für euren Magento-Stack?

Wir richten versionsfeste, nachvollziehbare Paketverwaltung für PHP, MySQL/MariaDB und Systemdienste ein, mit sauberem Repository-Management, gezieltem Pinning und automatisierter Cache-Hygiene für stabile Deployments.

Repository-Absicherung

Signed-By Keyrings statt apt-key, geprüfte Drittanbieter-Quellen für euren Stack

Versions-Pinning

PHP-, MySQL- und Kernel-Versionen gezielt fixieren, Kompatibilität mit Magento sichern

Server-Automatisierung

Ansible-gestützte, versionierte Paketkonfiguration über die gesamte Server-Flotte

10. Zusammenfassung

Die wichtigsten Punkte zum APT-Paketmanagement im Überblick: apt update befüllt die lokalen Paketindizes in /var/lib/apt/lists/, ohne selbst etwas zu installieren. dpkg installiert einzelne .deb-Dateien ohne Abhängigkeitsauflösung, apt und apt-get bauen als Frontends darauf auf, wobei apt-get die stabile, skriptsichere Schnittstelle bleibt. Pinning über /etc/apt/preferences.d/ steuert Paketversionen granular über Prioritäten, signed-by Keyrings in /etc/apt/keyrings/ ersetzen das veraltete apt-key, und apt clean, autoclean sowie autoremove halten den Paket-Cache und die installierte Paketliste schlank.

Der größte Hebel liegt in der konsequenten Anwendung dieser Muster über die gesamte Server-Flotte hinweg, statt sie einmalig auf einem einzelnen Server manuell umzusetzen. Repository-Definitionen, Pin-Dateien und Wartungs-Cronjobs gehören in ein Konfigurationsmanagement wie Ansible, damit jede Server-Instanz denselben, nachvollziehbaren Paketzustand hat und ein Kompatibilitätsproblem nicht erst nach einem unkontrollierten Major-Upgrade auf einem einzelnen Server auffällt.

APT-Paketmanagement im Detail: Das Wichtigste auf einen Blick

Schichtenarchitektur

dpkg installiert .deb-Dateien ohne Auflösung, apt/apt-get lösen Abhängigkeiten. apt für interaktiv, apt-get für Skripte.

Pinning

Pin-Priority in preferences.d: 1000 erzwingt, 500 ist Standard. apt-mark hold für einfache Fälle ohne Datei.

Third-Party-Repos

Signed-By Keyring statt apt-key, Fingerprint gegen Herstellerdokumentation prüfen, bevor die Quelle eingebunden wird.

Cache-Hygiene

autoclean statt clean für risikoarme Wartung. autoremove --purge entfernt verwaiste Abhängigkeiten inklusive Konfiguration.

11. FAQ: APT-Paketmanagement im Detail

1Was ist der Unterschied zwischen apt und apt-get?
apt bündelt die gebräuchlichsten Funktionen von apt-get und apt-cache in einem benutzerfreundlicheren Frontend. apt-get bietet eine stabile Schnittstelle für Skripte.
2Warum kein apt in Skripten verwenden?
Die apt-Manpage warnt: die CLI von apt ist instabil und kann sich ändern. apt-get und apt-cache bieten seit Jahrzehnten eine stabile Schnittstelle.
3Wie aktualisiere ich nur die Paketliste?
Mit apt update. Lädt nur die Indizes neu, ohne ein Paket zu installieren oder zu verändern.
4Pin-Priority 1000 vs. 500?
1000 erzwingt sogar ein Downgrade. 500 ist der Standardwert für normal konfigurierte Quellen ohne besondere Regel.
5Paket vor Upgrades schützen?
apt-mark hold paketname für den einfachen Fall. Für feinere Kontrolle eine Pin-Priority-Datei in preferences.d anlegen.
6Warum ist apt-key veraltet?
Ein importierter Schlüssel gilt systemweit für alle Quellen. Signed-By Keyrings binden das Vertrauen stattdessen an eine einzelne Quelle.
7apt clean vs. apt autoclean?
clean löscht restlos alles. autoclean entfernt nur Archivdateien nicht mehr herunterladbarer, ersetzter Versionen.
8Wann apt autoremove nutzen?
Regelmäßig, um verwaiste Abhängigkeiten wie alte Kernel-Versionen zu entfernen. Mit --purge fallen auch Konfigurationsdateien weg.
9E: Unmet dependencies beheben?
apt --fix-broken install berechnet einen Reparaturplan. Bei unterbrochenem Upgrade hilft zusätzlich dpkg --configure -a.
10Wo liegt der APT-Cache?
Indizes in /var/lib/apt/lists/, heruntergeladene .deb-Dateien in /var/cache/apt/archives/. Größe regelmäßig mit du -sh prüfen.