<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom"
      xmlns:thr="http://purl.org/syndication/thread/1.0"
      xml:lang="en-us">
  <link rel="self" href="http://Andreas-Voit.at/feeds/blog-von-andreas-voit_tag_linux.atom_1.0.links-and-content.xml" />
  <title type="text">Blog von Andreas Voit – tag: linux</title>
  <id>https://andreas-voit.at/tags/linux/</id>
  <link href="http://Andreas-Voit.at" />
  <icon>/favicon.ico</icon>
  <updated>2026-10-25T17:54:34+01:00</updated>
  <author>
    <name>Andreas Voit</name>
  </author>
  <subtitle type="text">Articles tagged with linux from Blog von Andreas Voit</subtitle>
  <rights>All content written by Andreas Voit</rights>
  <generator uri='https://github.com/novoid/lazyblorg'>Generated from Org-mode source code using lazyblorg which is written in Python. Industrial-strength technology, baby.</generator>
<!-- ############################################################################################# -->
<entry>
    <title type="text">Framework-Notebook mit restic aufs Ugreen-NAS sichern</title>
    <link href='https://Andreas-Voit.at/2026/10/25/restic-notebook-backup-nas' />
    <published>2026-10-25T15:45:00+01:00</published>
    <updated>2026-10-25T15:45:00+01:00</updated>
    <category scheme='https://Andreas-Voit.at/tags/backup' term='backup' />
    <category scheme='https://Andreas-Voit.at/tags/restic' term='restic' />
    <category scheme='https://Andreas-Voit.at/tags/linux' term='linux' />
    <category scheme='https://Andreas-Voit.at/tags/docker' term='docker' />
    <category scheme='https://Andreas-Voit.at/autotags/language' term='language:deutsch' />
    <summary type='html'>
&lt;p&gt;

Mein Framework 13 läuft seit einiger Zeit mit Kubuntu, aber zu meiner Schande hatte ich noch keine richtige Backup-Strategie eingerichtet. Seit dem Umzug auf das neue Ugreen-NAS ist dort genug Platz, also war es Zeit, das nachzuholen.

&lt;/p&gt;


&lt;p&gt;

Meine Wünsche waren:

&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Das Home-Verzeichnis und die Programm-Konfigurationen täglich
sichern.&lt;/li&gt;
&lt;li&gt;Zusätzlich einmal pro Woche das ganze System, damit ich den Laptop
im Notfall komplett wiederherstellen kann.&lt;/li&gt;
&lt;li&gt;Nur sichern, wenn der Laptop am Netzteil hängt.&lt;/li&gt;
&lt;li&gt;Von unterwegs soll es auch funktionieren.&lt;/li&gt;
&lt;li&gt;Aufbewahrung: 4 tägliche, 2 wöchentliche und 4 monatliche
Sicherungen.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;

In diesem Artikel zeige ich, wie ich das mit &lt;a href="https://restic.net"&gt;restic&lt;/a&gt;, einem &lt;a href="https://github.com/restic/rest-server"&gt;rest-server&lt;/a&gt; im Docker auf dem NAS und zwei systemd-Timern umgesetzt habe. Am Ende steht ein längerer Abschnitt zur Fehlersuche, denn der erste Lauf war zunächst quälend langsam.

&lt;/p&gt;

    </summary>    <content type='html'>

&lt;p&gt;

Mein Framework 13 läuft seit einiger Zeit mit Kubuntu, aber zu meiner Schande hatte ich noch keine richtige Backup-Strategie eingerichtet. Seit dem Umzug auf das neue Ugreen-NAS ist dort genug Platz, also war es Zeit, das nachzuholen.

&lt;/p&gt;


&lt;p&gt;

Meine Wünsche waren:

&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Das Home-Verzeichnis und die Programm-Konfigurationen täglich
sichern.&lt;/li&gt;
&lt;li&gt;Zusätzlich einmal pro Woche das ganze System, damit ich den Laptop
im Notfall komplett wiederherstellen kann.&lt;/li&gt;
&lt;li&gt;Nur sichern, wenn der Laptop am Netzteil hängt.&lt;/li&gt;
&lt;li&gt;Von unterwegs soll es auch funktionieren.&lt;/li&gt;
&lt;li&gt;Aufbewahrung: 4 tägliche, 2 wöchentliche und 4 monatliche
Sicherungen.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;

In diesem Artikel zeige ich, wie ich das mit &lt;a href="https://restic.net"&gt;restic&lt;/a&gt;, einem &lt;a href="https://github.com/restic/rest-server"&gt;rest-server&lt;/a&gt; im Docker auf dem NAS und zwei systemd-Timern umgesetzt habe. Am Ende steht ein längerer Abschnitt zur Fehlersuche, denn der erste Lauf war zunächst quälend langsam.

&lt;/p&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Die Idee&lt;/h2&gt;&lt;/header&gt;


&lt;figure class="image-center"&gt;
&lt;a href="2026-10-24T23.00.01%20restic%20Notebook-Backup%20Ablauf.png"&gt;
  &lt;img src="2026-10-24T23.00.01%20restic%20Notebook-Backup%20Ablauf%20-%20scaled%20width%20560.png" alt="Ablaufdiagramm vom Notebook über LAN oder Tailscale zum rest-server auf dem NAS und weiter zur USB-Platte" width="TMPREPLACEMEwidthSTART-2026-10-24T23.00.01 restic Notebook-Backup Ablauf - scaled width 560.png-TMPREPLACEMEwidthEND" height="TMPREPLACEMEheightSTART-2026-10-24T23.00.01 restic Notebook-Backup Ablauf - scaled width 560.png-TMPREPLACEMEheightEND" loading="lazy" /&gt;
&lt;/a&gt;
&lt;figcaption&gt;Der Weg der Daten: zuhause direkt übers LAN, unterwegs über Tailscale &lt;a class="figcaption-clue-link" href="2026-10-24T23.00.01%20restic%20Notebook-Backup%20Ablauf.png"&gt;(klicken für größere Version)&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;


&lt;p&gt;

Am Laptop läuft restic als root, gestartet von systemd-Timern. Es schickt die verschlüsselten Daten an einen rest-server, der als Container auf dem NAS läuft und alles in einer eigenen Freigabe ablegt. Zuhause geht das direkt über das Heimnetz, unterwegs über &lt;a href="https://tailscale.com"&gt;Tailscale&lt;/a&gt;. Nachts spiegelt das NAS die Freigabe zusätzlich auf eine USB-Platte.

&lt;/p&gt;


&lt;p&gt;

Warum gerade so:

&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;restic:&lt;/strong&gt; Habe ich schon bei anderen Setups in der
Vergangenheit verwendet. Mir gefällt dran, dass man damit einfach
überprüfen kann, ob das Backup im Ernstfall auch wirklich funktioniert.
Denn das ist ja oft das Problem: Man hat ein super Backup und wenn man
es einspielen will, wird einem dann erst klar, ob die Backupdatei sauber
angelegt wurde oder ob sie kaputt ist. Es dabei aber zu beachten, dass
bei &lt;strong&gt;restic der Speicherplatz am NAS bzw. externer Festplatte
überwacht werden muss. Geht der Speicherplatz aus, ist das restic Backup
nicht vollständig.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rest-server statt SFTP:&lt;/strong&gt; Er läuft als Container wie
alles andere auf dem NAS. Ich brauche keinen SSH-Benutzer und muss nicht
mit den Rechten von UGOS kämpfen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Append-only:&lt;/strong&gt; Der rest-server läuft im Modus &lt;code
class="verbatim"&gt;--append-only&lt;/code&gt;. Der Laptop darf also nur neue
Sicherungen anlegen, aber nichts löschen. Selbst ein Trojaner mit
root-Rechten auf dem Laptop kann die Backups damit nicht zerstören. Der
Preis dafür ist, dass das Aufräumen alter Sicherungen auf dem NAS laufen
muss.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ein Repository für beides:&lt;/strong&gt; restic dedupliziert. Die
wöchentliche System-Sicherung kostet nach dem ersten Lauf kaum noch
Platz.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nur am Netzteil:&lt;/strong&gt; Der Timer versucht es tagsüber
alle drei Stunden. Das Skript sichert nur, wenn der Laptop am Strom
hängt und die letzte Sicherung alt genug ist. So klappt es auch, wenn
der Laptop nur selten am Netzteil hängt.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;

Es gibt zwei Sicherungen, unterschieden über restic-Tags:

&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Was&lt;/th&gt;
&lt;th&gt;Wann&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class="verbatim"&gt;home&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class="verbatim"&gt;/home/benutzer&lt;/code&gt;, &lt;code
class="verbatim"&gt;/etc&lt;/code&gt;, &lt;code class="verbatim"&gt;/root&lt;/code&gt;, &lt;code
class="verbatim"&gt;/usr/local&lt;/code&gt;, Paketlisten&lt;/td&gt;
&lt;td&gt;einmal pro Tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class="verbatim"&gt;system&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;das ganze &lt;code class="verbatim"&gt;/&lt;/code&gt; inklusive &lt;code
class="verbatim"&gt;/boot&lt;/code&gt; und &lt;code
class="verbatim"&gt;/boot/efi&lt;/code&gt;, ohne &lt;code
class="verbatim"&gt;/home&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;einmal pro Woche&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;

Die täglichen Konfigurationen in &lt;code&gt;/etc&lt;/code&gt; sind damit doppelt drin, aber das kostet dank Deduplizierung nichts.

&lt;/p&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Voraussetzungen&lt;/h2&gt;&lt;/header&gt;

&lt;ul&gt;
&lt;li&gt;Ein NAS oder Server mit Docker und Docker Compose. Bei mir ist das
ein Ugreen DXP4800 Plus mit UGOS.&lt;/li&gt;
&lt;li&gt;Tailscale auf NAS und Laptop. Auf dem NAS läuft Tailscale bei mir
als eigener Container.&lt;/li&gt;
&lt;li&gt;restic ab Version 0.17 auf dem Laptop, weil erst ab dieser Version
die Zugangsdaten für den rest-server per Umgebungsvariable gehen.
Kubuntu 26.04 bringt 0.18.1 mit.&lt;/li&gt;
&lt;li&gt;Platz auf dem NAS. Mein Home hat knapp 400 GiB.&lt;/li&gt;
&lt;/ul&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Teil 1: Das NAS&lt;/h2&gt;&lt;/header&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Freigabe anlegen&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

In UGOS unter „Systemsteuerung“ → „Freigegebener Ordner“ lege ich eine neue Freigabe &lt;code&gt;fw13-backup&lt;/code&gt; an. Wichtig sind dabei zwei Einstellungen:

&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kein Zugriff für den normalen Benutzer.&lt;/strong&gt; Der Laptop
ist per SMB als mein normaler Benutzer angemeldet. Hätte dieser
Schreibrechte auf die Freigabe, könnte ein Trojaner die Backups einfach
über SMB löschen, und append-only wäre ausgehebelt. Der Container läuft
als root und braucht keine Freigaberechte.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Papierkorb aus.&lt;/strong&gt; Gelöschte Daten braucht hier
niemand, sie belegen nur Platz.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;

Bei der Gelegenheit ist mir aufgefallen, dass mein normaler Benutzer auch auf die Freigabe &lt;code&gt;docker&lt;/code&gt; Lesen und Schreiben hatte. Dort liegen Zugangsdaten und Konfigurationen meiner Container. Das habe ich gleich mit abgestellt.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;rest-server im Docker&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Die Compose-Datei liegt bei mir unter &lt;code&gt;/volume1/docker/rest-server/docker-compose.yaml&lt;/code&gt;:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;services:
  rest-server:
    image: restic/rest-server:0.14.0
    container_name: rest-server
    restart: unless-stopped
    ports:
      - "8000:8000"   # LAN direkt (zuhause schnell), unterwegs über Tailscale
    volumes:
      - /volume1/fw13-backup:/data
    environment:
      OPTIONS: "--append-only --private-repos"	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

&lt;code&gt;--private-repos&lt;/code&gt; sorgt dafür, dass jeder Benutzer nur in sein eigenes Unterverzeichnis schreiben darf. Der Benutzer &lt;code&gt;fw13&lt;/code&gt; kommt also nur an &lt;code&gt;/fw13/&lt;/code&gt; heran. Kommen später weitere Notebooks dazu, bekommt jedes einen eigenen Benutzer.

&lt;/p&gt;


&lt;p&gt;

Ursprünglich hatte ich den Port auf &lt;code&gt;127.0.0.1:8000&lt;/code&gt; beschränkt, damit der rest-server nur über Tailscale erreichbar ist. Warum er jetzt doch im LAN offen ist, steht weiter unten bei der Fehlersuche.

&lt;/p&gt;


&lt;p&gt;

Starten und einen Benutzer anlegen:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  cd /volume1/docker/rest-server
  docker compose up -d
  docker exec -it rest-server create_user fw13	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Das Passwort für den rest-server ist &lt;b&gt;nicht&lt;/b&gt; das restic-Passwort. Du kannst es mit &lt;code&gt;openssl rand -hex 16&lt;/code&gt; oder einem anderen Zufallsgenerator erzeugen und speichere es in einen Passwortmanager. Am besten eines ohne Sonderzeichen, dann gibt es später keinen Ärger mit Anführungszeichen.

&lt;/p&gt;


&lt;p&gt;

Die Warnung „No user exists“ im Log beim ersten Start ist normal, sie stammt aus der Zeit vor &lt;code&gt;create_user&lt;/code&gt;.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Für Tailscale freigeben&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Für unterwegs leite ich einen eigenen HTTPS-Port im Tailnet auf den rest-server weiter. Bei mir ist Port 8443 schon für etwas anderes belegt, deshalb 8444:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  docker exec tailscale tailscale serve --bg --https=8444 http://127.0.0.1:8000
  docker exec tailscale tailscale serve status	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Das ist nur im Tailnet sichtbar, nicht im Internet (dafür wäre &lt;code&gt;tailscale funnel&lt;/code&gt; zuständig). Die Einstellung bleibt auch nach einem Neustart erhalten.

&lt;/p&gt;


&lt;p&gt;

Ein schneller Test vom Laptop aus. Hier und im Folgenden steht &lt;code&gt;nas-name.&amp;lt;tailnet&amp;gt;.ts.net&lt;/code&gt; für die Tailscale-Adresse des NAS. Die Heimnetz-Adresse &lt;code&gt;192.168.1.10&lt;/code&gt;, der Benutzer &lt;code&gt;benutzer&lt;/code&gt; und die Ablageorte der Passwort- und Zugangsdateien (&lt;code&gt;repo-kennwort&lt;/code&gt; und &lt;code&gt;zugang.env&lt;/code&gt; am Laptop, &lt;code&gt;kennwort-fw13&lt;/code&gt; am NAS) sind Beispiele, die du an dein System anpassen musst:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  curl -u fw13 --max-time 15 https://nas-name.&amp;lt;tailnet&amp;gt;.ts.net:8444/fw13/config	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Die Antwort &lt;code&gt;Not Found&lt;/code&gt; ist hier richtig, denn das Repository gibt es noch nicht. &lt;code&gt;401&lt;/code&gt; heißt falsches Passwort, und „Connection refused“ heißt, dass die Weiterleitung fehlt.

&lt;/p&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Teil 2: Der Laptop&lt;/h2&gt;&lt;/header&gt;


&lt;p&gt;

Alles läuft als root, damit restic auch &lt;code&gt;/etc&lt;/code&gt; und die Systemdateien lesen kann.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;restic und Passwörter&lt;/h3&gt;&lt;/header&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  sudo apt install restic curl
  restic version	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Dann das Passwort für das Repository. &lt;b&gt;Ohne dieses Passwort ist das Backup wertlos&lt;/b&gt;, es gehört also sofort in den Passwortmanager:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  sudo install -d -m 700 /etc/restic
  openssl rand -base64 32 | sudo tee /etc/restic/repo-kennwort
  sudo chmod 600 /etc/restic/repo-kennwort	  &lt;/pre&gt;
    &lt;/div&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Die Zugangsdatei&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Alle Einstellungen stehen in &lt;code&gt;/etc/restic/zugang.env&lt;/code&gt; (danach &lt;code&gt;sudo chmod 600 /etc/restic/zugang.env&lt;/code&gt;):

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  RESTIC_REPOSITORY=rest:https://nas-name.&amp;lt;tailnet&amp;gt;.ts.net:8444/fw13/
  RESTIC_REST_USERNAME=fw13
  RESTIC_REST_PASSWORD=&amp;lt;Passwort für den rest-server&amp;gt;
  RESTIC_PASSWORD_FILE=/etc/restic/repo-kennwort
  RESTIC_CACHE_DIR=/var/cache/restic
  RESTIC_PROGRESS_FPS=0.0166   # Fortschritt etwa 1x pro Minute im Journal
  # zuhause direkt per LAN
  RESTIC_REPOSITORY_LAN=rest:http://192.168.1.10:8000/fw13/
  NAS_MAC=xx:xx:xx:xx:xx:xx	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Zu den letzten Zeilen:

&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code class="verbatim"&gt;RESTIC_CACHE_DIR&lt;/code&gt; ist unter systemd
nötig. Dort gibt es kein &lt;code class="verbatim"&gt;$HOME&lt;/code&gt;, und ohne
Cache muss restic bei jedem Lauf alle Metadaten neu vom NAS holen.&lt;/li&gt;
&lt;li&gt;&lt;code class="verbatim"&gt;RESTIC_PROGRESS_FPS&lt;/code&gt; lässt restic auch
ohne Terminal etwa einmal pro Minute eine Fortschrittszeile mit Prozent
und Restzeit ins Journal schreiben.&lt;/li&gt;
&lt;li&gt;&lt;code class="verbatim"&gt;NAS_MAC&lt;/code&gt; ist die MAC-Adresse des NAS,
also der Wert nach &lt;code class="verbatim"&gt;lladdr&lt;/code&gt; in der Ausgabe
von &lt;code class="verbatim"&gt;ip neigh show 192.168.1.10&lt;/code&gt;. Damit
prüft das Skript, ob es wirklich im eigenen Heimnetz ist. Sonst würde es
in einem fremden Netz mit zufällig gleicher IP das Passwort
unverschlüsselt an ein fremdes Gerät schicken.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;

Damit ich nicht jedes Mal alle Variablen setzen muss, gibt es einen kleinen Kurzbefehl &lt;code&gt;/usr/local/sbin/restic-fw13&lt;/code&gt;:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  #!/bin/sh
  set -a; . /etc/restic/zugang.env; set +a
  exec restic "$@"	  &lt;/pre&gt;
    &lt;/div&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  sudo chmod 755 /usr/local/sbin/restic-fw13
  sudo restic-fw13 init	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Ab jetzt gehen &lt;code&gt;sudo restic-fw13 snapshots&lt;/code&gt;, &lt;code&gt;restore&lt;/code&gt; und so weiter ohne Tipparbeit.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Was nicht ins Backup soll&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

&lt;code&gt;/etc/restic/excludes-home.txt&lt;/code&gt;:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;/home/benutzer/.cache
/home/benutzer/.local/share/Trash
/home/benutzer/.local/share/baloo
/home/benutzer/.thumbnails
/home/benutzer/.var/app/*/cache
/home/benutzer/snap/*/*/.cache
/home/benutzer/.local/share/Steam
/home/benutzer/KI/model
/root/.cache	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Steam-Spiele und KI-Modelle kann man jederzeit neu herunterladen, die müssen nicht ins Backup. Meine Fotos und Videos bleiben drin, die liegen nur auf dem Laptop.

&lt;/p&gt;


&lt;p&gt;

&lt;code&gt;/etc/restic/excludes-system.txt&lt;/code&gt;:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;/home
/tmp
/var/tmp
/var/cache
/var/lib/snapd/cache
/var/log/journal
/swap.img
/swapfile	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

&lt;code&gt;/proc&lt;/code&gt;, &lt;code&gt;/sys&lt;/code&gt;, &lt;code&gt;/dev&lt;/code&gt; und &lt;code&gt;/run&lt;/code&gt; fallen durch &lt;code&gt;--one-file-system&lt;/code&gt; automatisch weg. Weil &lt;code&gt;/boot&lt;/code&gt; und &lt;code&gt;/boot/efi&lt;/code&gt; bei mir eigene Partitionen sind (das legt der Kubuntu-Installer bei verschlüsselter Installation so an), stehen sie im Skript ausdrücklich als Quellen. Ob es sie gibt, zeigt &lt;code&gt;findmnt -M /boot&lt;/code&gt; bzw. &lt;code&gt;findmnt -M /boot/efi&lt;/code&gt;.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Das Backup-Skript&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Das Herzstück ist &lt;code&gt;/usr/local/sbin/restic-backup.sh&lt;/code&gt; (danach &lt;code&gt;sudo chmod 755&lt;/code&gt;). Es bekommt als Parameter &lt;code&gt;home&lt;/code&gt; oder &lt;code&gt;system&lt;/code&gt;:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  #!/bin/bash
  # Aufruf: restic-backup.sh home|system
  set -uo pipefail
  MODE="${1:-}"
  set -a; . /etc/restic/zugang.env; set +a
  STATE=/var/lib/restic-backup
  mkdir -p "$STATE"

  case "$MODE" in
      home)   MAXAGE=$((20*3600)) ;;     # höchstens 1x pro Tag
      system) MAXAGE=$((6*24*3600)) ;;   # höchstens 1x pro Woche
      ,*) echo "Aufruf: $0 home|system"; exit 2 ;;
  esac

  # Letzte erfolgreiche Sicherung noch frisch? Dann nichts tun.
  if [ -f "$STATE/$MODE.last" ] &amp;amp;&amp;amp; \
         [ $(( $(date +%s) - $(stat -c %Y "$STATE/$MODE.last") )) -lt $MAXAGE ]; then
      echo "$MODE: letzte Sicherung ist noch aktuell"; exit 0
  fi

  # Nur am Netzteil
  if ! systemd-ac-power; then echo "Akkubetrieb, übersprungen"; exit 0; fi

  # Zuhause? Dann direkt übers LAN, der Tailscale-Proxy ist beim Hochladen langsam
  if [ -n "${RESTIC_REPOSITORY_LAN:-}" ] &amp;amp;&amp;amp; ping -c1 -W1 192.168.1.10 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 \
         &amp;amp;&amp;amp; ip neigh show 192.168.1.10 | grep -qi "${NAS_MAC:-none}"; then
      export RESTIC_REPOSITORY="$RESTIC_REPOSITORY_LAN"; echo "Weg: LAN"
  else
      echo "Weg: Tailscale"
  fi

  # NAS erreichbar?
  if ! restic cat config &amp;gt;/dev/null; then
      echo "NAS nicht erreichbar, nächster Versuch beim nächsten Timer"; exit 0
  fi

  if [ "$MODE" = home ]; then
      # Paketlisten für die Neuinstallation
      P=/var/backups/pakete
      mkdir -p "$P"
      dpkg --get-selections &amp;gt; "$P/dpkg-selections.txt"
      apt-mark showmanual   &amp;gt; "$P/apt-manuell.txt"
      command -v snap    &amp;gt;/dev/null &amp;amp;&amp;amp; snap list &amp;gt; "$P/snap.txt"
      command -v flatpak &amp;gt;/dev/null &amp;amp;&amp;amp; flatpak list --app --columns=application &amp;gt; "$P/flatpak.txt"
      lsblk -f &amp;gt; "$P/lsblk.txt"; cp /etc/fstab "$P/fstab"

      restic backup -o rest.connections=20 --tag home --exclude-caches \
  	   --exclude-file=/etc/restic/excludes-home.txt \
  	   /home/benutzer /etc /root /usr/local /var/backups/pakete
      RC=$?
  else
      restic backup -o rest.connections=20 --tag system --one-file-system \
  	   --exclude-file=/etc/restic/excludes-system.txt \
  	   / /boot /boot/efi
      RC=$?
  fi

  # 0 = ok, 3 = ok, aber einzelne Dateien nicht lesbar
  if [ $RC -eq 0 ] || [ $RC -eq 3 ]; then
      touch "$STATE/$MODE.last"
      echo "$MODE: fertig (Code $RC)"
      exit 0
  fi
  echo "$MODE: FEHLER (Code $RC)"; exit $RC	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Ein paar Gedanken dazu:

&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ob eine Sicherung fällig ist, merkt sich das Skript über einen
Zeitstempel in &lt;code class="verbatim"&gt;/var/lib/restic-backup&lt;/code&gt;. Der
systemd-Timer darf es daher ruhig oft aufrufen.&lt;/li&gt;
&lt;li&gt;Fehlt das Netzteil oder das NAS, beendet sich das Skript mit Code 0.
Das ist kein Fehler, sondern einfach „heute nicht“. Der nächste Timer
versucht es wieder.&lt;/li&gt;
&lt;li&gt;Bei der Home-Sicherung landen nebenbei die Paketlisten (&lt;code
class="verbatim"&gt;apt-mark showmanual&lt;/code&gt;, Snap, Flatpak), &lt;code
class="verbatim"&gt;lsblk&lt;/code&gt; und &lt;code class="verbatim"&gt;fstab&lt;/code&gt; im
Backup. Damit lässt sich ein neu installiertes System schnell wieder mit
denselben Programmen bestücken.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-o rest.connections=20&lt;/code&gt; hat bei mir messbar nichts
gebracht (siehe Fehlersuche), schadet aber auch nicht.&lt;/li&gt;
&lt;/ul&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Teil 3: Zeitplan mit systemd&lt;/h2&gt;&lt;/header&gt;


&lt;p&gt;

Ein Dienst für beide Sicherungen, &lt;code&gt;/etc/systemd/system/restic-backup@.service&lt;/code&gt;:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;[Unit]
Description=restic-Sicherung (%i) aufs NAS
Wants=network-online.target
After=network-online.target tailscaled.service
ConditionACPower=true

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/restic-backup.sh %i
Nice=10
IOSchedulingClass=idle	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Dazu zwei Timer. &lt;code&gt;/etc/systemd/system/restic-backup-home.timer&lt;/code&gt;:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;[Unit]
Description=Home-Sicherung, Versuch alle 3 Stunden

[Timer]
OnCalendar=*-*-* 09,12,15,18,21:00
Persistent=true
RandomizedDelaySec=10min
Unit=restic-backup@home.service

[Install]
WantedBy=timers.target	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Und &lt;code&gt;/etc/systemd/system/restic-backup-system.timer&lt;/code&gt; mit denselben Zeiten, eine halbe Stunde versetzt. Dass das System nur einmal pro Woche gesichert wird, regelt das Skript:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;[Unit]
Description=System-Sicherung, wöchentlich

[Timer]
OnCalendar=*-*-* 09,12,15,18,21:30
Persistent=true
RandomizedDelaySec=10min
Unit=restic-backup@system.service

[Install]
WantedBy=timers.target	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

&lt;code&gt;Persistent=true&lt;/code&gt; holt Termine nach, die der Laptop im Ruhezustand verpasst hat. Der erste Lauf von Hand, und danach die Timer einschalten:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  sudo systemctl daemon-reload
  sudo systemctl start --no-block restic-backup@home.service
  journalctl -fu restic-backup@home.service

  sudo systemctl enable --now restic-backup-home.timer restic-backup-system.timer
  systemctl list-timers 'restic*'	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Ohne &lt;code&gt;--no-block&lt;/code&gt; wartet &lt;code&gt;systemctl start&lt;/code&gt; bis zum Ende der Sicherung, und das kann beim ersten Mal Stunden dauern.

&lt;/p&gt;


&lt;figure class="image-center"&gt;
&lt;a href="2026-10-24T23.00.02%20restic%20Notebook-Backup%20Journal%20Demo.png"&gt;
  &lt;img src="2026-10-24T23.00.02%20restic%20Notebook-Backup%20Journal%20Demo%20-%20scaled%20width%20560.png" alt="Terminal mit journalctl-Ausgabe einer restic-Sicherung" width="TMPREPLACEMEwidthSTART-2026-10-24T23.00.02 restic Notebook-Backup Journal Demo - scaled width 560.png-TMPREPLACEMEwidthEND" height="TMPREPLACEMEheightSTART-2026-10-24T23.00.02 restic Notebook-Backup Journal Demo - scaled width 560.png-TMPREPLACEMEheightEND" loading="lazy" /&gt;
&lt;/a&gt;
&lt;figcaption&gt;Der erste System-Lauf im Journal (gekürzt) &lt;a class="figcaption-clue-link" href="2026-10-24T23.00.02%20restic%20Notebook-Backup%20Journal%20Demo.png"&gt;(klicken für größere Version)&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;


&lt;p&gt;

Läuft gerade eine Sicherung, schreibt restic auf Zuruf sofort eine Fortschrittszeile ins Journal:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  sudo pkill -USR1 -x restic
  journalctl -u restic-backup@home.service -n 3 -o cat	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Im Terminal selbst erscheint dabei nichts, die Zeile steht im Journal.

&lt;/p&gt;


&lt;p&gt;

Der Bildschirm darf sich dabei übrigens sperren und der Laptop zugeklappt sein. Die Sicherung läuft als Systemdienst unabhängig von der Sitzung weiter, solange der Laptop nicht in den Ruhezustand geht.

&lt;/p&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Teil 4: Aufräumen und zweite Kopie auf dem NAS&lt;/h2&gt;&lt;/header&gt;


&lt;p&gt;

Wegen append-only kann der Laptop keine alten Sicherungen löschen. Das übernimmt das NAS mit einem eigenen restic. Dafür liegt das Repository-Passwort des Laptops auf dem NAS in &lt;code&gt;/volume1/docker/restic/kennwort-fw13&lt;/code&gt; (&lt;code&gt;chmod 600&lt;/code&gt;).

&lt;/p&gt;


&lt;p&gt;

Das Skript &lt;code&gt;/volume1/docker/restic/prune-notebooks.sh&lt;/code&gt;:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  #!/bin/sh
  R=/volume1/docker/restic/bin/restic
  LOG=/volume1/docker/restic/prune-notebooks.log
  for nb in fw13; do
      echo "== $(date '+%F %T') $nb" &amp;gt;&amp;gt; "$LOG"
      $R -r /volume1/fw13-backup/$nb \
         --password-file /volume1/docker/restic/kennwort-$nb --retry-lock 30m \
         forget --group-by host,tags \
         --keep-daily 4 --keep-weekly 2 --keep-monthly 4 --prune &amp;gt;&amp;gt; "$LOG" 2&amp;gt;&amp;amp;1
      # erste Woche im Monat: 5 % der Daten prüfen
      if [ "$(date +%d)" -le 07 ]; then
  	$R -r /volume1/fw13-backup/$nb \
  	   --password-file /volume1/docker/restic/kennwort-$nb \
  	   check --read-data-subset=5% &amp;gt;&amp;gt; "$LOG" 2&amp;gt;&amp;amp;1
      fi
  done	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

&lt;code&gt;--group-by host,tags&lt;/code&gt; ist wichtig: Damit gilt die Regel 4/2/4 getrennt für &lt;code&gt;home&lt;/code&gt; und &lt;code&gt;system&lt;/code&gt;. Bei &lt;code&gt;system&lt;/code&gt; gibt es nur eine Sicherung pro Woche, dort bleiben also die letzten vier Wochen und vier Monatsstände.

&lt;/p&gt;


&lt;p&gt;

Per Cron als root läuft es jeden Sonntag um 14:00, weit weg vom nächtlichen NAS-Backup:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;0 14 * * 0 /volume1/docker/restic/prune-notebooks.sh	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Läuft gerade eine Sicherung vom Laptop, wartet das Aufräumen dank &lt;code&gt;--retry-lock&lt;/code&gt; bis zu 30 Minuten.

&lt;/p&gt;


&lt;p&gt;

Mein NAS sichert sich nachts selbst mit restic auf eine USB-Platte. Das Notebook-Repository habe ich dort aber bewusst &lt;b&gt;nicht&lt;/b&gt; als weitere Quelle eingetragen. Eine geänderte Quellenliste hätte ein Neueinlesen aller 3 TB ausgelöst, und das Repository ist ohnehin schon verschlüsselt. Stattdessen spiegelt eine zusätzliche Zeile im nächtlichen Skript die Freigabe 1:1 auf die Platte:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  rsync -a --delete /volume1/fw13-backup/ "$MNT/fw13-backup/" &amp;amp;&amp;amp; echo "fw13-backup gespiegelt"	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

&lt;code&gt;$MNT&lt;/code&gt; ist dabei der Einhängepunkt der USB-Platte, den das Skript vorher ermittelt.

&lt;/p&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Teil 5: Prüfen und Test-Wiederherstellung&lt;/h2&gt;&lt;/header&gt;


&lt;p&gt;

Ein Backup zählt erst, wenn eine Wiederherstellung einmal geklappt hat. Nach dem ersten Lauf und danach etwa alle drei Monate:

&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Was&lt;/th&gt;
&lt;th&gt;Befehl am Laptop&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sicherungen anzeigen&lt;/td&gt;
&lt;td&gt;&lt;code class="verbatim"&gt;sudo restic-fw13 snapshots&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Letzte Läufe und Fehler&lt;/td&gt;
&lt;td&gt;&lt;code
class="verbatim"&gt;journalctl -u 'restic-backup@*' --since -3d&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nächste Termine&lt;/td&gt;
&lt;td&gt;&lt;code class="verbatim"&gt;systemctl list-timers 'restic*'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Einzelne Datei zurückholen&lt;/td&gt;
&lt;td&gt;&lt;code
class="verbatim"&gt;sudo restic-fw13 restore latest --tag home --include /home/benutzer/.zshrc --target /tmp/rtest&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Durchsuchen wie ein Laufwerk&lt;/td&gt;
&lt;td&gt;&lt;code class="verbatim"&gt;sudo restic-fw13 mount /mnt/restic&lt;/code&gt;
(Ende mit Strg+C)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Platzverbrauch&lt;/td&gt;
&lt;td&gt;&lt;code
class="verbatim"&gt;sudo restic-fw13 stats --mode raw-data&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;

Meine Test-Datei war die &lt;code&gt;.zshrc&lt;/code&gt;. Ein &lt;code&gt;diff&lt;/code&gt; mit dem Original war leer, also alles gut.

&lt;/p&gt;


&lt;p&gt;

Auch append-only sollte man einmal testen: &lt;code&gt;sudo restic-fw13 forget &amp;lt;ID&amp;gt;&lt;/code&gt; mit einer ID aus &lt;code&gt;snapshots&lt;/code&gt; muss am Laptop mit einem Fehler abbrechen.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Im Notfall&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Dann brauche ich nur zwei Einträge aus dem Passwortmanager: das restic-Passwort und das Passwort für den rest-server. Auf dem neuen System oder einem Live-USB installiere ich restic (und für unterwegs Tailscale) und lege &lt;code&gt;/etc/restic/zugang.env&lt;/code&gt;, &lt;code&gt;/etc/restic/repo-kennwort&lt;/code&gt; und &lt;code&gt;restic-fw13&lt;/code&gt; wie oben an.

&lt;/p&gt;


&lt;p&gt;

Der einfachste Weg ist eine frische Installation plus Daten:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  sudo restic-fw13 restore latest --tag home --target /var/tmp/r
  xargs -a /var/tmp/r/var/backups/pakete/apt-manuell.txt sudo apt install -y
  xargs -a /var/tmp/r/var/backups/pakete/flatpak.txt flatpak install -y
  sudo rsync -aH /var/tmp/r/home/benutzer/ /home/benutzer/	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Aus &lt;code&gt;/var/tmp/r/etc&lt;/code&gt; übernehme ich dann gezielt, was ich selbst geändert hatte. &lt;code&gt;fstab&lt;/code&gt;, &lt;code&gt;crypttab&lt;/code&gt; und &lt;code&gt;/etc/default/grub&lt;/code&gt; kopiere ich &lt;b&gt;nicht&lt;/b&gt; blind, die gehören zur neuen Installation.

&lt;/p&gt;


&lt;p&gt;

Alternativ geht auch das komplette System 1:1 aus der wöchentlichen Sicherung: vom Live-USB Partitionen anlegen (Vorlage ist die gesicherte &lt;code&gt;lsblk.txt&lt;/code&gt;), erst &lt;code&gt;system&lt;/code&gt; und dann &lt;code&gt;home&lt;/code&gt; nach &lt;code&gt;/mnt&lt;/code&gt; wiederherstellen, die UUIDs in &lt;code&gt;fstab&lt;/code&gt; und &lt;code&gt;crypttab&lt;/code&gt; anpassen und im chroot Initramfs und GRUB neu bauen. Das lohnt sich aber nur, wenn viel am System selbst eingerichtet war.

&lt;/p&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Fehlersuche: Warum war der erste Lauf so langsam?&lt;/h2&gt;&lt;/header&gt;


&lt;p&gt;

Eingerichtet war alles in einer guten Stunde. Dann kam der erste Home-Lauf mit knapp 400 GiB, und restic meldete:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;[41:01] 1.37%  32650 files 5.680 GiB, total 276787 files 414.167 GiB, 0 errors ETA 84:11:57	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

84 Stunden, also rund 2 MB/s. Bis zur Lösung hat es mehrere Runden gebraucht. Weil die einzelnen Schritte für andere vielleicht nützlich sind, schreibe ich sie hier auf.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Runde 1: Ist es der Laptop?&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Die naheliegende Vermutung war meine Einstellung &lt;code&gt;IOSchedulingClass=idle&lt;/code&gt; im Dienst. Ein &lt;code&gt;ionice&lt;/code&gt; und &lt;code&gt;renice&lt;/code&gt; auf den laufenden Prozess hat aber kaum etwas gebracht. &lt;code&gt;top&lt;/code&gt; zeigte den Laptop zu 99 % im Leerlauf, kein Warten auf die SSD. Und ein &lt;code&gt;dd&lt;/code&gt; auf eine große Datei las mit mehreren GB/s. Der Laptop wartet also auf das NAS.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Runde 2: Eine Netzwerkdose mit 100 Mbit&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Auf dem NAS lieferte der rest-server lokal 233 MB/s:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  curl -s -u fw13 -o /dev/null -w '%{speed_download}\n' http://127.0.0.1:8000/fw13/data/&amp;lt;Datei-ID&amp;gt;	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Vom Laptop aus, egal ob über Tailscale oder direkt im LAN, kamen nur etwa 11 MB/s an. Das ist ziemlich genau die Grenze einer 100-Mbit-Verbindung. Dabei zeigten beide Netzwerkkarten 1000 Mbit (&lt;code&gt;cat /sys/class/net/&amp;lt;if&amp;gt;/speed&lt;/code&gt;). Der Engpass lag also dazwischen, in meinem Fall in der Hausverkabelung. Mit einer anderen Netzwerkdose kamen über Tailscale plötzlich 75 MB/s an.

&lt;/p&gt;


&lt;p&gt;

Problem gelöst, dachte ich.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Runde 3: Hochladen ist nicht Herunterladen&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Nach einigen Minuten lag restic aber wieder bei nur 3 MB/s. Mein Test hatte nur die Richtung NAS → Laptop gemessen, das Backup schreibt aber in die andere Richtung. Also alles einzeln durchgemessen:

&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Ergebnis&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Schreiben auf die NAS-Platten (&lt;code class="verbatim"&gt;dd&lt;/code&gt;, 2
GB)&lt;/td&gt;
&lt;td&gt;128 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netz Laptop → NAS (&lt;code class="verbatim"&gt;iperf3&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;ca. 500 Mbit/s (≈ 60 MB/s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class="verbatim"&gt;fsync&lt;/code&gt; für ein 16-MB-Paket am NAS&lt;/td&gt;
&lt;td&gt;ca. 0,3 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;restic mit 20 statt 5 Verbindungen&lt;/td&gt;
&lt;td&gt;kein Unterschied&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;

Alles einzeln schnell genug, und trotzdem kamen über Tailscale nur 3 MB/s an. Auffällig war, dass der Tailscale-Container auf dem NAS dabei 25 bis 30 % CPU brauchte.

&lt;/p&gt;


&lt;p&gt;

Zwei Dinge sind mir in den Ausgaben von &lt;code&gt;iperf3&lt;/code&gt; aufgefallen. Erstens war die Absenderadresse meines Laptops eine Tailscale-Adresse (100.x.x.x), obwohl ich die LAN-Adresse des NAS angesprochen hatte. Der Grund: Mein Home Assistant bietet im Tailnet eine Subnetz-Route ins Heimnetz an, und der Laptop hat sie übernommen. Selbst der „direkte“ Verkehr im LAN lief also verschlüsselt durch Tailscale. Abhilfe am Laptop:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;  sudo tailscale set --accept-routes=false
  ip route get 192.168.1.10    # sollte jetzt die LAN-Schnittstelle zeigen	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Zweitens fehlte noch genau ein Test: das Hochladen durch &lt;code&gt;tailscale serve&lt;/code&gt;. Also den rest-server-Port testweise im LAN geöffnet (&lt;code&gt;"8000:8000"&lt;/code&gt; in der Compose-Datei), die Repository-Adresse am Laptop auf

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt; rest:http://192.168.1.10:8000/fw13/	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

umgestellt und neu gestartet:

&lt;/p&gt;


	  &lt;div class="example_code"&gt;
	  &lt;pre&gt;[4:00] 7.09%  37763 files 28.291 GiB, total 276774 files 398.835 GiB, 0 errors ETA 1:48:29
[5:01] 8.05%  39008 files 32.113 GiB, total 276774 files 398.835 GiB, 0 errors ETA 1:45:58	  &lt;/pre&gt;
    &lt;/div&gt;


&lt;p&gt;

Rund 3,7 GiB pro Minute, also etwa 60 MB/s, statt vorher 0,19. Der Upload durch den Proxy von &lt;code&gt;tailscale serve&lt;/code&gt; auf dem NAS war die Bremse. Beim Herunterladen ist er schnell, beim Hochladen der vielen 16-MB-Pakete von restic aber nicht.

&lt;/p&gt;


	  &lt;header&gt;&lt;h3 class="section-title"&gt;Die Lösung: zwei Wege&lt;/h3&gt;&lt;/header&gt;


&lt;p&gt;

Daher der zweite Weg im Skript: Zuhause geht restic direkt per HTTP an den rest-server, unterwegs weiter über Tailscale. Unterwegs sind die täglichen Änderungen klein, da reichen die 3 MB/s. Damit das Skript nicht in einem fremden Netz mit zufällig gleicher Adresse das Passwort verschickt, prüft es vorher die MAC-Adresse des NAS.

&lt;/p&gt;


&lt;p&gt;

Ein Kompromiss bleibt: Im Heimnetz geht das Passwort für den rest-server unverschlüsselt über HTTP. Die Backup-Daten selbst verschlüsselt restic immer, und löschen kann man wegen append-only ohnehin nichts. Für ein Heimnetz halte ich das für vertretbar.

&lt;/p&gt;


&lt;p&gt;

Mit &lt;code&gt;accept-routes=false&lt;/code&gt; erreiche ich Geräte im Heimnetz unterwegs nur noch über ihre Tailscale-Namen, nicht mehr über 192.168.1.x. Für mich passt das.

&lt;/p&gt;


&lt;p&gt;

Der erste Home-Lauf mit knapp 399 GiB dauerte danach etwa zwei Stunden, der erste System-Lauf mit 32 GiB nur sechseinhalb Minuten. Gespeichert wurden davon dank Kompression 16,8 GiB.

&lt;/p&gt;


	  &lt;header&gt;&lt;h2 class="section-title"&gt;Fazit&lt;/h2&gt;&lt;/header&gt;


&lt;p&gt;

Das Grundgerüst aus restic, rest-server und zwei systemd-Timern war schnell aufgebaut und läuft ab jetzt ohne mein Zutun. Den meisten Aufwand hat die Ursachenforschung für die langsame Übertragungsgeschwindigkeit gemacht. Dabei habe ich gelernt, Up- und Download getrennt zu messen und jedes Stück der Kette einzeln zu prüfen, statt beim ersten guten Messwert aufzuhören.

&lt;/p&gt;


&lt;p&gt;

Und das wichtigste: Ich habe jetzt endlich ein Backup vom Laptop, das ich auch schon einmal zurückgespielt habe.

&lt;/p&gt;

    </content>
    <id>https://andreas-voit.at/2026/10/25/restic-notebook-backup-nas-from-tag-feed-with-content</id>
</entry></feed>