Unattended Upgrades: Sicherheitsupdates automatisieren
$
/etc
Unattended Upgrades · APT · Patch-Management · Linux
Unattended Upgrades
Sicherheitsupdates automatisieren, ohne die Kontrolle zu verlieren

Ungepatchte Server sind das häufigste Einfallstor für Angriffe, aber vollautomatische Updates ohne Kontrolle bergen ein eigenes Risiko. Dieser Artikel zeigt, wie unattended-upgrades Sicherheitspatches zuverlässig einspielt, Fehler per E-Mail meldet und Reboots in ein planbares Wartungsfenster verschiebt, statt den Betrieb unvorhersehbar zu unterbrechen.

14 Min. Lesezeit unattended-upgrades · apt-listchanges · systemd-Timer Debian 12 · Ubuntu 22.04/24.04

1. Der Zielkonflikt: gepatcht bleiben vs. Kontrolle behalten

Die Mehrzahl erfolgreicher Server-Kompromittierungen nutzt keine Zero-Day-Lücken, sondern längst bekannte Schwachstellen, für die seit Wochen oder Monaten ein Patch verfügbar ist. Wer Updates nur manuell einspielt, verschiebt das Patchen fast zwangsläufig, weil andere Aufgaben Vorrang bekommen. Unattended Upgrades lösen genau dieses Problem: Sicherheitspatches werden automatisch heruntergeladen und installiert, ohne dass ein Administrator jeden einzelnen Server einzeln pflegen muss.

Der Preis für diese Automatisierung ist ein reales Risiko: Ein fehlerhaftes Update kann einen Dienst destabilisieren, eine Konfigurationsdatei überschreiben oder einen unerwarteten Neustart eines Kernel-Pakets auslösen. Die Lösung ist nicht, auf Automatisierung zu verzichten, sondern sie gezielt einzugrenzen: nur Security-Repositories automatisch patchen, Fehler sofort per E-Mail melden und Neustarts in ein planbares Wartungsfenster verschieben. So bleibt der Server aktuell, ohne dass ein Update um drei Uhr morgens unbemerkt einen Produktionsdienst lahmlegt.

Dieser Artikel behandelt die Konfiguration von unattended-upgrades auf Debian- und Ubuntu-basierten Systemen, von der Grundinstallation über die Beschränkung auf sicherheitsrelevante Pakete bis zur sauberen Trennung von automatischem Patchen und kontrolliertem Reboot.

2. Installation und Grundkonfiguration

Das Paket unattended-upgrades ist auf Ubuntu-Servern meist bereits vorinstalliert, auf Debian muss es explizit nachinstalliert werden. Nach der Installation aktiviert dpkg-reconfigure im interaktiven Modus die automatischen Updates und legt die Basiskonfiguration in /etc/apt/apt.conf.d/20auto-upgrades an. Diese Datei steuert zwei grundlegende Schalter: ob apt-get update täglich automatisch läuft und ob unattended-upgrade anschließend Pakete installiert.

Die eigentliche Logik steckt in /etc/apt/apt.conf.d/50unattended-upgrades. Diese Datei ist von Haus aus umfangreich kommentiert, aber die Standardwerte sind für Produktionsserver zu großzügig: Ohne Anpassung installiert das Paket unter Umständen auch Updates aus dem regulären -updates-Repository, nicht nur aus -security. Wer die Datei einmal grundlegend versteht, kann sie danach gezielt auf den eigenen Risikoappetit zuschneiden, statt sich auf Distributionsvoreinstellungen zu verlassen.


#!/usr/bin/env bash
# Install and enable unattended-upgrades on a fresh Debian/Ubuntu server
set -euo pipefail

apt-get update
apt-get install -y unattended-upgrades apt-listchanges

# Enable the daily systemd timer / cron entry
dpkg-reconfigure -plow unattended-upgrades

# Verify the base toggle file was written correctly
cat /etc/apt/apt.conf.d/20auto-upgrades
# APT::Periodic::Update-Package-Lists "1";
# APT::Periodic::Unattended-Upgrade "1";

# Confirm the service and timer are active
systemctl status unattended-upgrades.service --no-pager
systemctl list-timers apt-daily-upgrade.timer

Ein Detail, das häufig übersehen wird: apt-listchanges zeigt vor jedem Upgrade eine Zusammenfassung der Changelog-Eintraege betroffener Pakete an. In Kombination mit unattended-upgrades landet diese Zusammenfassung automatisch in der E-Mail-Benachrichtigung aus Abschnitt 5, was die Nachvollziehbarkeit erheblich verbessert. Ohne dieses Paket sieht man im Log nur Paketnamen und Versionsnummern, aber keinen Hinweis darauf, welches konkrete Sicherheitsproblem behoben wurde.

3. Nur Sicherheitsupdates: Origins-Pattern richtig setzen

Der Kern der Risikobegrenzung liegt im Block Unattended-Upgrade::Origins-Pattern in 50unattended-upgrades. Standardmäßig enthält diese Liste bei manchen Distributionen bereits mehr als nur Security-Updates. Für einen konservativen Ansatz, der ausschließlich sicherheitsrelevante Patches automatisch einspielt, muss die Liste auf die -security-Suite reduziert werden. Auf Debian-Systemen lautet das relevante Origin-Muster origin=Debian,codename=${distro_codename}-security, auf Ubuntu origin=Ubuntu,archive=${distro_codename}-security.

Wichtig ist, alle anderen Zeilen mit -updates, -proposed oder -backports auszukommentieren, wenn wirklich nur Security-Patches automatisch laufen sollen. Feature-Updates aus dem regulären -updates-Kanal können neue Funktionsversionen oder Verhaltensänderungen mitbringen, die man bewusst und manuell testen möchte, bevor sie auf Produktionssystemen landen. Diese Trennung ist der wichtigste einzelne Konfigurationsschritt, um den Zielkonflikt aus Abschnitt 1 aufzulösen.


// /etc/apt/apt.conf.d/50unattended-upgrades
// Restrict automatic installs to security-only origins

Unattended-Upgrade::Origins-Pattern {
    "origin=Debian,codename=${distro_codename}-security";
    "origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
    // Regular point releases stay disabled, test manually first
    // "origin=Debian,codename=${distro_codename}-updates";
    // "origin=Debian,codename=${distro_codename}-proposed-updates";
};

// Remove unused dependencies after a successful upgrade run
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";

// Keep at most 2 old kernel versions on disk
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

4. Zeitplan: von der Cron-Datei zum systemd-Timer

Auf aktuellen Debian- und Ubuntu-Versionen wird unattended-upgrades nicht mehr über eine klassische Crontab gesteuert, sondern über den systemd-Timer apt-daily-upgrade.timer, der wiederum den Service apt-daily-upgrade.service auslöst. Dieser Timer ist standardmäßig auf einen zufälligen Zeitpunkt pro Tag mit einem RandomizedDelaySec gesetzt, damit nicht alle Server einer Flotte gleichzeitig auf dieselben Paketspiegel zugreifen. Für einzelne Server ist das unproblematisch, in größeren Umgebungen mit gemeinsamem Spiegel-Server verhindert die Randomisierung Lastspitzen.

Wer den Zeitpunkt präziser steuern will, etwa um Patch-Läufe außerhalb der Hauptgeschäftszeiten zu erzwingen, überschreibt den Timer mit einer Drop-in-Datei statt die Systemdatei direkt zu editieren. Das korrekte Pattern dafür ist systemctl edit apt-daily-upgrade.timer, das automatisch eine Override-Datei unter /etc/systemd/system/apt-daily-upgrade.timer.d/ anlegt und beim nächsten Paket-Update nicht überschrieben wird.


# /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf
# Created via: systemctl edit apt-daily-upgrade.timer
# Pin the upgrade run to a fixed early-morning slot instead of a random one

[Timer]
OnCalendar=
OnCalendar=*-*-* 04:15:00
RandomizedDelaySec=300
Persistent=true

5. E-Mail-Benachrichtigungen bei Fehlern konfigurieren

Automatisierung ohne Rückmeldung ist blindes Vertrauen. Der Block Unattended-Upgrade::Mail in 50unattended-upgrades sendet standardmäßig gar keine E-Mail, es sei denn, man trägt eine Adresse ein. Mit Unattended-Upgrade::MailOnlyOnError "true" beschränkt man den Versand auf fehlgeschlagene Läufe, statt täglich eine Erfolgsmeldung zu bekommen, die nach wenigen Tagen ohnehin ignoriert wird. Diese Kombination ist der Sweet Spot: Stille bedeutet Erfolg, eine E-Mail bedeutet sofortigen Handlungsbedarf.

Voraussetzung ist ein funktionierender Mail-Transport auf dem Server. Ein minimaler msmtp- oder postfix-Relay reicht aus, damit /usr/sbin/sendmail tatsächlich zustellt. Ein häufiger Fehler in der Praxis: Die Konfiguration sieht korrekt aus, aber der Server hat gar keinen funktionierenden Mailversand, und Fehler verpuffen unbemerkt. Ein Testlauf mit absichtlich blockiertem Paket deckt das zuverlässig auf, bevor man sich auf die Benachrichtigung verlässt.


// /etc/apt/apt.conf.d/50unattended-upgrades
// Send mail only when something actually goes wrong

Unattended-Upgrade::Mail "ops-alerts@mironsoft.de";
Unattended-Upgrade::MailOnlyOnError "true";
Unattended-Upgrade::Sender "root@$(hostname -f)";

// Verbosity of the report attached to failure mails
Unattended-Upgrade::Verbose "true";
Unattended-Upgrade::Debug "false";

#!/usr/bin/env bash
# Force a dry-run failure to verify the mail pipeline actually delivers
set -euo pipefail

# Simulate an upgrade run without installing anything
unattended-upgrade --dry-run --debug 2>&1 | tee /tmp/uu-dryrun.log

# Send a manual test mail through the same transport used by cron/systemd
echo "Test: unattended-upgrades mail delivery" | \
  mail -s "[TEST] unattended-upgrades on $(hostname -f)" ops-alerts@mironsoft.de

# Check the mail queue for delivery problems
mailq

6. Pakete gezielt ausschließen und Versionssperren setzen

Manche Pakete sollen selbst bei einem als sicherheitsrelevant eingestuften Update niemals automatisch aktualisiert werden, etwa die Datenbank-Engine oder der PHP-Interpreter, wenn eine Major-Version-Kompatibilität zu einer produktiven Anwendung besteht. Unattended-Upgrade::Package-Blacklist akzeptiert Regex-Muster und schließt passende Pakete vollständig von automatischen Updates aus, unabhängig vom Origin. Das ist bewusst grob: Ein einmal geblacklistetes Paket muss danach manuell gepflegt werden, sonst häufen sich unbemerkt offene Sicherheitslücken an.

Eine feinere Alternative ist APT Pinning über /etc/apt/preferences.d/, das statt eines kompletten Ausschlusses eine maximale Versionsgrenze setzt. Damit lassen sich Patch-Level-Updates innerhalb einer Major-Version weiterhin automatisch einspielen, während ein Versionssprung, der Breaking Changes mitbringen könnte, blockiert bleibt. Diese Kombination aus Blacklist für kritische Kernkomponenten und Pinning für alles andere ist in produktiven Umgebungen der robusteste Ansatz.


// /etc/apt/apt.conf.d/50unattended-upgrades
// Never auto-update the database engine or the active PHP runtime

Unattended-Upgrade::Package-Blacklist {
    "mysql-server-*";
    "mariadb-server-*";
    "php8.3-*";
};

# /etc/apt/preferences.d/pin-nginx.pref
# Allow patch-level updates, block the next major version jump

Package: nginx nginx-common nginx-core
Pin: version 1.24.*
Pin-Priority: 1001

7. Reboots in ein kontrolliertes Wartungsfenster legen

Kernel-Updates, glibc-Patches und einige OpenSSL-Aktualisierungen erfordern einen Neustart, damit die neue Version tatsächlich aktiv wird. Der schlimmste Fall ist ein Server, der wochenlang mit installiertem, aber nicht aktivem Sicherheitspatch läuft, weil niemand den fälligen Reboot bemerkt. Der zweitschlimmste Fall ist ein Server, der automatisch um eine unvorhersehbare Uhrzeit neu startet und dabei aktive Nutzersitzungen oder laufende Batch-Jobs unterbricht. Die Lösung ist, den Reboot zwar zu automatisieren, aber strikt an ein festes Wartungsfenster zu binden.

Die Optionen Unattended-Upgrade::Automatic-Reboot und Unattended-Upgrade::Automatic-Reboot-Time steuern genau das: Ein Reboot wird nur ausgeführt, wenn /var/run/reboot-required existiert, und zwar erst zum konfigurierten Zeitpunkt, nicht sofort nach dem Update. Zusätzlich lohnt sich ein eigener systemd-Timer, der unabhängig vom Update-Lauf prüft, ob ein Reboot aussteht, und diesen kontrolliert mit Vorwarnzeit für angemeldete Nutzer durchführt. So bleibt der Automatisierungsgrad hoch, ohne die Vorhersehbarkeit für den Betrieb zu opfern.


// /etc/apt/apt.conf.d/50unattended-upgrades
// Reboot only when actually required, and only inside the maintenance window

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";
Unattended-Upgrade::Automatic-Reboot-Time "04:30";

#!/usr/bin/env bash
# maintenance-reboot.sh: independent check, run inside a fixed window
set -euo pipefail

if [[ ! -f /var/run/reboot-required ]]; then
  echo "[OK] No reboot pending, nothing to do"
  exit 0
fi

echo "[INFO] Reboot required, packages:"
cat /var/run/reboot-required.pkgs 2>/dev/null || true

# Warn logged-in users 5 minutes ahead, then reboot
wall "Maintenance reboot for security updates in 5 minutes."
sleep 300
systemctl reboot

8. Logging, Trockenlauf und laufende Kontrolle

Jeder Lauf von unattended-upgrades schreibt ein detailliertes Protokoll nach /var/log/unattended-upgrades/unattended-upgrades.log sowie eine kompakte Zusammenfassung installierter Pakete nach unattended-upgrades-dpkg.log. Diese beiden Dateien sind die erste Anlaufstelle bei der Fehlersuche, wenn eine E-Mail-Benachrichtigung eingegangen ist oder ein Dienst nach einem nächtlichen Update unerwartetes Verhalten zeigt. Da beide Logs mit der Zeit wachsen, gehört eine logrotate-Konfiguration mit Kompression und einer sinnvollen Aufbewahrungsfrist zur Grundausstattung, nicht erst nach dem ersten vollgelaufenen /var/log.

Vor jeder Änderung an der Konfiguration lohnt sich ein Trockenlauf mit unattended-upgrade --dry-run --debug, der exakt zeigt, welche Pakete anhand der aktuellen Origins-Pattern und Blacklist tatsächlich aktualisiert würden, ohne etwas zu installieren. Dieser Befehl ist auch das richtige Werkzeug, um nach einer Anpassung der Security-Only-Filterung aus Abschnitt 3 zu verifizieren, dass wirklich nur die gewünschten Pakete erfasst werden, bevor der nächste automatische Lauf startet.


# /etc/logrotate.d/unattended-upgrades
# Keep six months of compressed history for audit and incident review

/var/log/unattended-upgrades/*.log {
    monthly
    rotate 6
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root adm
}

9. Automatisierungsgrade im direkten Vergleich

Zwischen komplett manuellem Patchen und vollautomatischen Updates ohne jede Einschränkung liegt ein breites Spektrum an Konfigurationsoptionen. Die folgende Übersicht stellt die gängigen Automatisierungsgrade gegenüber und zeigt, welcher Ansatz für Produktionsserver empfehlenswert ist.

Ansatz Risiko Empfehlung Begründung
Rein manuelles Patchen Patches bleiben wochenlang aus Nicht empfohlen Bekannte Lücken bleiben offen, weil Zeit fehlt
Alle Repositories automatisch Feature-Updates ohne Test Nicht empfohlen Breaking Changes landen ungeplant in Produktion
Security-only, ohne Mail Fehlgeschlagene Updates unbemerkt Bedingt geeignet Kein Feedback-Kanal bei Problemen
Security-only + Mail bei Fehlern Gering Empfohlen Automatisch gepatcht, Fehler sofort sichtbar
+ festes Reboot-Wartungsfenster Sehr gering Best Practice Patches aktiv, Neustarts planbar statt überraschend

In der Praxis ist die Kombination aus Security-only-Filterung, fehlerbasierter E-Mail-Benachrichtigung und einem festen Reboot-Fenster der Ansatz, der Automatisierungsgrad und Kontrolle am besten ausbalanciert. Wer diese drei Bausteine konsequent kombiniert, reduziert sowohl das Risiko ungepatchter Lücken als auch das Risiko unkontrollierter Ausfälle durch fehlerhafte Updates auf ein Minimum.

Mironsoft

Server-Hardening, Patch-Management und Linux-Betrieb für Magento-Infrastruktur

Server zuverlässig patchen, ohne Überraschungen?

Wir richten unattended-upgrades produktionstauglich ein: Security-only-Filterung, Fehlerbenachrichtigung per Mail und ein festes Wartungsfenster für Reboots, abgestimmt auf eure Magento- und Infrastruktur-Landschaft.

Patch-Audit

Bestehende Update-Konfiguration prüfen und Lücken identifizieren

Automatisierung

Security-only-Updates, Blacklist und Mail-Alerts produktionsreif konfigurieren

Wartungsfenster

Kontrollierte Reboot-Fenster in bestehende Deployment-Prozesse integrieren

10. Zusammenfassung

Unattended Upgrades lösen den Zielkonflikt zwischen konstant gepatchten Servern und der Angst vor unkontrollierten Nebenwirkungen durch gezielte Eingrenzung statt durch Verzicht auf Automatisierung. Die Beschränkung auf -security-Origins in Unattended-Upgrade::Origins-Pattern verhindert, dass ungetestete Feature-Updates automatisch installiert werden. MailOnlyOnError sorgt dafür, dass Stille Erfolg bedeutet und jede E-Mail sofortigen Handlungsbedarf signalisiert. Eine Package-Blacklist schützt kritische Kernkomponenten wie Datenbank und Laufzeitumgebung vor automatischen Eingriffen.

Reboots gehören strikt in ein festes Wartungsfenster, gesteuert über Automatic-Reboot-Time oder einen eigenen systemd-Timer mit Vorwarnzeit für Nutzer. So bleibt der Server durchgehend gepatcht, ohne dass ein Neustart unvorhersehbar mitten am Tag passiert. Regelmäßige Trockenläufe mit --dry-run --debug und eine saubere Logrotate-Konfiguration runden die Konfiguration ab und machen jeden Update-Lauf nachvollziehbar.

Unattended Upgrades automatisieren: Das Wichtigste auf einen Blick

Security-only patchen

Origins-Pattern auf -security beschränken, -updates und -backports auskommentieren.

Fehler per Mail melden

MailOnlyOnError "true" plus funktionierender Mail-Transport, verifiziert mit einem Testlauf.

Kritische Pakete ausschließen

Package-Blacklist für Datenbank und Laufzeitumgebung, APT Pinning für alles andere.

Reboots im Wartungsfenster

Automatic-Reboot-Time auf ein festes, ruhiges Zeitfenster setzen, Nutzer vorwarnen.

11. FAQ: Unattended Upgrades automatisieren

1Was ist unattended-upgrades und wofür wird es eingesetzt?
Ein Debian/Ubuntu-Paket, das definierte APT-Repositories automatisch nach Updates durchsucht und passende Pakete ohne manuelles Eingreifen installiert, vor allem für zeitnahe Sicherheitspatches.
2Wie stelle ich sicher, dass nur Sicherheitsupdates automatisch installiert werden?
Origins-Pattern auf die -security-Suite beschränken, alle Zeilen mit -updates, -proposed oder -backports auskommentieren.
3Wie werde ich benachrichtigt, wenn ein Update fehlschlägt?
Über Unattended-Upgrade::Mail mit Zieladresse und MailOnlyOnError auf true, damit nur bei echten Fehlern eine E-Mail kommt.
4Wie schließe ich einzelne Pakete von automatischen Updates aus?
Über Package-Blacklist mit Regex-Mustern, etwa für Datenbank oder PHP. APT Pinning eignet sich, um nur bestimmte Versionssprünge zu blockieren.
5Wie verhindere ich einen unerwarteten Reboot mitten am Tag?
Automatic-Reboot-Time auf ein festes, verkehrsarmes Zeitfenster setzen, etwa 04:30 Uhr. Reboot läuft nur, wenn wirklich einer aussteht.
6Woran erkenne ich, ob ein Server einen Reboot benötigt?
An der Datei /var/run/reboot-required. reboot-required.pkgs listet die auslösenden Pakete, meist Kernel oder libc6.
7Läuft unattended-upgrades noch über Cron oder über systemd?
Über den systemd-Timer apt-daily-upgrade.timer. Zeitpunkt per systemctl edit apt-daily-upgrade.timer mit Drop-in-Datei anpassbar.
8Wie teste ich die Konfiguration, ohne echte Updates zu installieren?
Mit unattended-upgrade --dry-run --debug. Zeigt genau, welche Pakete installiert würden, ohne etwas zu ändern.
9Wo finde ich die Protokolle abgeschlossener Update-Läufe?
In /var/log/unattended-upgrades/unattended-upgrades.log und unattended-upgrades-dpkg.log, verwaltet über logrotate.
10Ist unattended-upgrades für produktive Magento-Server geeignet?
Ja, mit Blacklist für Datenbank und PHP-Version sowie einem festen Reboot-Wartungsfenster, damit das Betriebssystem gepatcht bleibt, ohne die Anwendung ungeplant zu gefährden.