Zum Hauptinhalt springen
Fehlerbehebung 10 Min. Lesezeit

sshd nach Unattended Upgrade auf Ubuntu 24.04 reparieren (März 2026)

So reparieren Sie openssh-server nach fehlgeschlagenem unattended-upgrades auf Ubuntu 24.04. Behandelt das fehlende /run/sshd-Verzeichnis, den half-configured dpkg-Status, fehlgeschlagenes ssh.socket und ein vollständiges automatisiertes Fix-Skript.

sshd nach Unattended Upgrade auf Ubuntu 24.04 reparieren (März 2026)

Am 16. März 2026 hat ein fehlerhaftes openssh-server-Upgrade (1:9.6p1-3ubuntu13.14 auf .15) SSH auf Ubuntu-24.04-Servern mit unattended-upgrades zum Absturz gebracht. Die Ursache scheint ein fehlendes /run/sshd-Verzeichnis, das dazu führte, dass das postinst-Skript fehlschlug und dpkg halb konfiguriert sowie ssh.socket in einem fehlerhaften Zustand hinterließ. Die Lösung besteht darin, das Verzeichnis neu zu erstellen, den verwaisten sshd-Prozess zu beenden, systemd zurückzusetzen und das Paket neu zu konfigurieren.

TL;DR - Schnellfix (als root ausführen)

mkdir -p /run/sshd && chmod 0755 /run/sshd
systemctl reset-failed ssh.socket ssh.service && systemctl start ssh.socket
dpkg --configure openssh-server

Falls der alte sshd-Prozess den Port blockiert, erst beenden: kill $(pgrep -f '/usr/sbin/sshd' | xargs -I{} sh -c 'ps -o ppid= -p {} | tr -d " "' | grep '^1$'). Weiter unten folgt das vollständige automatisierte Skript.

Was schiefgelaufen ist

Das openssh-server-Paket-Upgrade von 1:9.6p1-3ubuntu13.14 auf 1:9.6p1-3ubuntu13.15 scheint mit einem fehlerhaften postinst-Maintainer-Skript ausgeliefert worden zu sein. Als unattended-upgrades über Nacht lief und versuchte, das neue Paket zu konfigurieren, schlug das Skript fehl. Dadurch blieb dpkg in einem halb konfigurierten Zustand, systemds ssh.socket in einem fehlerhaften Zustand, und der alte sshd-Masterprozess war verwaist -- er lief noch, wurde aber nicht mehr von systemd verwaltet.

Der Server bleibt nur so lange erreichbar, wie dieser verwaiste sshd-Prozess läuft. Stirbt er ab oder wird der Server neu gestartet, ist der SSH-Zugang vollständig verloren. In Laravel Forge erscheinen betroffene Server als "Disconnected", da Forge sie nicht mehr per SSH erreichen kann.

Wie wir das Problem diagnostiziert haben

Auf einem unserer betroffenen Systeme haben wir bei der Untersuchung Folgendes festgestellt.

dpkg: error processing package openssh-server

Paketstatus prüfen:

$ dpkg -s openssh-server | grep Status
Status: install ok half-configured

Das bestätigt, dass das Paket mitten im Upgrade steckt. Ein Blick darauf, was unattended-upgrades gemacht hat:

$ cat /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
...
Setting up openssh-server (1:9.6p1-3ubuntu13.15) ...
dpkg: error processing package openssh-server (--configure):
 installed openssh-server package post-installation script subprocess returned error exit status 1

ssh.socket: Failed with result 'service-start-limit-hit'

systemd prüfen:

$ systemctl status ssh.socket
Active: failed (Result: service-start-limit-hit)

$ journalctl -u ssh.socket
ssh.socket: Failed with result 'service-start-limit-hit'.
Failed to start ssh.socket - OpenBSD Secure Shell server socket.

$ journalctl -u ssh.service
ssh.service: Failed with result 'exit-code'.

Die Socket-Aktivierung ist vollständig defekt. Wir konnten aber noch per SSH einloggen, was bedeutete, dass noch etwas lauschte. Suche nach dem verwaisten Prozess:

$ ps -eo pid,ppid,cmd | grep sshd
1234     1  sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

PPID 1 -- das ist der alte sshd-Masterprozess, der nach dem fehlgeschlagenen Upgrade von systemd nicht mehr verwaltet wird. Er akzeptiert noch Verbindungen, weshalb SSH noch funktioniert, läuft aber auf geborgter Zeit.

fatal: Missing privilege separation directory: /run/sshd

Das auth.log enthüllte die wahrscheinliche Ursache:

$ grep sshd /var/log/auth.log
2026-03-18T18:20:19.201354+00:00 sshd[3115043]: fatal: Missing privilege separation directory: /run/sshd

Das Laufzeitverzeichnis fehlte tatsächlich:

$ ls -la /run/sshd
ls: cannot access '/run/sshd': No such file or directory

Dieses fehlende Verzeichnis dürfte der Grund sein, warum das postinst-Skript fehlschlug, da sshd es für die Privilege Separation benötigt.

Wir haben außerdem einen Crash-Report gefunden:

$ ls /var/crash/
openssh-server.0.crash

Fehlermeldungen, die auftreten können

Je nachdem, wo man nachschaut, können einige oder alle dieser Meldungen auftreten:

In der dpkg / apt-Ausgabe

dpkg: error processing package openssh-server (--configure):
 installed openssh-server package post-installation script subprocess returned error exit status 1
Errors were encountered while processing:
 openssh-server
E: Sub-process /usr/bin/dpkg returned an error code (1)

Bei apt upgrade oder apt install

You might want to run 'apt --fix-broken install' to correct these.
The following packages have unmet dependencies:
 openssh-server : Depends: openssh-sftp-server but it is not going to be installed

Paketstatus

Status: install ok half-configured

systemd-Fehler

ssh.socket: Failed with result 'service-start-limit-hit'.
ssh.service: Failed with result 'exit-code'.

Auth-Log

sshd[3115043]: fatal: Missing privilege separation directory: /run/sshd

So behebt man das Problem

Wir haben ein Skript geschrieben, das die gesamte Reparatur automatisiert. Es ist sicher, auf Servern auszuführen, die NICHT betroffen sind -- es erkennt den defekten Zustand zuerst und beendet sich sauber, wenn alles in Ordnung ist. Das macht es einfach, das Skript auf allen Servern auszuführen, ohne sich darum kümmern zu müssen, welche tatsächlich betroffen sind.

Das Skript:

  1. Liest den SSH-Port aus sshd_config (geht nicht von Port 22 aus)
  2. Erkennt, ob der Server betroffen ist (defekter dpkg-Zustand und/oder fehlgeschlagenes ssh.socket)
  3. Erstellt /run/sshd, falls es fehlt
  4. Sucht und beendet den verwaisten sshd-Masterprozess
  5. Wartet, bis der Port freigegeben wird
  6. Setzt ssh.socket zurück und startet es
  7. Führt dpkg --configure aus, um den Paketstatus zu reparieren
  8. Überprüft, ob alles funktioniert
  9. Bereinigt die Crash-Datei

Hier ist das vollständige Skript:

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

# Fix broken openssh-server upgrade on Ubuntu 24.04
# Safe to run on unaffected servers -- exits cleanly.

if [[ $EUID -ne 0 ]]; then
    echo "ERROR: Must run as root." >&2
    exit 1
fi

echo "=== openssh-server upgrade fix ==="

# -- 0. Determine SSH port from sshd_config --
SSH_PORT=22
if [[ -f /etc/ssh/sshd_config ]]; then
    configured_port=$(grep -Ei '^\s*Port\s+' /etc/ssh/sshd_config | awk '{print $2}' | tail -1)
    if [[ -n "${configured_port:-}" ]]; then
        SSH_PORT="$configured_port"
    fi
fi
echo "[*] Using SSH port: $SSH_PORT"

# -- 1. Detect if affected --
broken_dpkg=false
failed_socket=false

if dpkg -s openssh-server 2>/dev/null | grep -qE 'Status:.*(half-configured|half-installed|unpacked|triggers-awaited|triggers-pending)'; then
    broken_dpkg=true
    echo "[!] openssh-server dpkg state is broken."
fi

if systemctl is-failed --quiet ssh.socket 2>/dev/null; then
    failed_socket=true
    echo "[!] ssh.socket is in failed state."
fi

if ! $broken_dpkg && ! $failed_socket; then
    echo "[OK] Server is not affected. openssh-server package and ssh.socket are healthy."
    exit 0
fi

echo ""
echo "Server is affected. Proceeding with fix..."
echo ""

# -- 2. Create /run/sshd if missing --
if [[ ! -d /run/sshd ]]; then
    echo "[*] Creating /run/sshd ..."
    mkdir -p /run/sshd
    chmod 0755 /run/sshd
else
    echo "[OK] /run/sshd already exists."
fi

# -- 3. Kill orphaned sshd master process --
orphan_pids=()
while IFS= read -r pid; do
    [[ -z "$pid" ]] && continue
    ppid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ') || continue
    if [[ "$ppid" == "1" ]]; then
        orphan_pids+=("$pid")
    fi
done < <(pgrep -f '/usr/sbin/sshd' 2>/dev/null || true)

if [[ ${#orphan_pids[@]} -gt 0 ]]; then
    echo "[*] Found orphaned sshd master process(es): ${orphan_pids[*]}"
    for pid in "${orphan_pids[@]}"; do
        echo "    Killing PID $pid ..."
        kill "$pid" 2>/dev/null || true
    done
else
    echo "[OK] No orphaned sshd master processes found."
fi

# -- 4. Wait for port to free --
echo "[*] Waiting for port $SSH_PORT to free ..."
for i in $(seq 1 30); do
    if ! ss -tlnp | grep -q ":${SSH_PORT} "; then
        echo "    Port $SSH_PORT is free."
        break
    fi
    if [[ $i -eq 30 ]]; then
        echo "WARNING: Port $SSH_PORT still in use after 30s. Continuing anyway."
    fi
    sleep 1
done

# -- 5. Reset and start ssh.socket --
echo "[*] Resetting ssh.socket ..."
systemctl reset-failed ssh.socket 2>/dev/null || true
systemctl reset-failed ssh.service 2>/dev/null || true

echo "[*] Starting ssh.socket ..."
systemctl start ssh.socket

# -- 6. Fix dpkg state --
if $broken_dpkg; then
    echo "[*] Running dpkg --configure openssh-server ..."
    dpkg --configure openssh-server
fi

# -- 7. Verify --
echo ""
echo "=== Verification ==="

errors=0

if systemctl is-active --quiet ssh.socket; then
    echo "[OK] ssh.socket is active."
else
    echo "[FAIL] ssh.socket is NOT active."
    errors=$((errors + 1))
fi

if ss -tlnp | grep -q ":${SSH_PORT} "; then
    echo "[OK] Port $SSH_PORT is listening."
else
    echo "[FAIL] Port $SSH_PORT is NOT listening."
    errors=$((errors + 1))
fi

status=$(dpkg -s openssh-server 2>/dev/null | grep '^Status:' || echo "not found")
if echo "$status" | grep -q 'install ok installed'; then
    echo "[OK] dpkg state is clean: $status"
else
    echo "[FAIL] dpkg state is not clean: $status"
    errors=$((errors + 1))
fi

# -- 8. Clean up crash file --
if [[ -f /var/crash/openssh-server.0.crash ]]; then
    echo "[*] Removing /var/crash/openssh-server.0.crash ..."
    rm -f /var/crash/openssh-server.0.crash
fi

echo ""
if [[ $errors -eq 0 ]]; then
    echo "=== All checks passed. Server is fixed. ==="
else
    echo "=== $errors check(s) failed. Manual investigation needed. ==="
    exit 1
fi

Auf einem einzelnen Server ausführen:

sudo bash fix-openssh-upgrade.sh

Auf mehrere Server gleichzeitig verteilen:

for server in server1 server2 server3; do
    echo "--- $server ---"
    ssh root@$server 'bash -s' < fix-openssh-upgrade.sh
done

Vorbeugung für die Zukunft

Wer verhindern möchte, dass unattended-upgrades künftig openssh-server aktualisiert, kann das Paket auf die Blacklist setzen. Dazu die Datei /etc/apt/apt.conf.d/50unattended-upgrades bearbeiten und zum Abschnitt Package-Blacklist hinzufügen:

Unattended-Upgrade::Package-Blacklist {
    "openssh-server";
};

So werden SSH-bezogene Pakete nur noch aktualisiert, wenn man es manuell tut und den Vorgang überwachen kann.

Wenn der Zugang vollständig gesperrt ist

Falls der verwaiste sshd-Prozess bereits abgestorben ist oder der Server neu gestartet wurde, ist kein SSH-Login mehr möglich. In diesem Fall kann man über den Konsolenzugang des Hosting-Anbieters die Reparatur durchführen:

  • DigitalOcean: Droplet Console (webbasiert)
  • AWS: EC2 Serial Console oder Session Manager
  • Hetzner: VNC-Konsole in der Cloud Console
  • Jeder Anbieter: VNC- oder KVM-Zugang über das Control Panel

Zusammenfassung

Das openssh-server-Upgrade vom 16. März 2026 auf Ubuntu 24.04 hat SSH auf Servern mit unattended-upgrades beschädigt. Die Symptome sind ein halb konfigurierter dpkg-Zustand, ein fehlgeschlagenes ssh.socket, ein "fatal: Missing privilege separation directory: /run/sshd"-Fehler im auth.log, ein verwaister sshd-Prozess und Server, die in Laravel Forge als "Disconnected" angezeigt werden. Die Lösung umfasst das Neuerstellen von /run/sshd, das Beenden des verwaisten Prozesses, das Zurücksetzen der systemd-Units und die Neukonfiguration des Pakets. Das obige Skript automatisiert den gesamten Vorgang und kann gefahrlos auf nicht betroffenen Servern ausgeführt werden.

Überwachen Sie Ihre eigenen Server

Verfolgen Sie CPU, Speicher, Festplatte und Prozesse auf bis zu 2 Servern kostenlos. Die Einrichtung dauert etwa 5 Minuten.

Kostenlos starten

Verwandte Artikel