Unattended Updates: Debian 13 und CachyOS automatisch patchen
Die meisten Sicherheitslücken werden nicht ausgenutzt, weil niemand patcht – sondern weil es zu spät passiert. Automatische Updates sind deshalb keine Bequemlichkeit, sondern Teil der Absicherung. Nur sieht „automatisch“ bei Debian und bei Arch grundlegend anders aus. Dieser Artikel zeigt für beide Welten ein Stufenmodell, die passenden Konfigurationen und fertige Skripte für Timer und Cron – bis hin zu einem Setup-Skript, das die komplette Debian-Einrichtung in einem Lauf erledigt.
Warum automatisch patchen?
Zwischen der Veröffentlichung eines Fixes und dem ersten Angriff darauf vergehen oft nur Stunden. Wer selbst hostet, ist sein eigener Administrator – und genau deshalb funktioniert „das mache ich am Wochenende“ nicht. Zwei Zahlen genügen als Begründung:
- Ein ungepatchter Dienst im Internet ist innerhalb von Stunden im Visier automatischer Scanner – unabhängig davon, ob er irgendwo verlinkt ist.
- Auf einem gewarteten System ist die Zahl der offenen Sicherheitslücken systematisch niedriger als die Zahl der Funktionen, die du eigentlich nutzt.
Was automatische Updates dagegen nicht lösen:
| Erwartung | Realität |
|---|---|
| „Dann muss ich nichts mehr tun.“ | Dienste laufen weiter mit alten Bibliotheken im Speicher, Neustarts bleiben Handarbeit – ohne needrestart merkst du es nicht. |
| „Ein Neustart ist nie nötig.“ | Kernel- und glibc-Updates brauchen ihn. Wer das ignoriert, patcht die Platte, aber nicht den laufenden Kernel. |
| „Konfigurationsdateien aktualisieren sich mit.“ | Bei Debian bekommst du Rückfragen, bei Arch entstehen .pacnew-Dateien. Beides ist Handarbeit und genau der Punkt, an dem Automatik endet. |
| „Updates können nichts kaputt machen.“ | Doch – nur selten. Deshalb steht in diesem Artikel ein Stufenmodell vor jedem Automatik-Skript. |
Das Stufenmodell: melden, laden, installieren
Der entscheidende Denkfehler ist, „automatische Updates“ als einen einzigen Schalter zu betrachten. Es sind vier Stufen – und du darfst selbst entscheiden, bis wohin die Automatik gehen soll. Die riskante Entscheidung ist immer nur die letzte Stufe.
| Stufe | Was passiert | Risiko | Umsetzung |
|---|---|---|---|
| 1 – Melden | Du erfährst, dass Aktualisierungen vorliegen. Am System ändert sich nichts. | keins | checkupdates (Arch), apt list --upgradable (Debian) |
| 2 – Herunterladen | Die Pakete liegen im lokalen Cache, installiert wird später. | keins | pacman -Syuw (Arch), APT::Periodic::Download-Upgradeable-Packages (Debian) |
| 3 – Sicherheitsupdates installieren | Nur Fixes aus der Sicherheitsquelle werden eingespielt. | gering | unattended-upgrades auf Debian |
| 4 – Alles installieren | Vollständiges Upgrade inklusive Funktions- und Versionswechseln. | bei Rolling Releases deutlich höher | pacman -Syu, apt full-upgrade |
unattended-upgrades. Auf Arch/CachyOS gibt es Stufe 3 nicht, weil es keine getrennte
Sicherheitsquelle gibt: Ein RollingleRelease hat nur „alles“ oder „nichts“. Dort ist Stufe 2 die
verantwortungsvolle Automatik – und Stufe 4 bleibt eine bewusste Entscheidung.
Debian 13: unattended-upgrades
Debian bringt alles mit, was man braucht. Der bequeme Weg führt über zwei Befehle:
sudo apt update
sudo apt install unattended-upgrades apt-listchanges needrestart
sudo dpkg-reconfigure -plow unattended-upgrades # fragt: Automatik aktivieren?
Das dpkg-reconfigure legt die Aktivierung an – die eigentliche Steuerung steckt in zwei Dateien:
# /etc/apt/apt.conf.d/20auto-upgrades -> Schalter
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
Die Richtlinie gehört nicht in die mitgelieferte Datei, sondern in eine eigene – sonst überschreibt sie das nächste Paket-Update. Eigene Dateien mit höherer Nummer werden später gelesen und gewinnen:
# /etc/apt/apt.conf.d/52unattended-upgrades-local
// Welche Quellen dürfen automatisch installiert werden?
Unattended-Upgrade::Origins-Pattern {
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};
// Pakete, die NIE automatisch angefasst werden (bewusste Auswahl!)
Unattended-Upgrade::Package-Blacklist {
// "linux-image-.*"; // Kernel nur manuell -> dann aber auch manuell patchen!
// "docker-ce";
// "nginx";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "false";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
Unattended-Upgrade::Mail "root";
Unattended-Upgrade::Mail-Report "only-on-error";
Unattended-Upgrade::SyslogEnable "true";
| Einstellung | Was sie bewirkt – und was du abwägen musst |
|---|---|
Origins-Pattern | Die drei Zeilen entsprechen der Debian-Voreinstellung: label=Debian deckt den Stable-Zweig ab (inkl. Punkt-Updates), die beiden -security-Zeilen die Sicherheitsquelle. Willst du nur Sicherheitsfixes, lösche die erste Zeile – dann bleibt das System ruhiger, Bugfixes kommen aber später. |
Package-Blacklist | Ein zweischneidiges Messer: Ein geblacklistetes Paket wird nie automatisch und nie automatisch gepatcht. Wer dort linux-image-.* einträgt, muss Kernel-Updates selbst fahren. Deshalb ist die Liste standardmäßig leer. |
AutoFixInterruptedDpkg | Repariert halb abgebrochene Installationen automatisch – wichtig bei Stromausfall oder hartem Neustart. |
Remove-Unused-Dependencies | false ist die vorsichtige Wahl: Ein autoremove zur falschen Zeit kann Pakete mitnehmen, die du als Abhängigkeit installiert hast. Aufräumen gehört in den Wartungslauf, nicht in das Update. |
Automatic-Reboot | false plus Benachrichtigung ist für Server die richtige Wahl. true mit Uhrzeit (03:00) ist bequem, aber du entscheidest damit über die Verfügbarkeit. |
Mail-Report | only-on-error hält still, wenn nichts ist – und meldet sich, wenn etwas fehlschlägt. Gibt es erst in aktuellen Versionen (2.10+). |
Und der Test – ohne dass irgendetwas installiert wird:
sudo unattended-upgrade --dry-run --debug
journalctl -u unattended-upgrades -n 50 --no-pager
tail -n 30 /var/log/unattended-upgrades/unattended-upgrades.log
apt-daily.timer aktualisiert zweimal täglich die Paketlisten,
apt-daily-upgrade.timer spielt die Updates ein (Standard: ab 06:00 mit zufälliger
Verzögerung). Kontrolle:
systemctl list-timers 'apt-daily*'. Den Zeitpunkt verschiebt man mit einem Drop-in –
sudo systemctl edit apt-daily-upgrade.timer – und dort etwa
OnCalendar=*-*-* 04:30 setzen.
Dienste neu starten und Neustart erkennen
Der häufigste Irrtum nach der Einrichtung: „Updates installiert, alles erledigt.“ Ist es nicht. Aktualisiert
werden Dateien auf der Platte – laufende Prozesse arbeiten weiter mit der alten Version
im Speicher. Bei einer Bibliothek wie libssl bedeutet das: der Patch ist installiert, aber
nicht aktiv.
| Problem | Lösung |
|---|---|
| Dienste laufen mit alten Bibliotheken | needrestart prüft das nach jedem apt-Lauf. Standardmäßig fragt es nach – im unbeaufsichtigten Betrieb ist genau das der Fehler. |
| Fragen bleiben unbeantwortet | In /etc/needrestart/conf.d/50-unattended.conf den Automatikmodus setzen (siehe Skript unten). |
| Neuer Kernel, alter Kernel läuft | Neustart erforderlich – erkennbar an /var/run/reboot-required (Debian) bzw. am Kernel-Vergleich (universell, siehe Skript 3). |
Ein Einrichtungs-Skript, das die wichtigsten Punkte in einem Zug setzt:
#!/usr/bin/env bash
# /usr/local/bin/unattended-setup-debian.sh - einmalig als root ausfuehren
set -euo pipefail
[ "$(id -u)" -eq 0 ] || { echo "Bitte als root ausfuehren."; exit 1; }
echo "== 1/6 Pakete =="
apt-get update
apt-get install -y unattended-upgrades apt-listchanges needrestart
echo "== 2/6 Schalter setzen =="
cat > /etc/apt/apt.conf.d/20auto-upgrades << 'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
EOF
echo "== 3/6 Richtlinie (eigene Datei, update-sicher) =="
cat > /etc/apt/apt.conf.d/52unattended-upgrades-local << 'EOF'
Unattended-Upgrade::Origins-Pattern {
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "false";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Mail "root";
Unattended-Upgrade::Mail-Report "only-on-error";
Unattended-Upgrade::SyslogEnable "true";
EOF
echo "== 4/6 Dienste automatisch neu starten =="
mkdir -p /etc/needrestart/conf.d
cat > /etc/needrestart/conf.d/50-unattended.conf << 'EOF'
# 'a' = automatisch neu starten, ohne Rueckfrage
$nrconf{restart} = 'a';
EOF
echo "== 5/6 Timer aktivieren =="
systemctl enable --now apt-daily.timer apt-daily-upgrade.timer
systemctl list-timers 'apt-daily*' --no-pager
echo "== 6/6 Probelauf =="
unattended-upgrade --dry-run --debug | tail -n 25
echo "Fertig. Log: /var/log/unattended-upgrades/unattended-upgrades.log"
restart = 'a' ist eine Entscheidung mit Folgen. Ein Dienst, der mitten in
einer Transaktion neu startet, kann eine laufende Verarbeitung abbrechen. Für Webserver, Nextcloud oder
Datenbanken ist das meist unkritisch – für alles, was gerade einen langen Job ausführt, nicht. Wer es
kontrollierter will, lässt restart auf der Voreinstellung und liest stattdessen die Liste,
die needrestart ins Journal schreibt.
Alles in einem: das Setup-Skript
Wer die Einrichtung nicht in sechs Einzelschritten nachbauen will, nimmt ein Skript. Das folgende stammt
aus einem Laptop-Setup und war ursprünglich für Ubuntu mit xtradeb-PPA
geschrieben – hier ist es auf Debian 13 portiert, um needrestart ergänzt und
so aufgebaut, dass es den kompletten Ablauf der beiden vorigen Abschnitte in einem Lauf erledigt.
| Im Ubuntu-Original | Auf Debian 13 | Grund |
|---|---|---|
Allowed-Origins mit ${distro_id}:${distro_codename}-security und ESM-Zeilen | Origins-Pattern mit origin=Debian,label=Debian-Security | ESM (Extended Security Maintenance) ist ein Ubuntu-Abo-Modell; Debian verwendet die offizielle Vorlage mit origin/label. |
LP-PPA-xtradeb-apps, LP-PPA-remmina-…, LP-PPA-cappelikan | weggelassen – oder als "origin=<Name>"; für die eigene Fremdquelle | PPAs sind Ubuntu-only. Auf Debian existieren diese Quellen nicht; die Zeilen wären wirkungslos. |
Überschreibt die mitgelieferte 50unattended-upgrades | Eigene Datei 52unattended-upgrades-local | Die 50er ist eine conffile des Pakets: Wer sie überschreibt, bekommt bei jedem Paketupdate eine Rückfrage. |
Nur unattended-upgrades und apt-listchanges | Zusätzlich needrestart im Automatikmodus | Ohne Dienst-Neustart bleibt der Patch auf der Platte liegen, während der alte Code im Speicher weiterläuft. |
Remove-Unused-Dependencies "true" im Update-Lauf | "false" – aufgeräumt wird in clean.sh | Patchen und Aufräumen trennen: Ein autoremove zur falschen Zeit nimmt gern Pakete mit, die du bewusst installiert hast. |
OnlyOnACPower "true" | übernommen – auf Servern aber "false" | Die Option ist für Laptops gedacht: Updates nur am Netzteil. |
#!/usr/bin/env bash
# setup_updates.sh - Automatische Updates und Wartung auf Debian 13 einrichten
# Einmalig als root ausfuehren: sudo bash setup_updates.sh
set -euo pipefail
[ "$(id -u)" -eq 0 ] || { echo "Bitte als root ausfuehren."; exit 1; }
echo "=================================================="
echo " Automatisches Update-Setup: Debian 13"
echo "=================================================="
# 1) Erforderliche Pakete installieren
echo "[1/6] Installiere unattended-upgrades, apt-listchanges, needrestart ..."
apt-get update
apt-get install -y unattended-upgrades apt-listchanges needrestart
# 2) Schalter setzen
echo "[2/6] Schreibe /etc/apt/apt.conf.d/20auto-upgrades ..."
cat << 'EOF' > /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
EOF
# 3) Richtlinie - eigene Datei statt der mitgelieferten 50er
echo "[3/6] Schreibe /etc/apt/apt.conf.d/52unattended-upgrades-local ..."
cat << 'EOF' > /etc/apt/apt.conf.d/52unattended-upgrades-local
Unattended-Upgrade::Origins-Pattern {
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
# "origin=xtradeb"; # Fremdquelle: Namen mit apt-cache policy ermitteln
};
Unattended-Upgrade::Package-Blacklist { };
Unattended-Upgrade::DevRelease "false";
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::MinimalSteps "true";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "false"; # Aufraeumen macht clean.sh
Unattended-Upgrade::Automatic-Reboot "false"; # Server: so lassen
Unattended-Upgrade::OnlyOnACPower "true"; # Laptop; Server: "false"
Unattended-Upgrade::Mail "root";
Unattended-Upgrade::Mail-Report "only-on-error";
Unattended-Upgrade::SyslogEnable "true";
EOF
# 4) needrestart unbeaufsichtigt schalten
echo "[4/6] Setze needrestart auf Automatikmodus ..."
mkdir -p /etc/needrestart/conf.d
cat << 'EOF' > /etc/needrestart/conf.d/50-unattended.conf
# 'a' = Dienste nach dem Update automatisch neu starten, ohne Rueckfrage
$nrconf{restart} = 'a';
EOF
# 5) Timer-Takt verdichten (2 h / 4 h) - fuer Laptops ohne feste Laufzeiten
echo "[5/6] Erstelle systemd-Timer-Overrides ..."
mkdir -p /etc/systemd/system/apt-daily.timer.d
cat << 'EOF' > /etc/systemd/system/apt-daily.timer.d/override.conf
[Timer]
OnCalendar=
OnCalendar=*-*-* 00,02,04,06,08,10,12,14,16,18,20,22:00:00
RandomizedDelaySec=15m
Persistent=true
EOF
mkdir -p /etc/systemd/system/apt-daily-upgrade.timer.d
cat << 'EOF' > /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf
[Timer]
OnCalendar=
OnCalendar=*-*-* 01,05,09,13,17,21:00:00
RandomizedDelaySec=15m
Persistent=true
EOF
systemctl daemon-reload
systemctl enable --now apt-daily.timer apt-daily-upgrade.timer
# 6) Wartungs-Skript erstellen und per Cron aufrufen
echo "[6/6] Erstelle /root/clean.sh und trage den Cronjob ein ..."
cat << 'EOF' > /root/clean.sh
#!/usr/bin/env bash
set -euo pipefail
UA_LOG="/var/log/unattended-upgrades/unattended-upgrades.log"
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_message "START: System-Ueberwachung und Bereinigung..."
if [ -f "$UA_LOG" ]; then
if grep -q "ERROR" "$UA_LOG"; then
log_message "!!! ALARM !!! Der automatische Update-Dienst hat Fehler gemeldet! Bitte pruefen: $UA_LOG"
else
log_message "OK: Der automatische Hintergrund-Dienst laeuft fehlerfrei."
fi
if [ -n "$(find "$UA_LOG" -mtime +3 2>/dev/null)" ]; then
log_message "WARNUNG: Seit mehr als 3 Tagen wurden keine automatischen Updates protokolliert."
fi
else
log_message "WARNUNG: Die Logdatei von unattended-upgrades existiert nicht. Laeuft der Dienst?"
fi
log_message "Starte regelmaessige Systembereinigung..."
apt-get autoremove --purge -y
apt-get autoclean
apt-get clean
log_message "ENDE: Bereinigung erfolgreich abgeschlossen."
exit 0
EOF
chmod +x /root/clean.sh
CRON_ENTRY="0 11 * * 1-5 /root/clean.sh >> /var/log/sys_clean.log 2>&1"
(crontab -l 2>/dev/null | grep -Fv "/root/clean.sh"; echo "$CRON_ENTRY") | crontab -
echo "== Probelauf =="
unattended-upgrade --dry-run --debug | tail -n 20
echo "=================================================="
echo " FERTIG! Kontrolle: systemctl list-timers 'apt-daily*'"
echo "=================================================="
| Schritt | Was passiert | Warum so |
|---|---|---|
| 1/6 Pakete | Installiert unattended-upgrades, apt-listchanges und needrestart. | needrestart ist der Teil, der einen Patch überhaupt erst wirksam macht – ohne ihn wird nur die Datei ersetzt. |
| 2/6 Schalter | Schreibt 20auto-upgrades: Listen aktualisieren, Updates einspielen, Pakete vorladen, wöchentlich aufräumen. | Genau diese Datei legt sonst dpkg-reconfigure an – hier schreibt sie das Skript selbst, damit keine Rückfrage kommt. |
| 3/6 Richtlinie | Schreibt die Quellen- und Verhaltensregeln nach 52unattended-upgrades-local. | Eigene Dateien mit höherer Nummer überleben jedes Paketupdate und gewinnen gegen die mitgelieferte 50er. |
| 4/6 needrestart | Setzt $nrconf{restart} = 'a' – Dienste werden ohne Rückfrage neu gestartet. | Unbeaufsichtigt heißt: Es ist niemand da, der eine Rückfrage beantwortet. Die Rückfrage ist der Standardfehler dieser Einrichtung. |
| 5/6 Timer | Überschreibt den Standardtakt: Paketlisten alle zwei Stunden, Installation alle vier Stunden. | Ein Laptop läuft unregelmäßig. Persistent=true holt verpasste Läufe nach, der dichte Takt verkürzt die Lücke zwischen Fix und Installation. |
| 6/6 Wartung | Legt /root/clean.sh an (Logprüfung, autoremove, autoclean) und ruft es werktags um 11:00 per Cron auf. | Der Cron-Eintrag wird vorher gefiltert – so entstehen keine Duplikate, wenn das Skript erneut läuft. |
50unattended-upgrades bearbeiten? Weil das die Datei des
Pakets ist. Debian behandelt sie als conffile: Bei der nächsten Aktualisierung fragt dpkg, ob
deine Änderungen behalten werden sollen – und eine automatisierte Installation kann diese Frage nicht
beantworten. Die eigene Datei mit der Nummer 52 ist ruhiger und bei Updates unsichtbar.
OnlyOnACPower:
Auf einem Laptop sinnvoll (keine Updates im Akkubetrieb), auf einem Server muss der Wert
"false" sein, sonst wartet die Automatik auf ein Netzteil, das es nicht gibt. Zweitens
apt-get autoremove --purge -y in clean.sh: Es entfernt nicht benötigte Pakete
samt Konfiguration – wer das nicht will, lässt --purge weg.
systemctl list-timers 'apt-daily*' zeigt den
neuen Takt, tail -n 20 /var/log/sys_clean.log die Wartungsausgabe und
journalctl -u apt-daily-upgrade -n 30 --no-pager den letzten Updatelauf.
Fremdquellen wie xtradeb mitpatchen
unattended-upgrades rührt nur Quellen an, die im Origins-Pattern stehen. Eine
Fremdquelle wird deshalb nie mitgepatcht, solange sie dort fehlt – genau deshalb enthielt das
ursprüngliche Ubuntu-Skript explizite Zeilen für xtradeb, Remmina und Cappelikan. Auf Debian
ermittelst du den Namen der Quelle selbst:
# 1) Origin-Namen der eingerichteten Fremdquelle ermitteln
apt-cache policy | grep -B1 -A2 -i xtradeb
# Beispielausgabe: release o=xtradeb,a=stable,n=stable,c=main
# -> die Zeichenkette hinter "o=" ist der Origin-Name
# 2) Diese Zeile in den Origins-Pattern-Block eintragen
# /etc/apt/apt.conf.d/52unattended-upgrades-local
Unattended-Upgrade::Origins-Pattern {
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
"origin=xtradeb"; # Fremdquelle, Name aus Schritt 1
};
# 3) Pruefen, ob die Quelle erkannt wird
unattended-upgrade --dry-run --debug | grep -i origin
CachyOS/Arch: warum es anders ist
Auf Arch gibt es kein unattended-upgrades – und das ist kein fehlendes Feature, sondern
Philosophie. Drei Unterschiede, die man verstehen muss, bevor man Automatik baut:
| Unterschied | Konsequenz |
|---|---|
| Keine getrennte Sicherheitsquelle | Es gibt keine „Sicherheitsupdates“, die man isoliert einspielen könnte. Alles kommt aus denselben Repositories – also gibt es nur „alles“ oder „nichts“. |
| Rolling Release | Ein Upgrade bringt regelmäßig neue Hauptversionen. „Ich habe seit vier Monaten nicht aktualisiert“ ist auf Arch kein Ruhezustand, sondern ein wachsendes Risiko. |
| Partial-Upgrade-Verbot | Einzelne Pakete dürfen nie isoliert aktualisiert werden, sonst passen Bibliotheken und Abhängigkeiten nicht mehr zusammen. Deshalb heißt es pacman -Syu – niemals nur -Sy gefolgt von Einzelinstallationen. |
Dazu kommt ein Punkt, der sich nicht automatisieren lässt: Arch-News lesen. Bei
grundlegenden Änderungen (Paketumstellungen, Konfigurationsformate) steht dort vor dem Upgrade, was zu tun
ist. Es gibt ein Werkzeug, das diese Pflicht erzwingt: informant (aus dem AUR) blockiert
pacman -Syu, solange du die News des Tages nicht bestätigt hast. Für einen unbetreuten
Automatiklauf ist das allerdings ungeeignet – es würde dort schlicht hängen bleiben.
Auf CachyOS zusätzlich praktisch: die eigenen Werkzeuge cachyos-rate-mirrors (Mirror-Liste nach Geschwindigkeit ordnen) und paru als AUR-Helfer sowie paccache aus pacman-contrib für den Paketcache.
Skript 1: Updates melden und herunterladen
Das ist die Variante, die auf Arch/CachyOS dauerhaft laufen sollte: kein Risiko fürs laufende System, aber die Aktualisierungen liegen bereit und du erfährst davon.
#!/usr/bin/env bash
# /usr/local/bin/arch-update-check.sh - Updates melden und herunterladen
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
have() { command -v "$1" >/dev/null 2>&1; }
notify() { logger -t arch-update "$1"; echo "$(date '+%F %T') $1" >> /var/log/arch-update.log; }
# 1) Mirror-Liste pflegen
if have cachyos-rate-mirrors; then cachyos-rate-mirrors >/dev/null 2>&1 || true
elif have reflector; then reflector --latest 10 --sort rate --save /etc/pacman.d/mirrorlist || true
fi
# 2) Verfuegbare Updates ermitteln
if have checkupdates; then
LIST="$(checkupdates 2>/dev/null || true)" # arbeitet mit temporaerer Datenbank
else
pacman -Sy >/dev/null
LIST="$(pacman -Qu || true)"
fi
if [ -z "$LIST" ]; then
notify "keine Updates verfuegbar"
printf 'count=0\n' > /run/arch-update.count
exit 0
fi
COUNT="$(printf '%s\n' "$LIST" | wc -l)"
notify "$COUNT Updates verfuegbar:"
printf '%s\n' "$LIST" | tail -n 20 | while read -r l; do notify " $l"; done
# 3) Nur herunterladen - nichts installieren
pacman -Syuw --noconfirm
notify "$COUNT Updates heruntergeladen, Installation offen"
# 4) Zustand fuer Monitoring/Benachrichtigung ablegen
printf 'count=%s\n' "$COUNT" > /run/arch-update.count
if [ "$COUNT" -ge 30 ]; then notify "Hinweis: viele offene Updates - jetzt installieren"; fi
pacman -Syuw ist die
Synchronisationsdatenbank aktueller als das installierte System. Installiere deshalb kein
einzelnes Paket, bevor du das Upgrade nachgeholt hast – das wäre genau das verbotene Partial Upgrade.
Der Abschluss ist immer:
sudo pacman -Su (ohne vorheriges -y, die Datenbank ist ja schon aktuell).
Skript 2: vollautomatisch – mit Sicherheitsnetz
Wer auf Arch/CachyOS wirklich automatisch installieren will, sollte drei Dinge einkalkulieren: einen
Snapshot davor, das Melden von .pacnew-Dateien danach und
eine ehrliche Ausgabe im Journal. Genau das macht dieses Skript.
#!/usr/bin/env bash
# /usr/local/bin/arch-update-apply.sh - vollautomatisches Upgrade (bewusste Entscheidung!)
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
have() { command -v "$1" >/dev/null 2>&1; }
log() { echo "[$(date '+%F %T')] $*"; }
# 0) Netzwerk? Sonst gar nicht erst anfangen.
if ! ping -c1 -W3 archlinux.org >/dev/null 2>&1; then log "kein Netz - Abbruch"; exit 0; fi
# 1) Sicherheitsnetz: Snapshot vor dem Upgrade
if have snapper; then
snapper -c root create -d "pre-upgrade $(date '+%F %T')" || log "snapper-Snapshot fehlgeschlagen"
elif have timeshift; then
timeshift --create --comments "pre-upgrade" --scripted || log "timeshift-Snapshot fehlgeschlagen"
else
log "WARNUNG: kein Snapper/Timeshift - kein Rollback moeglich"
fi
# 2) Upgrade
log "pacman -Syu"
pacman -Syu --noconfirm
# 3) Paketcache pflegen: die letzten zwei Versionen behalten
have paccache && paccache -rk2 || true
# 4) .pacnew/.pacsave melden - NICHT automatisch zusammenfuehren!
PACNEW="$(find /etc -name '*.pacnew' -o -name '*.pacsave' 2>/dev/null || true)"
if [ -n "$PACNEW" ]; then
log "ACHTUNG: Konfigurationsdateien zu pruefen:"
printf '%s\n' "$PACNEW" | while read -r f; do log " $f"; done
log "Zusammenfuehren mit: sudo pacdiff"
fi
# 5) Neustart noetig?
if [ -n "$(find /boot -maxdepth 1 -name 'vmlinuz*' -newermt "$(uptime -s)" 2>/dev/null)" ]; then
log "REBOOT EMPFOHLEN: neuer Kernel installiert"
fi
log "fertig"
if have curl && [ -n "${KUMA_PUSH_URL:-}" ]; then
curl -fsS -m 10 "${KUMA_PUSH_URL}?status=up&msg=arch-upgrade-ok" >/dev/null 2>&1 || true
fi
| Zeile | Beweggrund |
|---|---|
| Netzwerk-Test zuerst | Ein Upgrade ohne Netz scheitert in der Mitte – und hinterlässt genau den halben Zustand, den man vermeiden will. |
| Snapshot vor dem Upgrade | Bei btrfs ist das die einzige echte Versicherung. Ein System, das sich per Snapshot zurückrollen lässt, darf Automatik haben. |
--noconfirm | Nötig für unbeaufsichtigt – aber wisse, dass pacman bei Rückfragen (Paket ersetzen, Konflikt) die Voreinstellung wählt. Genau deshalb gehört dieses Skript nur auf Systeme, die man kontrolliert. |
paccache -rk2 | Hält den Cache klein und behält zwei Versionen – deine Downgrade-Rettung, ohne die pacman -Scc gefährlich wäre. |
find /etc -name '*.pacnew' | Der Punkt, den kein Automatikskript lösen darf. Es meldet – zusammengeführt wird per pacdiff von Hand. |
| Kernel-Prüfung | Der einzige belastbare Hinweis auf einen nötigen Neustart. Er basiert auf einem Vergleich der Dateizeit im /boot mit der Startzeit des Systems – funktioniert auf jeder Distribution. |
Skript 3: Neustart-Bedarf erkennen
Dieses kleine Skript passt zu beiden Familien und ist der beste Kandidat für ein Monitoring: Es liefert einen Exit-Code zurück (0 = kein Neustart nötig, 1 = bitte neu starten) und lässt sich deshalb auch von Uptime Kuma oder einem anderen Check auswerten.
#!/usr/bin/env bash
# /usr/local/bin/reboot-check.sh
set -euo pipefail
REQ=0
# Debian: die klassische Markierung
if [ -f /var/run/reboot-required ]; then
echo "Neustart noetig: $(cat /var/run/reboot-required 2>/dev/null | tr '\n' ' ')"
[ -f /var/run/reboot-required.pkgs ] && cat /var/run/reboot-required.pkgs
REQ=1
fi
# Universell: wurde ein Kernel installiert, nachdem das System gestartet ist?
NEWK="$(find /boot -maxdepth 1 -name 'vmlinuz*' -newermt "$(uptime -s)" 2>/dev/null || true)"
if [ -n "$NEWK" ]; then
echo "Neuer Kernel installiert nach dem letzten Start:"; echo "$NEWK"
REQ=1
fi
[ "$REQ" -eq 0 ] && echo "Kein Neustart erforderlich."
exit "$REQ"
Warum der zweite Test wichtig ist: Die Datei /var/run/reboot-required wird von
update-notifier-common geschrieben – auf schlanken Servern fehlt dieses Paket oft. Der
Dateizeit-Vergleich dagegen funktioniert überall und erkennt genau den Fall, der zählt: Kernel auf der
Platte neu, Kernel im Speicher alt.
needrestart.
Zwei Ersatzwege: checkrestart aus pacman-contrib zeigt Prozesse mit gelöschten
Bibliotheken, und lsof +L1 findet Dateien, die noch von laufenden Prozessen offen gehalten
werden. Beides sind Melde-Werkzeuge – der Neustart des Dienstes bleibt Handarbeit.
Arch: Wartung und Aufräumen per Cron
Das Debian-Setup-Skript hat einen Teil, den es auf Arch nicht gibt: den regelmäßigen Aufräumlauf
/root/clean.sh. Nicht, weil Arch ihn nicht bräuchte – im Gegenteil: ohne paccache
wächst der Paketcache unbegrenzt –, sondern weil dort nichts von allein aufgeräumt wird. Die folgende
Tabelle ordnet jeden Schritt des Debian-Skripts seinem Arch-Gegenstück zu.
| Schritt im Debian-Skript | Arch/CachyOS |
|---|---|
| 1/6 Pakete installieren | unattended-upgrades gibt es nicht. Sinnvoll ist höchstens pacman -S pacman-contrib – darin liegen paccache und checkrestart. |
2/6 Schalter 20auto-upgrades | Kein Schalter: Die Stufe wählst du über die Skripte – Melden und Laden dauerhaft, Installieren als bewusste Entscheidung. |
3/6 Origins-Pattern | Nicht möglich: Es gibt keine getrennte Sicherheitsquelle, aus der man gezielt patchen könnte. |
4/6 needrestart-Automatik | checkrestart bzw. lsof +L1 melden nur. Der Neustart der Dienste bleibt Handarbeit. |
| 5/6 Timer-Takt | Kein apt-daily-Timer zum Überschreiben – also eigener systemd-Timer (nächster Abschnitt) oder Cron. |
6/6 clean.sh + Cron | arch-maintenance.sh unten: Cache pflegen, Journal begrenzen, Verwaistes und .pacnew melden. |
Für das Melden und Herunterladen ist mit Skript 1 alles gesagt – hier fehlt nur noch das Aufräumen. Es läuft bewusst als Meldeskript: Verwaiste Pakete werden ausgegeben, aber nicht entfernt.
#!/usr/bin/env bash
# /usr/local/bin/arch-maintenance.sh - Aufraeumen und pruefen (Arch/CachyOS)
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LOG=/var/log/arch-maintenance.log
log() { echo "$(date '+%F %T') - $*"; logger -t arch-maintenance "$*"; }
have() { command -v "$1" >/dev/null 2>&1; }
{
log "START: Wartung"
# 1) Update-Log auswerten - Gegenstueck zur Logpruefung im Debian-Skript
if [ -f /var/log/arch-update.log ]; then
if [ -n "$(find /var/log/arch-update.log -mtime +3 2>/dev/null)" ]; then
log "WARNUNG: seit mehr als 3 Tagen kein Update-Check protokolliert."
else
log "OK: Update-Check laeuft regelmaessig."
fi
else
log "WARNUNG: /var/log/arch-update.log fehlt - laeuft arch-update-check.sh?"
fi
# 2) Paketcache pflegen: zwei Versionen behalten, den Rest verwerfen
if have paccache; then paccache -rk2 || true; paccache -ruk0 || true; fi
# 3) Verwaiste Pakete nur MELDEN - entfernt wird von Hand
ORPH="$(pacman -Qtdq 2>/dev/null || true)"
if [ -n "$ORPH" ]; then
log "Verwaiste Pakete (pruefen, dann: sudo pacman -Rns $(printf '%s ' $ORPH)):"
printf '%s\n' "$ORPH" | while read -r p; do log " $p"; done
fi
# 4) Konfigurationsdateien melden - niemals automatisch zusammenfuehren
PACNEW="$(find /etc -name '*.pacnew' -o -name '*.pacsave' 2>/dev/null || true)"
if [ -n "$PACNEW" ]; then
log "ACHTUNG: .pacnew/.pacsave vorhanden, zusammenfuehren mit pacdiff:"
printf '%s\n' "$PACNEW" | while read -r f; do log " $f"; done
fi
# 5) Journal begrenzen - sonst waechst /var/log unbemerkt
journalctl --vacuum-size=200M >/dev/null 2>&1 || true
# 6) Neustart-Bedarf wie in Skript 3
if [ -f /var/run/reboot-required ] || \
[ -n "$(find /boot -maxdepth 1 -name 'vmlinuz*' -newermt "$(uptime -s)" 2>/dev/null)" ]; then
log "HINWEIS: Neustart empfohlen (neuer Kernel installiert)."
fi
log "ENDE: Wartung abgeschlossen."
} >> "$LOG" 2>&1
Der Auslöser – dieselbe Uhrzeit wie im Original-Skript, nur ohne apt-Timer, den man dafür nutzen könnte:
# /etc/cron.d/arch-maintenance
# Min Std Tag Monat WTag Benutzer Befehl
0 11 * * 1-5 root /usr/local/bin/arch-maintenance.sh
# Alternativ als systemd-Timer - der Aufbau steht im naechsten Abschnitt:
# OnCalendar=Mon..Fri 11:00
# Persistent=true
pacman -Scc. Der Paketcache ist die einfachste
Downgrade-Rettung, und paccache -rk2 behält die letzten zwei Versionen genau deshalb.
Timer und Cron für die Skripte
Die Skripte brauchen einen Auslöser. Auf systemd-Systemen sind Timer das richtige Werkzeug – wie ihre
Optionen im Detail funktionieren (OnCalendar, Persistent,
RandomizedDelaySec, AccuracySec), steht ausführlich im Artikel zur monatlichen
Systempflege. Hier die passenden Einheiten:
# /etc/systemd/system/arch-update-check.service
[Unit]
Description=Arch: Updates pruefen und herunterladen
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/arch-update-check.sh
Nice=10
IOSchedulingClass=idle
# /etc/systemd/system/arch-update-check.timer
[Unit]
Description=Taeglicher Update-Check
[Timer]
OnCalendar=*-*-* 08,20:00
Persistent=true
RandomizedDelaySec=30m
[Install]
WantedBy=timers.target
Zwei Termine am Tag sind hier bewusst gewählt: morgens informiert, abends heruntergeladen – und die
Installation machst du, wenn es dir passt. Wer es ruhiger mag, nimmt OnCalendar=daily.
Die Variante mit Cron – für Systeme ohne systemd oder als Vergleich:
# /etc/cron.d/arch-update
# Min Std Tag Monat WTag Benutzer Befehl
0 8 * * * root /usr/local/bin/arch-update-check.sh >/dev/null 2>&1
# Warum der volle Pfad? Cron startet mit minimalem PATH und ohne Login-Shell.
# Wer stattdessen die Ausgabe sehen will, leitet sie ins Journal:
# ... root /usr/local/bin/arch-update-check.sh 2>&1 | logger -t arch-update
| Aufgabe | Intervall | Begründung |
|---|---|---|
| Updates melden (Arch/CachyOS) | 1–2× täglich | Reaktionszeit bei Sicherheitsfixes |
| Updates herunterladen | mit dem Melden gekoppelt | Der spätere Installationsschritt ist dann schnell |
| Sicherheitsupdates installieren (Debian) | 2× täglich (Timer-Standard) | Debian-Voreinstellung, bewährt |
| Neustart-Check | stündlich | Damit das Monitoring einen Neustartbedarf schnell sieht |
| Vollständiges Upgrade (falls gewollt) | wöchentlich, nachts | Selten genug für Ruhe, häufig genug gegen Versionsdrift |
Benachrichtigungen richtig machen
Ein Update, von dem niemand erfährt, ist nur halb nützlich. Hier scheitern die meisten Skripte an einem
Detail: Ein root-Prozess aus einem System-Timer hat keine Desktop-Sitzung.
notify-send schlägt fehl, weil die Umgebungsvariablen
DBUS_SESSION_BUS_ADDRESS und DISPLAY fehlen.
| Weg | Vorgehen | Für wen |
|---|---|---|
| Statusdatei + User-Timer | Der System-Timer schreibt nur eine Datei (z. B. /run/arch-update.count), ein systemctl --user-Timer liest sie und ruft notify-send auf. | Desktops (CachyOS) |
| Journal | logger -t arch-update "…" → Auswertung mit journalctl -t arch-update. Minimal, aber immer vorhanden. | alle Systeme |
Auf Debian direkt eingebaut: Unattended-Upgrade::Mail plus Mail-Report "only-on-error". Braucht einen funktionierenden Mailversand. | Server | |
| Monitoring-Push | Nach erfolgreichem Lauf einen Push an Uptime Kuma schicken. Bleibt der Push aus, alarmiert das Monitoring – das erkennt auch „Update hängt seit drei Tagen“. | Server mit Monitoring |
| MOTD / Login-Hinweis | Eine Datei unter /etc/update-motd.d/ legt den Neustartbedarf auf den SSH-Begrüßungstext. | Server |
Der Monitoring-Push in der Praxis – passt direkt zu einem Uptime-Kuma-Push-Monitor:
# Am Ende eines Update-Skripts:
KUMA_URL="https://kuma.meine.domain/api/push/DEINTOKEN"
if [ "$OK" = "1" ]; then
curl -fsS -m 10 "$KUMA_URL?status=up&msg=updates-ok" >/dev/null || true
else
curl -fsS -m 10 "$KUMA_URL?status=down&msg=update-fehlgeschlagen" >/dev/null || true
fi
Wenn es schiefgeht
| Situation | Ursache | Vorgehen |
|---|---|---|
dpkg wurde unterbrochen | Stromausfall, harter Neustart, Ctrl+C | sudo dpkg --configure -a, dann sudo apt --fix-broken install. Mit AutoFixInterruptedDpkg passiert das automatisch. |
Arch: pacman -Dk meldet Fehler | Abgebrochene Transaktion | sudo pacman -Dk prüfen, oft hilft ein erneutes pacman -Syu; im Zweifel Snapshot zurückrollen. |
| Ein Paket lässt sich nicht installieren | Abhängigkeitskonflikt, fehlende Bibliothek | Debian: apt -f install, Paket mit apt-mark hold pinnen. Arch: pacman -Syu vollständig durchlaufen lassen, nicht einzeln. |
| Konfigurationsdatei „vergessen“ | Debian fragt interactiv, Arch legt .pacnew an | Unbeaufsichtigt wird nichts überschrieben. Prüfen: find /etc -name '*.pacnew', dann pacdiff bzw. dpkg --configure -a mit Dialog. |
| Nach dem Update startet ein Dienst nicht | Neue Hauptversion mit geänderter Konfiguration | journalctl -u dienst -n 50, Diff gegen die .dpkg-dist/.pacnew-Datei, im Notfall Snapshot oder Paket-Downgrade. |
| System bootet nicht mehr | Kernel, Treiber oder Bootloader betroffen | Im Bootmenü den vorherigen Kernel wählen; bei btrfs den Snapshot zurückrollen. Beides ist der Grund, warum ein Snapshot und ein zweiter Kernel installiert bleiben sollten. |
| Platte voll mitten im Update | /var oder /boot zu klein | Der häufigste Anfängerfehler bei /boot. Vorher prüfen (df -h /boot) und alte Kernel entfernen. |
Gefahrlos testen
| Methode | Wie | Aussagekraft |
|---|---|---|
| Probelauf | Debian: unattended-upgrade --dry-run --debug · Arch: sudo pacman -Syu --print | Zeigt exakt, was passieren würde – ohne Änderung |
Skript mit DRY=1 | Eigene Skripte mit Trockenmodus bauen (siehe Artikel Systempflege) | Prüft die Logik, nicht die Pakete |
| Virtuelle Maschine | Klonen, Upgrade laufen lassen, starten | Hoch – aber nur, wenn die VM dem echten System ähnelt |
| Snapshot + Rollback üben | Snapshot erstellen, Upgrade, absichtlich zurückrollen | Die einzige Methode, die auch dein Vorgehen im Ernstfall prüft |
| Einmal scharf laufen lassen | sudo systemctl start … und Journal lesen | Unverzichtbar – Timer, die nie manuell getestet wurden, funktionieren selten beim ersten Mal allein |
Häufige Fragen (FAQ)
| Frage | Antwort |
|---|---|
| Wie schnell bin ich nach einem Fix gepatcht? | Debian mit den Standard-Timern: innerhalb von etwa 12 Stunden. Arch mit zweimal täglich: ebenfalls innerhalb von Stunden. Wer es enger braucht, setzt den Check auf stündlich – auf einem Server kostet das nichts. |
| Kann ich automatische Updates komplett abschalten? | Ja, aber dann gehört der Patch-Termin fest in deinen Kalender. Ein System, das nie ein Sicherheitsupdate bekommt, ist nur noch nicht aufgefallen. |
Debian: Warum nicht einfach 50unattended-upgrades bearbeiten? | Weil das Paket die Datei bei Updates überschreibt. Eigene Dateien mit höherer Nummer (z. B. 52-…) bleiben erhalten und gewinnen. |
| Debian: Der Server startet nachts neu – warum? | Automatic-Reboot steht auf true. Auf Servern setzt man es auf false und informiert stattdessen. |
| Warum haben meine Dienste nach dem Update noch die alte Version? | Weil Dateien aktualisiert wurden, laufende Prozesse aber im Speicher bleiben. Auf Debian löst das needrestart – und Kernel-Updates brauchen immer einen Neustart. |
Warum gibt es auf Arch kein unattended-upgrades? | Weil es keine getrennte Sicherheitsquelle gibt und ein Rolling Release nur „alles oder nichts“ kennt. Automatisiert wird dort das Melden und Herunterladen. |
| Kann ich das Setup-Skript auch auf Ubuntu verwenden? | Die Struktur ja, die Quellen nein: Auf Ubuntu trägst du statt der Debian-Origins die -security-Quelle (und ggf. ESM) ein – die mitgelieferte 50unattended-upgrades enthält genau die passenden Zeilen als Vorlage. Fremdquellen wie xtradeb stehen dort als LP-PPA-… und müssen ausdrücklich im Origins-Pattern auftauchen, sonst bleiben sie ungepatcht. |
Was sind .pacnew-Dateien? | Der Vorschlag des Pakets zu einer Konfigurationsdatei, die du geändert hast. pacman überschreibt nichts – du führst zusammen, mit pacdiff. In Automatikläufen wird nur gemeldet. |
| Kostet das viel Traffic? | Nur wenn Updates existieren. Debian lädt zusätzlich zweimal täglich die Paketlisten (wenige MB). Arch aktualisiert die Datenbank beim Check – deshalb checkupdates mit temporärer Datenbank nutzen, wenn du nur informieren willst. |
| Kann ich einzelne Pakete zurückhalten? | Ja: Debian apt-mark hold paket, Arch in /etc/pacman.conf unter IgnorePkg. Beides birgt das gleiche Risiko – zurückgehaltene Pakete bleiben ungepatcht. |
Fazit
Automatische Updates sind kein Schalter, sondern eine Entscheidung auf einer Skala. Debian macht Stufe 3 bequem – Sicherheitsfixes laufen von allein, der Rest bleibt bei dir. Arch und CachyOS kennen diese Stufe nicht; dort ist das Herunterladen plus Meldung die dauerhafte Automatik, und das Installieren eine bewusste Handlung mit Snapshot im Rücken.
Die Skripte in diesem Artikel sind genau so aufgebaut: Das Melden und Laden läuft unbeaufsichtigt, das Installieren ist markiert und protokolliert, der Neustart-Bedarf wird erkannt und nach außen gemeldet. Wer das einmal eingeführt hat, hat das Thema „bin ich aktuell?“ dauerhaft vom Tisch.
needrestart mit restart='a' entscheidet, ob ein Patch wirklich aktiv wird.
③ Auf Arch/CachyOS ist Melden + Herunterladen die richtige Automatik – Installieren bleibt Handarbeit.
④ Ein Snapshot vor dem Upgrade ist die Eintrittskarte für jede Automatik auf Rolling Releases.
⑤ Melde den Erfolg, nicht die Verfügbarkeit – nur so fällt ein hängender Timer auf.