Zum Inhalt

Runbook: Reboot von NUC und Hetzner

Geplanter Neustart beider Server mit Prüfliste davor und danach. Erstellt für homeserver#196.

Die Liste prüft Wirkung, nicht Zustand: dass ein Container läuft, heißt nicht, dass er seine Daten sieht. Genau dafür sind die Kommandos unten da.

Vorbedingung: die Startreihenfolge auf dem NUC

docker.service hat keine Abhängigkeit zu den Mount-Units — es ist nur nach network-online.target geordnet. Die fünf Netzwerk-Mounts sind zwar Before=multi-user.target, Docker aber auch; zueinander sind sie damit nicht geordnet.

Folge: Docker kann Container starten, bevor NFS und die Storage Box bereit sind. Ein Bind-Mount wird beim Containerstart aufgelöst — zeigt /mnt/unas in dem Moment noch auf das leere lokale Verzeichnis, arbeitet der Container dauerhaft darauf weiter, auch wenn das NFS Sekunden später einhängt. Betroffen wären Immich, Paperless, der Media-Stack und die 5-Jahres-Daten von VictoriaMetrics und VictoriaLogs.

Vor dem ersten Reboot nach dieser Liste einmalig setzen:

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/10-wait-for-mounts.conf >/dev/null <<'EOF'
[Unit]
RequiresMountsFor=/mnt/ssd /mnt/unas /mnt/pictures /mnt/monitoring /mnt/paperless /mnt/storagebox
EOF
sudo systemctl daemon-reload

Danach die Wirkung prüfen, nicht den Dateiinhalt — ein Drop-in ohne Sektionskopf wird zeilenweise still verworfen:

systemctl show docker.service -p RequiresMountsFor
# erwartet: RequiresMountsFor=/mnt/ssd /mnt/unas ... (nicht leer)

Während des NUC-Reboots ist das Haus ohne DNS

Pi-hole auf dem NUC ist der DNS-Server für 10.10.10.0/24. Solange der NUC neu startet, löst im LAN nichts auf — kein Streaming, kein Smart Home, nichts. Vorher prüfen, ob auf der UDM ein zweiter DNS-Server hinterlegt ist, und Lars vorher Bescheid geben.

Reihenfolge

Erst Hetzner, dann NUC. Auf dem Hetzner laufen Uptime Kuma und ntfy, also der Weg, auf dem eine Störung gemeldet wird. Den will man beim riskanteren der beiden Neustarts oben haben. Umgekehrt merkt man einen misslungenen NUC-Reboot erst, wenn man selbst nachsieht.


Teil 1 — Hetzner vServer

Vorher

ssh <hetzner>
uptime && uname -r
cat /var/run/reboot-required 2>/dev/null || echo "(kein Flag)"
docker ps --format '{{.Names}}\t{{.Status}}' | tee /tmp/vorher-container.txt
docker ps -q | wc -l          # Anzahl merken

Reboot

sudo systemctl reboot

Nachher

uname -r                      # neuer Kernel aktiv?
docker ps -q | wc -l          # gleiche Anzahl wie vorher?
docker ps -a --filter status=exited --filter status=restarting --format '{{.Names}}'
                              # leer erwartet

Von außen gegenprüfen — diese vier decken Authelia, lldap, Headscale und die Alarmkette ab:

for u in https://ntfy.homelab-external.robinwerner.net \
         https://headscale.homelab-external.robinwerner.net \
         https://uptime.homelab-external.robinwerner.net \
         https://auth.homelab-external.robinwerner.net; do
  printf '%-60s ' "$u"; curl -s -o /dev/null -w '%{http_code}\n' --max-time 8 "$u"
done

Tailnet prüfen (vom NUC aus): docker exec tailscale tailscale statushetzner-server muss wieder active sein und idealerweise direct, nicht über DERP.


Teil 2 — Intel NUC

Vorher

uptime && uname -r
cat /var/run/reboot-required.pkgs 2>/dev/null   # welches Paket verlangt den Reboot
free -h                                          # Swap-Stand notieren
docker ps -q | wc -l                             # Container-Anzahl merken
docker ps --format '{{.Names}}\t{{.Status}}' > /tmp/vorher-container.txt

Kein Backup darf laufen — borgmatic mitten im Lauf abzuschneiden hinterlässt ein Lock im Repo:

systemctl is-active borgmatic.service     # "inactive" erwartet
systemctl list-timers borgmatic.timer --no-pager

Läuft gerade eines, entweder abwarten oder den Timer für die Dauer stoppen.

Reboot

sudo systemctl reboot

Nachher — in dieser Reihenfolge

1. Mounts zuerst. Vor allem anderen, weil daran alles Weitere hängt:

for m in /mnt/ssd /mnt/unas /mnt/pictures /mnt/monitoring /mnt/paperless \
         /mnt/storagebox /mnt/borg-repo /mnt/borg-repo-aiserver; do
  printf '  %-26s ' "$m"; mountpoint -q "$m" && echo ok || echo FEHLT
done

Fehlt einer, nicht weitermachen: erst den Mount reparieren, dann die betroffenen Stacks mit docker compose up -d --force-recreate neu erstellen, damit sie den Mount auch sehen.

2. Host-Dienste:

systemctl is-active docker nut-monitor borgmatic.timer    # 3x active erwartet

3. Container:

docker ps -q | wc -l                                       # gleiche Anzahl wie vorher
docker ps -a --filter status=exited --filter status=restarting --format '{{.Names}}'
docker ps --filter health=unhealthy --format '{{.Names}}'

4. Sehen die Container ihre Daten? Der eigentliche Test — ein leerer Bind-Mount fällt sonst tagelang nicht auf:

docker exec immich_server ls /usr/src/app/upload >/dev/null && echo "immich ok"
docker exec victorialogs ls /vlogs >/dev/null && echo "vlogs ok"
docker exec victoriametrics ls /storage >/dev/null && echo "vmetrics ok"

5. DNS und Netz:

dig +short @10.10.10.3 heise.de                            # Antwort erwartet
docker exec tailscale tailscale status | head -3

6. Traefik und Anwendungen:

curl -s http://127.0.0.1:8082/metrics | grep -c '^traefik_'  # > 0
curl -s -o /dev/null -w 'HA %{http_code}\n' --max-time 5 http://10.10.10.3:8123/

Dazu einmal im Browser: grafana.home.robinwerner.net, fotos.home.robinwerner.net, paperless.home.robinwerner.net. Die decken Traefik-Routing, Zertifikate und die drei Stacks mit den größten Datenmengen ab.

7. Swap: free -h — nach dem Neustart nahe null. War er vorher voll, ist das der Normalzustand und kein Grund zur Sorge; bleibt er binnen Tagen wieder bei 100 %, gehört das untersucht.

Wenn etwas fehlt

Symptom Erster Griff
Ein Mount fehlt systemctl status mnt-<name>.mount, dann systemctl start — bei NFS zuerst prüfen, ob die UNAS Pro erreichbar ist
Container läuft, Daten fehlen Mount war beim Start noch nicht da → Mount richten, dann docker compose up -d --force-recreate <stack>
Kein DNS im LAN docker ps --filter name=pihole; notfalls an der UDM übergangsweise einen öffentlichen Resolver setzen
Traefik liefert kein Zertifikat docker logs traefik \| grep -i acme; /mnt/ssd/container-data/traefik/letsencrypt muss gemountet sein
Tailnet bleibt offline docker logs tailscale; Headscale auf dem Hetzner erreichbar?

Stand bei Erstellung (06.09.2026)

NUC Hetzner
Uptime 100 Tage
Kernel 5.15.0-179-generic
Reboot verlangt von libc6 Kernel-Update seit 29.07.
Swap 4,0 GiB von 4,0 GiB belegt
Container 65, alle mit Restart-Policy

Alle Mount-Units auf dem NUC (mnt-unas, mnt-pictures, mnt-monitoring, mnt-paperless, mnt-storagebox) sind enabled und kommen nach dem Neustart von selbst zurück — die Reihenfolge gegenüber Docker ist der offene Punkt, siehe Vorbedingung oben.