<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>NFS on Kabelbruch</title><link>https://kabelbruch.de/tags/nfs/</link><description>Recent content in NFS on Kabelbruch</description><image><title>Kabelbruch</title><url>https://kabelbruch.de/og-image.png</url><link>https://kabelbruch.de/og-image.png</link></image><generator>Hugo</generator><language>de-DE</language><lastBuildDate>Thu, 05 Nov 2026 10:00:00 +0100</lastBuildDate><atom:link href="https://kabelbruch.de/tags/nfs/index.xml" rel="self" type="application/rss+xml"/><item><title>Drei Tage ohne Backup, und ich hab's nicht gemerkt</title><link>https://kabelbruch.de/posts/drei-tage-ohne-backup-pbs-nfs/</link><pubDate>Thu, 05 Nov 2026 10:00:00 +0100</pubDate><guid>https://kabelbruch.de/posts/drei-tage-ohne-backup-pbs-nfs/</guid><description>Mein Proxmox-Backup fiel drei Nächte aus, ohne dass es jemand merkte. Ursache: ein gestoppter Container, ein Wartungsmodus und ein NAS mit eigenem Kopf.</description><content:encoded><![CDATA[<p>Ein Backup, das nicht läuft, ist schlimmer als gar keins. Bei gar keinem weiß man wenigstens, dass man keins hat.</p>
<p>Ich hatte eins. Jeden Abend um 21 Uhr sichert mein Proxmox-Host alle Gäste auf einen Proxmox Backup Server. Aufbewahrung, Garbage Collection und Verify waren sauber eingerichtet, die Deduplizierung lag bei ungefähr 66:1. Ich war zufrieden. Vom 7. bis zum 9. Oktober ist trotzdem jede einzelne Sicherung gescheitert, und ich habe es nicht gemerkt.</p>
<p>Draufgestoßen bin ich durch reinen Zufall. Ich wollte eigentlich nur nachsehen, ob es auf dem Backupserver Updates zu installieren gab. Dabei bin ich über den Ausfall gestolpert.</p>
<h2 id="wie-mein-backup-aufgebaut-ist">Wie mein Backup aufgebaut ist</h2>
<p>Damit die Fehler gleich Sinn ergeben, kurz zum Aufbau:</p>
<ul>
<li><strong>Proxmox VE 9</strong> auf einem einzelnen Host. Ein Backup-Job sichert jeden Abend alle Gäste im Snapshot-Modus.</li>
<li><strong>Proxmox Backup Server (PBS) 4.2</strong> läuft als Container auf <strong>demselben</strong> Host. Das ist nicht ideal, dazu später mehr.</li>
<li>Der Datastore des PBS, also der Ort, an dem die Sicherungen tatsächlich liegen, ist ein <strong>NFS-Share auf meinem NAS</strong>, einem UniFi UNAS Pro mit UniFi Drive.</li>
</ul>
<p>Kurz zu den Begriffen: NFS ist ein Protokoll, mit dem ein Rechner ein Verzeichnis eines anderen Rechners wie eine lokale Festplatte einbindet. Ein „Export“ ist auf der NAS-Seite die Freigabe samt Regeln, wer darauf zugreifen darf und mit welchen Rechten.</p>
<h2 id="fehler-nummer-eins-der-pbs-war-aus">Fehler Nummer eins: der PBS war aus</h2>
<p>Im Aufgabenprotokoll von Proxmox stand an allen drei Abenden dasselbe:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">could not activate storage &#39;PBS&#39; ... Can&#39;t connect to 10.0.98.50:8007 (No route to host)
</span></span></code></pre></div><p>„No route to host“ klingt nach Netzwerk, war aber viel banaler. Der Container mit dem PBS lief schlicht nicht. Wenn kein Programm auf der Adresse antwortet, gibt es eben auch keinen Weg dorthin.</p>
<p>Warum er gestoppt war, weiß ich bis heute nicht.</p>
<p>Ein kleiner Tipp am Rande: Proxmox VE 9 schreibt kein <code>/var/log/syslog</code> mehr. Den Status der letzten Backup-Läufe bekommt man so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pvesh get /nodes/&lt;NODE&gt;/tasks --typefilter vzdump --limit <span class="m">5</span> --output-format json
</span></span></code></pre></div><p>Den Container gestartet, Autostart eingeschaltet (<code>onboot 1</code>), Haken dran. Dachte ich.</p>
<h2 id="fehler-nummer-zwei-wartungsmodus">Fehler Nummer zwei: Wartungsmodus</h2>
<p>Der PBS lief wieder, das Backup scheiterte trotzdem. Diesmal stand der Datastore im <strong>Wartungsmodus „offline“</strong>. In diesem Zustand nimmt der PBS keine Sicherungen an, auch wenn der Dienst selbst läuft.</p>
<p>Aufheben lässt sich das mit einem Befehl, ausgeführt im PBS-Container:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">proxmox-backup-manager datastore update Repository --delete maintenance-mode
</span></span></code></pre></div><p>Wer oder was den Wartungsmodus gesetzt hat, habe ich nicht herausgefunden. Das steht noch auf meiner Liste.</p>
<h2 id="fehler-nummer-drei-das-nas-hat-eigene-vorstellungen-von-rechten">Fehler Nummer drei: das NAS hat eigene Vorstellungen von Rechten</h2>
<p>Jetzt wird es interessant. Die Dateien im Datastore gehören auf dem NAS dem Benutzer und der Gruppe mit der ID 34. Das ist unter Debian der Systembenutzer <code>backup</code>, unter dem der PBS arbeitet. Die Rechte stehen auf 770, also darf nur dieser Benutzer hinein.</p>
<p>UniFi Drive bildet NFS-Zugriffe aber standardmäßig auf einen eigenen Benutzer ab. Im Export steht dann:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">all_squash,anonuid=977,anongid=988
</span></span></code></pre></div><p><code>all_squash</code> heißt: Egal, als wer der Client kommt, auf dem NAS gilt er als Benutzer 977. Und der darf in den Datastore nicht hinein. Ergebnis: <code>Permission denied</code>.</p>
<p>Das Problem kannte ich schon von der Einrichtung. Damals hatte ich den Export per SSH direkt auf dem NAS angepasst:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /etc/exports.d/
</span></span><span class="line"><span class="cl">grep -l Repository *.exports            <span class="c1"># die passende Datei finden</span>
</span></span><span class="line"><span class="cl">sed -i <span class="s1">&#39;s/anonuid=977,anongid=988/anonuid=34,anongid=34/&#39;</span> &lt;DATEI&gt;
</span></span><span class="line"><span class="cl">exportfs -ra                            <span class="c1"># übernehmen, ohne den NFS-Server neu zu starten</span>
</span></span><span class="line"><span class="cl">exportfs -v <span class="p">|</span> grep -A1 Repository       <span class="c1"># muss jetzt anonuid=34,anongid=34 zeigen</span>
</span></span></code></pre></div><p><code>exportfs -ra</code> ist dabei wichtig. Ein Neustart des NFS-Servers würde alle anderen Mounts kurz unterbrechen, und davon hängen bei mir auch die Docker-Container ab.</p>
<p>Irgendwann zwischen damals und dem Ausfall war diese Änderung aber verschwunden. Also noch einmal angepasst, im Container neu eingebunden, Backup von Hand gestartet. Um 23:40 Uhr stand da endlich <code>Backup job finished successfully</code>.</p>
<h2 id="und-dann-hat-das-nas-es-noch-einmal-gemacht">Und dann hat das NAS es noch einmal gemacht</h2>
<p>Am selben Abend habe ich gleich noch etwas umgebaut, das schon länger auf der Liste stand. Dazu gleich mehr. Dabei habe ich in der UniFi-Oberfläche die NFS-Verbindung eines <strong>anderen</strong> Containers geändert, meines Medienservers.</p>
<p>Kurz nach Mitternacht kam der PBS nach einem Neustart wieder nicht an seinen Datastore. Der Export stand wieder auf 977:988.</p>
<p>Die Erklärung: <strong>UniFi Drive schreibt bei jeder Änderung an irgendeiner NFS-Verbindung alle Export-Dateien neu.</strong> Meine Handarbeit auf der Kommandozeile kennt die Oberfläche nicht, also ist sie danach weg. Vermutlich war genau das auch der Grund, warum der Fix vorher schon verschwunden war. Beweisen kann ich das nicht.</p>
<p>Ich hatte also die Wahl: entweder nie wieder etwas an den NFS-Verbindungen ändern, oder dem NAS beibringen, meine Änderung selbst wiederherzustellen.</p>
<h2 id="ein-wächter-auf-dem-nas">Ein Wächter auf dem NAS</h2>
<p>Das NAS läuft intern mit systemd. Damit lässt sich eine <strong>path-Unit</strong> bauen. Die beobachtet ein Verzeichnis und startet einen Dienst, sobald sich darin etwas ändert. Dazu kommt ein Timer, der alle fünf Minuten nachsieht, falls doch einmal etwas durchrutscht.</p>
<p>Das Skript selbst ist klein:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/sh
</span></span></span><span class="line"><span class="cl"><span class="c1"># Repository-Export fuer PBS auf UID/GID 34 (backup) mappen.</span>
</span></span><span class="line"><span class="cl"><span class="nv">F</span><span class="o">=</span><span class="k">$(</span>grep -l <span class="s2">&#34;/var/nfs/shared/Repository &#34;</span> /etc/exports.d/*.exports 2&gt;/dev/null<span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span> -n <span class="s2">&#34;</span><span class="nv">$F</span><span class="s2">&#34;</span> <span class="o">]</span> <span class="o">||</span> <span class="nb">exit</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> grep -q <span class="s2">&#34;anonuid=977,anongid=988&#34;</span> <span class="s2">&#34;</span><span class="nv">$F</span><span class="s2">&#34;</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">  sed -i <span class="s1">&#39;s/anonuid=977,anongid=988/anonuid=34,anongid=34/&#39;</span> <span class="s2">&#34;</span><span class="nv">$F</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  exportfs -ra
</span></span><span class="line"><span class="cl">  logger -t repo-export-fix <span class="s2">&#34;Repository-Export korrigiert: </span><span class="nv">$F</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span></code></pre></div><p>Es ändert nur dann etwas, wenn wirklich der UniFi-Standard drinsteht. Ein zweiter Lauf tut nichts.</p>
<p>Dazu drei Units unter <code>/etc/systemd/system/</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="c1"># repo-export-fix.service</span>
</span></span><span class="line"><span class="cl"><span class="k">[Unit]</span>
</span></span><span class="line"><span class="cl"><span class="na">Description</span><span class="o">=</span><span class="s">Repository-NFS-Export auf UID 34 (PBS) mappen</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[Service]</span>
</span></span><span class="line"><span class="cl"><span class="na">Type</span><span class="o">=</span><span class="s">oneshot</span>
</span></span><span class="line"><span class="cl"><span class="na">ExecStart</span><span class="o">=</span><span class="s">/data/scripts/repo-export-fix.sh</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="c1"># repo-export-fix.path</span>
</span></span><span class="line"><span class="cl"><span class="k">[Unit]</span>
</span></span><span class="line"><span class="cl"><span class="na">Description</span><span class="o">=</span><span class="s">Aenderungen in /etc/exports.d ueberwachen</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[Path]</span>
</span></span><span class="line"><span class="cl"><span class="na">PathModified</span><span class="o">=</span><span class="s">/etc/exports.d</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[Install]</span>
</span></span><span class="line"><span class="cl"><span class="na">WantedBy</span><span class="o">=</span><span class="s">multi-user.target</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="cl"><span class="c1"># repo-export-fix.timer</span>
</span></span><span class="line"><span class="cl"><span class="k">[Unit]</span>
</span></span><span class="line"><span class="cl"><span class="na">Description</span><span class="o">=</span><span class="s">Repository-Export alle 5 Minuten pruefen</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[Timer]</span>
</span></span><span class="line"><span class="cl"><span class="na">OnBootSec</span><span class="o">=</span><span class="s">2min</span>
</span></span><span class="line"><span class="cl"><span class="na">OnUnitActiveSec</span><span class="o">=</span><span class="s">5min</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">[Install]</span>
</span></span><span class="line"><span class="cl"><span class="na">WantedBy</span><span class="o">=</span><span class="s">timers.target</span>
</span></span></code></pre></div><p>Einschalten und einmal von Hand starten:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl daemon-reload
</span></span><span class="line"><span class="cl">systemctl <span class="nb">enable</span> --now repo-export-fix.path repo-export-fix.timer
</span></span><span class="line"><span class="cl">systemctl start repo-export-fix.service
</span></span></code></pre></div><p>Zum Test habe ich den Export absichtlich zurückgedreht. Nach weniger als drei Sekunden war er wieder korrigiert, und im Journal stand die Meldung:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">journalctl -t repo-export-fix
</span></span></code></pre></div><p>Meine größte Sorge war, ob Skript und Units ein Firmware-Update des NAS überleben. Herstellerfirmware räumt gern alles weg, was nicht von ihr selbst stammt. Das erste Update kam gleich am nächsten Tag, und der Wächter war danach noch da. Verlassen mag ich mich darauf trotzdem nicht. Nach jedem Update prüfe ich deshalb kurz:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">systemctl is-enabled repo-export-fix.path repo-export-fix.timer
</span></span></code></pre></div><p>Beide müssen <code>enabled</code> melden. Sonst richte ich sie neu ein. Die komplette Anleitung liegt dafür in meinen Notizen.</p>
<h2 id="nebenbei-backup-ohne-umweg-über-die-firewall">Nebenbei: Backup ohne Umweg über die Firewall</h2>
<p>Der Umbau, von dem oben die Rede war: Bis dahin lief der Backup-Verkehr vom Proxmox-Host zum NAS <strong>geroutet</strong>, also quer durch die Firewall, inklusive Intrusion Prevention. Für Backup-Daten ist das ein unnötiger Umweg, und es macht die Firewall zum Teil des Backups.</p>
<p>Jetzt hängen Host, PBS-Container und Docker-VM zusätzlich mit einer zweiten Netzwerkkarte direkt im Storage-VLAN des NAS. Der Verkehr bleibt auf Layer 2, also im selben Netzsegment, und läuft nur noch über den Switch. Auf dem Host ist das eine eigene Bridge ohne Gateway:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">auto vmbr&lt;VLAN&gt;
</span></span><span class="line"><span class="cl">iface vmbr&lt;VLAN&gt; inet static
</span></span><span class="line"><span class="cl">        address 10.0.99.2/28
</span></span><span class="line"><span class="cl">        bridge-ports nic0.&lt;VLAN&gt;
</span></span><span class="line"><span class="cl">        bridge-stp off
</span></span><span class="line"><span class="cl">        bridge-fd 0
</span></span></code></pre></div><p>Zwei Dinge habe ich dabei gelernt:</p>
<ul>
<li>Sobald ein Gast eine Netzwerkkarte im Storage-VLAN hat, nutzt er sie auch als Absender. Das NAS muss dann die <strong>neue</strong> IP in der Freigabe kennen. Sonst läuft der alte Mount noch eine Weile asymmetrisch weiter, also Anfrage direkt und Antwort über den Router, und bricht beim nächsten Neuverbinden ab.</li>
<li>Den Server im Storage-Eintrag von Proxmox kann man mit <code>pvesm set</code> nicht ändern, weil <code>server</code> ein fester Parameter ist. Ich habe die Zeile direkt in <code>/etc/pve/storage.cfg</code> angepasst. Der Fingerprint des PBS bleibt dabei gleich, Proxmox merkt also nichts.</li>
</ul>
<h2 id="warum-es-niemand-gemerkt-hat">Warum es niemand gemerkt hat</h2>
<p>Das ist eigentlich die wichtigste Frage, und die Antwort ist peinlich einfach. Proxmox hat die Fehler gemeldet, brav, jeden Abend. Das Benachrichtigungsziel war aber <code>mail-to-root</code>, und diese Mails landeten im lokalen Postfach von <code>root</code> auf dem Host. Da schaut niemand rein.</p>
<p>Zwei Tage später habe ich das richtig eingerichtet: Proxmox verschickt Benachrichtigungen jetzt per SMTP über meinen eigenen Mailserver, mit Anmeldung, und die Firewall lässt genau diesen Weg zu. Die Testmail kam an.</p>
<p>Für meinen Blog-Server habe ich später gleich weitergedacht. Das <a href="/posts/vps-backup-pull-prinzip-borg/">VPS-Backup</a> meldet sich nach jedem Lauf aktiv bei Uptime Kuma. Bleibt die Meldung aus, kommt eine Mail. Das fängt auch den Fall ab, dass gar nichts passiert, nicht nur den, dass etwas schiefgeht.</p>
<h2 id="was-ich-daraus-mitnehme">Was ich daraus mitnehme</h2>
<p><strong>Ein Backup ohne Alarm ist ein Gerücht.</strong> Dass der Job eingerichtet ist, sagt nichts darüber, ob er läuft. Die Meldung muss dort ankommen, wo ich sie auch sehe.</p>
<p><strong>Fehler kommen selten allein.</strong> Hätte ich nach dem ersten Fix aufgehört nachzusehen, wäre das Backup am nächsten Abend wieder gescheitert, nur mit einer anderen Meldung.</p>
<p><strong>Handarbeit an Geräten mit eigener Oberfläche hält nicht.</strong> Wenn eine Weboberfläche die Konfiguration verwaltet, überschreibt sie früher oder später, was ich per SSH geändert habe. Entweder man baut einen Wächter, so wie ich, oder man lässt die Finger davon.</p>
<p><strong>„No route to host“ heißt nicht immer Netzwerk.</strong> Manchmal ist am anderen Ende einfach niemand zu Hause.</p>
<h2 id="was-als-nächstes-kommt">Was als Nächstes kommt</h2>
<p>Ganz zufrieden bin ich mit meinem Backup noch nicht:</p>
<ul>
<li>Der PBS läuft auf demselben Host, den er sichert. Fällt der Host aus, muss ich den PBS erst neu aufsetzen und den Datastore wieder einbinden, bevor ich irgendetwas zurückholen kann. Das will ich einmal durchspielen und aufschreiben.</li>
<li>Es gibt keine Kopie außerhalb des NAS. Von 3-2-1 bin ich noch ein Stück entfernt, also drei Kopien auf zwei verschiedenen Medien, davon eine außer Haus.</li>
<li>Proxmox meldet sich am PBS noch als <code>root@pam</code> an. Ein eigener Benutzer mit einem API-Token, der nur sichern darf, wäre sauberer.</li>
<li>Und einen echten Restore-Test habe ich auch noch nicht gemacht. Ein Backup, das man nie zurückgespielt hat, ist im Grunde auch nur ein Gerücht.</li>
</ul>
]]></content:encoded></item></channel></rss>