sshd repareren na unattended upgrade op Ubuntu 24.04 (maart 2026)
Hoe openssh-server te repareren na mislukte unattended-upgrades op Ubuntu 24.04. Behandelt de ontbrekende /run/sshd-directory, de half-configured dpkg-status, mislukte ssh.socket en een volledig geautomatiseerd reparatiescript.
Op 16 maart 2026 brak een foutieve openssh-server upgrade (1:9.6p1-3ubuntu13.14 naar .15) SSH op Ubuntu 24.04-servers die unattended-upgrades draaien. De oorzaak lijkt een ontbrekende /run/sshd-map die ervoor zorgde dat het postinst-script faalde, waardoor dpkg half-geconfigureerd achterbleef en ssh.socket in een mislukte toestand terechtkwam. De oplossing is om de map opnieuw aan te maken, het verweesde sshd-proces te stoppen, systemd te resetten en het pakket opnieuw te configureren.
TL;DR - Snelle oplossing (uitvoeren als root)
mkdir -p /run/sshd && chmod 0755 /run/sshd
systemctl reset-failed ssh.socket ssh.service && systemctl start ssh.socket
dpkg --configure openssh-server
Als het oude sshd-proces de poort blokkeert, stop het dan eerst: kill $(pgrep -f '/usr/sbin/sshd' | xargs -I{} sh -c 'ps -o ppid= -p {} | tr -d " "' | grep '^1$'). Lees verder voor het volledige geautomatiseerde script.
Wat er misging
De openssh-server pakketupgrade van 1:9.6p1-3ubuntu13.14 naar 1:9.6p1-3ubuntu13.15 lijkt te zijn uitgebracht met een foutief postinst-onderhoudersscript. Toen unattended-upgrades 's nachts draaide en probeerde het nieuwe pakket te configureren, mislukte het script. Dit liet dpkg in een half-geconfigureerde toestand achter, zette systemds ssh.socket in een mislukte staat en liet het oude sshd-masterproces verweesd achter -- nog steeds actief, maar niet langer beheerd door systemd.
De server blijft bereikbaar zolang dat verweesde sshd-proces blijft draaien. Als het stopt of de server herstart, gaat SSH-toegang volledig verloren. In Laravel Forge tonen getroffen servers als "Disconnected" omdat Forge ze niet meer via SSH kan bereiken.
Hoe we het diagnosticeerden
Op een van onze getroffen systemen vonden we het volgende bij het onderzoeken.
dpkg: error processing package openssh-server
De pakketstatus controleren:
$ dpkg -s openssh-server | grep Status
Status: install ok half-configured
Dat bevestigt dat het pakket vastzit midden in een upgrade. Kijken wat unattended-upgrades deed:
$ 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 controleren:
$ 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'.
Socket-activering is volledig kapot. Maar we konden nog steeds inloggen via SSH, wat betekende dat er nog iets luisterde. Het verweesde proces opsporen:
$ ps -eo pid,ppid,cmd | grep sshd
1234 1 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
PPID 1 -- dat is het oude sshd-masterproces, verweesd nadat systemd het kwijtraakte tijdens de mislukte upgrade. Het accepteert nog steeds verbindingen, waardoor SSH nog werkt, maar het draait op geleende tijd.
fatal: Missing privilege separation directory: /run/sshd
Het auth.log onthulde wat waarschijnlijk de oorzaak is:
$ grep sshd /var/log/auth.log
2026-03-18T18:20:19.201354+00:00 sshd[3115043]: fatal: Missing privilege separation directory: /run/sshd
De runtime-map ontbrak inderdaad:
$ ls -la /run/sshd
ls: cannot access '/run/sshd': No such file or directory
Deze ontbrekende map lijkt de oorzaak te zijn geweest van het falen van het postinst-script, omdat sshd het nodig heeft voor privilege-scheiding.
We vonden ook een crashrapport:
$ ls /var/crash/
openssh-server.0.crash
Foutmeldingen die je kunt tegenkomen
Afhankelijk van waar je kijkt, kun je enkele of alle van deze foutmeldingen tegenkomen:
In dpkg / apt uitvoer
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)
Bij het uitvoeren van apt upgrade of 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
Pakketstatus
Status: install ok half-configured
Systemd-fouten
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
Hoe je het oplost
We hebben een script geschreven dat de volledige oplossing automatiseert. Het is veilig om uit te voeren op servers die NIET getroffen zijn -- het detecteert de kapotte toestand eerst en stopt netjes als alles in orde is. Dit maakt het eenvoudig om het op al je servers uit te voeren zonder je zorgen te maken over welke daadwerkelijk kapot zijn.
Het script:
- Leest je SSH-poort uit sshd_config (gaat niet uit van poort 22)
- Detecteert of de server getroffen is (kapotte dpkg-toestand en/of mislukte ssh.socket)
- Maakt
/run/sshdaan als die ontbreekt - Zoekt en stopt het verweesde sshd-masterproces
- Wacht tot de poort vrijkomt
- Reset en start
ssh.socket - Voert
dpkg --configureuit om de pakketstatus te herstellen - Verifieert dat alles werkt
- Ruimt het crashbestand op
Hier is het volledige script:
#!/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
Om het op een enkele server uit te voeren:
sudo bash fix-openssh-upgrade.sh
Om het naar meerdere servers te sturen:
for server in server1 server2 server3; do
echo "--- $server ---"
ssh root@$server 'bash -s' < fix-openssh-upgrade.sh
done
Dit in de toekomst voorkomen
Als je wilt voorkomen dat unattended-upgrades openssh-server in de toekomst aanraakt, kun je het op een zwarte lijst zetten. Bewerk /etc/apt/apt.conf.d/50unattended-upgrades en voeg toe aan de Package-Blacklist-sectie:
Unattended-Upgrade::Package-Blacklist {
"openssh-server";
};
Dit zorgt ervoor dat SSH-gerelateerde pakketten alleen worden geupgraded wanneer je dat handmatig doet en het proces kunt bewaken.
Als je volledig buitengesloten bent
Als het verweesde sshd-proces al gestopt is of de server herstart is, kun je niet meer inloggen via SSH. Gebruik in dat geval de consoletoegang van je hostingprovider om de oplossing uit te voeren:
- DigitalOcean: Droplet Console (webgebaseerd)
- AWS: EC2 Serial Console of Session Manager
- Hetzner: VNC-console in de Cloud Console
- Elke provider: VNC- of KVM-toegang via je controlepaneel
Samenvatting
De openssh-server upgrade van 16 maart 2026 op Ubuntu 24.04 brak SSH op servers die unattended-upgrades draaien. De symptomen zijn een half-geconfigureerde dpkg-toestand, een mislukte ssh.socket, een "fatal: Missing privilege separation directory: /run/sshd" fout in auth.log, een verweesd sshd-proces en servers die als "Disconnected" verschijnen in Laravel Forge. De oplossing omvat het opnieuw aanmaken van /run/sshd, het stoppen van het verweesde proces, het resetten van systemd-units en het herconfigueren van het pakket. Het bovenstaande script automatiseert het volledige proces en is veilig uit te voeren op niet-getroffen servers.