
🌐 Auch auf: English · Français · Español
Ein kurzer Nachtrag zum RAIDZ1-NAS-Projekt. Der Spickzettel in jenem Beitrag hat dirzpool scrub storage als Befehl mitgegeben, den du ausführen kannst. Offen blieb aber, ob irgendetwas ihn für dich ausführt – und, da ein Scrub nur dann etwas bringt, wenn du auch erfährst, dass er etwas gefunden hat, ob das System dir in diesem Fall Bescheid sagt. Beide Fragen hatten am Ende spannendere Antworten als „ja, natürlich“.🔍 Scrub und Trim, je ein Absatz
zpool scrub liest jeden belegten Block im Pool und prüft ihn gegen seine gespeicherte Prüfsumme. Eine Abweichung – ein Bit, das irgendwo auf dem physischen Medium still und heimlich gekippt ist – wird aus der RAIDZ-Parität rekonstruiert und automatisch neu geschrieben. Genau das ist der ganze Mechanismus, der ZFS immun gegen das schleichende Bit-Rot-Problem macht, dem der ursprüngliche Beitrag mehrere Absätze gewidmet hat: Nicht, dass Korruption nicht passieren könnte – der Scrub ist das, was aus „Korruption, die nie jemand bemerken wird“ eine „Korruption, die repariert ist, bevor es jemand bemerkt“ macht. zpool trim ist SSD-spezifisch. Es teilt der Firmware des Laufwerks mit, welche Blöcke ZFS nicht mehr nutzt (gelöschte Dateien, überschriebene Daten), damit die SSD diesen Platz vorab löschen und vorbereiten kann, statt das mitten im Schreibvorgang hektisch nachzuholen. Lässt du es lange genug weg, sinkt die Schreibleistung schleichend, weil dem Laufwerk die vorgelöschten Blöcke ausgehen – das SSD-Pendant dazu, nie den Müll rauszubringen und sich dann zu wundern, warum man in der Küche immer langsamer vorankommt. Keins von beiden bringt als einmalige Aktion etwas. Der ganze Sinn ist, dass sie nach Zeitplan laufen.📅 Wer drückt eigentlich auf den Abzug?
Ich habe nach der Antwort gesucht, statt sie einfach anzunehmen, und das war auch gut so – die naheliegende Stelle war die falsche. OpenZFS bringt unter Debian zwei Planungsmechanismen nebeneinander mit, und nur einer davon hat überhaupt etwas getan:$ systemctl list-unit-files | grep zfs-scrub
zfs-scrub-monthly@.timer disabled enabled
zfs-scrub-weekly@.timer disabled enabledBeide deaktiviert. Hätte ich hier aufgehört, wäre die ehrliche Antwort „nein, nichts führt ihn aus“ gewesen. Aber zfsutils-linux legt außerdem eine ganz normale Cron-Datei ab, unabhängig von diesen Timern, und die ist aktiv:# /etc/cron.d/zfsutils-linux
# TRIM the first Sunday of every month.
24 0 1-7 * * root if [ $(date +\%w) -eq 0 ] && [ -x /usr/lib/zfs-linux/trim ]; then /usr/lib/zfs-linux/trim; fi
# Scrub the second Sunday of every month.
24 0 8-14 * * root if [ $(date +\%w) -eq 0 ] && [ -x /usr/lib/zfs-linux/scrub ]; then /usr/lib/zfs-linux/scrub; fiTrim am ersten Sonntag, Scrub am zweiten, beide um 00:24 Uhr. Das aufgerufene Skript /usr/lib/zfs-linux/scrub ist auch kein blindes zpool scrub $everything – es geht jeden Pool durch, prüft, ob sein Zustand ONLINE ist, und liest pro Pool eine benutzerdefinierte Property namens org.debian:periodic-scrub, um zu entscheiden, ob er dabei ist:$ zfs get -H -o value org.debian:periodic-scrub storage
-- bedeutet nicht gesetzt, was das Skript als auto behandelt – der Scrub läuft. Setzt du sie bei einem Pool auf disable, nimmst du diesen Pool heraus, ohne den Cronjob selbst anzufassen – ein saubererer Hebel, als das Skript zu editieren. Kurz gesagt: Zwei Planungssysteme sind installiert, nur das ältere, Cron-basierte ist eingeschaltet, und die eigentliche Entscheidung pro Pool ist eine Property, kein fest verdrahteter Pool-Name. Nichts davon lässt sich über zpool status herausfinden – du musst direkt in systemctl, /etc/cron.d und die Property schauen, und genau das habe ich am Ende gemacht, nachdem mir die sehr berechtigte Frage gestellt wurde: „Ist das wirklich automatisiert, oder hast du mir nur den manuellen Befehl gezeigt?“ Monatlich ist hier übrigens auch das richtige Intervall – das sind SSDs, und ein wöchentlicher Scrub-Rhythmus ist eher ein Standard aus der HDD-Ära, der auf Flash vor allem Verschleiß ohne zusätzlichen Nutzen bringt.🔔 Warnt dich irgendetwas, wenn der Scrub ein Problem findet?
Das ist der Teil, der mich wirklich überrascht hat. Die Infrastruktur, um dich zu warnen, existiert, ist installiert und läuft:$ systemctl status zfs-zed
● zfs-zed.service - ZFS Event Daemon (zed)
Active: active (running)ZED (der ZFS Event Daemon) achtet auf Pool-Ereignisse – ein Scrub ist fertig, ein Resilver abgeschlossen, ein Gerät ändert seinen Zustand – und seine Konfiguration nennt sogar einen Empfänger:# /etc/zfs/zed.d/zed.rc
ZED_EMAIL_ADDR="root"
ZED_NOTIFY_INTERVAL_SECS=3600Sieht konfiguriert aus. Ist es auch – zumindest aus Sicht von ZED selbst. Aber der eigentliche Zustellmechanismus, vergraben in zed-functions.sh, ist ziemlich unspektakulär:: "${ZED_EMAIL_PROG:="mail"}"zed_notify_email ruft ein Binary auf, das buchstäblich mail heißt. Und auf dieser Kiste:$ which mail mailx msmtp
$Nichts. Kein mailutils, kein msmtp, überhaupt kein MTA installiert. zpool create zieht nie einen als Abhängigkeit mit, und solange du nicht separat daran denkst, eine Mailzustellung zu installieren, hat ZED einen Empfänger, aber keinen Weg, ihn zu erreichen. Das Zedlet scrub_finish-notify.sh würde beim nächsten Scrub korrekt feuern, seine Nachricht bauen und sie an zed_notify_email übergeben, das versuchen würde, mail auszuführen, „command not found“ bekäme und scheitern würde – lautlos, zumindest für jeden, der auf eine tatsächlich eintreffende Mail wartet. In journalctl -u zed steht der Fehler, wenn du danach suchst. Wenn nicht, macht dich nichts darauf aufmerksam. Darauf möchte ich kurz herumkauen, denn das ist eine wirklich gute Pointe: Im ganzen ersten Beitrag ging es um ein Dateisystem, das sich weigert, Korruption unbemerkt durchgehen zu lassen – Prüfsummen statt blindem Vertrauen, Selbstheilung statt stillem Versagen. Und die Schicht darüber, deren einziger Job es ist, einem Menschen Bescheid zu sagen, wenn diese Maschinerie ihre Arbeit tut, hat selbst genau auf die stille Art versagt, die ZFS verhindern soll. Die Lehre aus dem letzten Beitrag reicht weiter, als ich dachte: „Sieht still und leise okay aus“ ist eine Eigenschaft von Infrastruktur, nicht nur von Platten.🛠️ Die Reparatur, diesmal richtig
Die Lücke ist nur ein fehlender MTA, keine ZED-Fehlkonfiguration, also besteht die Lösung wirklich aus drei Schritten: Mailclient installieren, auf einen Relay zeigen lassen, ZED sagen, wen er anschreiben soll.apt-get install -y msmtp msmtp-mta bsd-mailxmsmtp-mta verlinkt msmtp als /usr/sbin/sendmail, und genau das rufen mail/mailx – und damit auch ZED – unter der Haube auf. Dieses Homelab hat bereits einen funktionierenden ausgehenden Relay (Strato, wird anderswo schon für Benachrichtigungen anderer Hosts genutzt), also habe ich /etc/msmtprc auf dasselbe Konto gerichtet, statt etwas Neues aufzusetzen:# /etc/msmtprc — root-owned, chmod 600 (it holds a password)
defaults
auth on
tls on
tls_starttls on
logfile /var/log/msmtp.log
account homelab
host smtp.strato.de
port 587
from homelab@apt-upgrade.me
user homelab@apt-upgrade.me
password ██████████████████
account default : homelabDirekt danach chown root:root /etc/msmtprc && chmod 600 /etc/msmtprc – in der Datei steht ein Passwort im Klartext, und zfs-zed.service läuft ohnehin als root, also ist „nur root“ sowohl richtig als auch ausreichend. Dasselbe gilt für die Logdatei. Dann der eigentliche Sinn der ganzen Übung – ZED beibringen, Mails nicht mehr an ein lokales root-Konto zu adressieren, das nie jemand lesen wird, sondern sie dorthin zu schicken, wo ich sie auch wirklich sehe:sed -i 's/^ZED_EMAIL_ADDR=.*/ZED_EMAIL_ADDR="you@example.com"/' /etc/zfs/zed.d/zed.rc
systemctl restart zfs-zedKeine Aliase, kein lokaler Mail-Spool, keine Weiterleitungsregel, die man im Blick behalten muss – ZED_EMAIL_ADDR ist wörtlich der Empfänger, mit dem mail aufgerufen wird. Ihn direkt auf ein echtes Postfach zu setzen ist also einfacher, als erst die lokale Zustellung zum Laufen zu bringen und dann eine Weiterleitung obendrauf zu stapeln.✅ Funktioniert nachweislich
Statt bis zum zweiten Sonntag des Monats zu warten, um herauszufinden, ob das alles tatsächlich funktioniert, habe ich eine manuelle Testmail über genau denselben Weg geschickt, den ZED nimmt –mail, das zu msmtp aufgelöst wird, das sich bei Strato authentifiziert:$ echo "This is a test message from the storage NAS (192.168.10.x) confirming that
msmtp + ZED mail delivery is now working via the Strato relay." |
\
mail -s "ZFS ZED delivery check - storage NAS" you@example.com
$ tail -1 /var/log/msmtp.log
host=smtp.strato.de tls=on auth=on user=homelab@apt-upgrade.me from=homelab@apt-upgrade.me
recipients=you@example.com mailsize=436 smtpstatus=250
smtpmsg='250 2.0.0 OK queued with id 990330282JJ9ENX' exitcode=EX_OKsmtpstatus=250 / exitcode=EX_OK bedeutet, dass Strato die Nachricht zur Zustellung angenommen hat – das ist die Seite von msmtp. Die Postfach-Seite hat es ein paar Sekunden später bestätigt:From: homelab@apt-upgrade.me
To: you@example.com
Subject: ZFS ZED delivery check - storage NAS
Date: Wed, 2 Sep 2026 21:19
This is a test message from the storage NAS (192.168.10.x) confirming that
msmtp + ZED mail delivery is now working via the Strato relay.Von Ende zu Ende, vom Relay bis ins Postfach, in etwa der Zeit, die man zum Lesen der Logzeile braucht. Damit ist die ganze Reparatur verifiziert – nicht „sollte jetzt gehen“, sondern eine echte E-Mail, die wirklich angekommen ist. Kleine Sache, aber es lohnt sich, sie klar auszusprechen: Die eigentliche Lösung ist nicht „msmtp installieren“. Sie besteht darin zu bemerken, dass eine Komponente, deren einzige Aufgabe es ist, Alarm zu schlagen, genauso lautlos ausfallen kann wie das, worüber sie wachen soll – und dass man nur dann sicher weiß, dass sie funktioniert, wenn man sie auslöst und nachsieht, statt die Konfiguration zu lesen und es einfach anzunehmen.



