Drei Skripte, die aus einem Debian-, Ubuntu- oder anderen Debian-basierten Server ein gut organisiertes, snapshot-fähiges Btrfs-System machen:
setup-btrfs.sh— migriert eine einzelne Btrfs-Root-Partition in eine saubere Subvolume-Struktur, geeignet für Timeshift und Container-Workloads.setup-timeshift.sh— installiert und verbindet Timeshift mitgrub-btrfs, einschließlich automatischer GRUB-Aktualisierung beim Schließen der GUI nach dem Speichern eines Kommentars.setup-snapper.sh— sobald Root von einem benannten Subvolume läuft, ergänzt das ein SUSE-artiges Snapper-Setup: Timeline-Snapshots, Snapshots rund um jedeapt-Änderung und über GRUB bootbare Snapshots viagrub-btrfs.
Zuerst setup-btrfs.sh ausführen; setup-timeshift.sh und setup-snapper.sh setzen ein benanntes Root-Subvolume voraus und weisen darauf hin, falls das noch nicht der Fall ist.
setup-btrfs.sh hilft dabei, einen Debian-, Ubuntu- oder anderen Debian-basierten Server mit einer einzelnen Btrfs-Root-Partition in ein System mit sauberer Subvolume-Struktur zu verwandeln – geeignet für Timeshift und Container-Workloads. Funktioniert sowohl beim einmaligen Umstieg auf einer frischen Installation als auch nachträglich auf einem bereits laufenden, migrierten System, um dort noch fehlende Subvolumes zu ergänzen (kein Neustart nötig).
Auf einem Debian- (oder Debian-basierten) System mit Btrfs-Root führt das Skript im Wesentlichen aus:
-
Ermittelt das aktuelle Root-Device per
findmnt(z. B./dev/vda2[/@rootfs]→/dev/vda2). -
Mountet das Btrfs-Top-Level (
subvolid=5) nach/mnt/btrfs-root. -
Prüft vorab den freien Speicherplatz (jedes Byte auf
/wird während der Migration kurzzeitig dupliziert) und bricht ab, wenn es eng wird. -
Erkennt eine schon (teilweise) durchgeführte Migration und wechselt automatisch in einen inkrementellen Modus: Läuft
/bereits von einem benannten Subvolume, werden Root, GRUB und das Default-Subvolume nicht mehr angefasst — es werden nur noch fehlende Subvolumes für noch nicht separat gemountete Pfade ergänzt, sofort aktiv, ohne Neustart. Jeder Zielpfad wird einzeln klassifiziert: bereits korrekt eingerichtet (übersprungen, taucht im Auswahldialog gar nicht erst auf), anderweitig belegt (übersprungen mit Warnung, wird nicht überschrieben), oder noch offen (Kandidat für die Auswahl). -
Fragt in einem interaktiven Terminal ausdrücklich nach ("ja" eintippen), bevor irgendetwas verändert wird — samt Warnhinweis, was das Skript tut und dass ein Fehlschlag das System unbootbar machen kann. Ohne Terminal (automatisierte Läufe) wird die Abfrage übersprungen.
-
Zeigt in einem interaktiven Terminal einen Auswahldialog (
whiptail): universell sinnvolle Subvolumes (@root,@home,@log,@cache,@tmp_var,@tmp) sind vorausgewählt, alle vom Software-Stack abhängigen (Datenbanken, ClamAV, Docker/Podman, Webserver-Docroot) starten abgewählt — beides frei änderbar. Abgewählte Pfade bekommen kein eigenes Subvolume und bleiben einfach Teil von@. Ohne interaktives Terminal (z.B. bei automatisierter Ausführung) werden nur die universell sinnvollen Subvolumes ohne Nachfrage angelegt. -
Stoppt bekannte Datenbank-, Datastore- und Container-Dienste vor deren Datenkopie, falls sie gerade laufen. Im inkrementellen Modus werden sie nach aktiven neuen Mounts neu gestartet; im initialen Migrationsmodus bleiben sie bis zum Reboot gestoppt — für eine konsistente Kopie statt halbgeschriebener Dateien.
-
Bietet optional eine interaktive APT-Auswahl mit Kurzbeschreibungen für:
timeshift: einfache System-Restore-Snapshots.snapper: Server-/CLI-Snapshotverwaltung für Btrfs.btrbk: Btrfs-Backups und Replikation per SSH.btrfsmaintenance: geplante Scrub-, Balance-, Trim- und Defrag-Aufgaben.duperemove: Deduplizierung gleicher Btrfs-Extents.grub-btrfs: Btrfs-Snapshots im GRUB-Bootmenü bootbar machen — fortgeschritten: setzt einen bereits eingerichteten Snapshot-Manager (Timeshift/Snapper) voraus. Für die vollständige Integration danachsetup-timeshift.shodersetup-snapper.shausführen.
Die Tools werden nur installiert — nicht automatisch konfiguriert.
-
Legt (idempotent) folgende Subvolumes an:
@(neues Root)@root@home@spool@log@cache@tmp_var@srv@tmp@opt@containers@docker@mongodb@mysql@postgresql@chroma@clamav@stalwart@elasticsearch@opensearch@clickhouse@cassandra@couchdb@neo4j@rabbitmq@docker-volumes@containers-volumes@www
-
Kopiert das aktuelle Root-Dateisystem nach
@(mit Ausschlüssen für/dev,/proc,/sys,/run,/mnt,/media,/lost+foundsowie – automatisch aus dem Mapping unten abgeleitet – allen Pfaden, die ein eigenes Subvolume bekommen). -
Kopiert die Inhalte wichtiger Verzeichnisse in ihre Subvolumes:
/root→@root/home→@home/var/spool→@spool/var/log→@log/var/cache→@cache/var/tmp→@tmp_var/srv→@srv/tmp→@tmp/opt→@opt/var/lib/containers→@containers/var/lib/docker→@docker/var/lib/mongodb→@mongodb/var/lib/mysql→@mysql/var/lib/postgresql→@postgresql/var/lib/chroma→@chroma/var/lib/clamav→@clamav/var/lib/stalwart→@stalwart/var/lib/elasticsearch→@elasticsearch/var/lib/opensearch→@opensearch/var/lib/clickhouse→@clickhouse/var/lib/cassandra→@cassandra/var/lib/couchdb→@couchdb/var/lib/neo4j→@neo4j/var/lib/rabbitmq→@rabbitmq/var/lib/docker/volumes→@docker-volumes/var/lib/containers/storage/volumes→@containers-volumes/var/www→@www
Datenbank- und Datastore-Subvolumes (
@mongodb,@mysql,@postgresql,@chroma,@clamav,@stalwart,@elasticsearch,@opensearch,@clickhouse,@cassandra,@couchdb,@neo4j,@rabbitmq) sowie die benannten Docker-/Podman-Volumes (@docker-volumes,@containers-volumes) behalten normale Btrfs-Mounts mit CoW und Prüfsummen, bekommen aber vor der Datenkopiebtrfs property set ... compression no. Damit verlässt sich das Skript nicht auf per-Subvolume gesetztecompress-/nodatacow-fstab-Optionen, die Btrfs für Mounts desselben Dateisystems nicht zuverlässig getrennt unterstützt. Image-Layer und Metadaten in@docker/@containersselbst bleiben auf der normalen komprimierten Policy. -
Bereitet im neuen Root (
@) die Mountpoints vor, damit die Subvolumes dort eingehängt werden können. -
Passt
/etc/fstabim laufenden System an:- legt ein Backup als
fstab.backup-YYYY-MM-DD-HHMMSSan, - kommentiert alte Btrfs-Root-Zeilen als
#OLD-ROOT …aus, - fügt neue Btrfs-Einträge für
/,/home,/var/log,/var/lib/docker,/var/wwwusw. mit den entsprechenden@…-Subvolumes hinzu.
- legt ein Backup als
-
Passt GRUB an (falls vorhanden):
- ersetzt ggf.
@rootfsdurch@in/etc/default/grub, - ruft
update-grubodergrub-mkconfig -o /boot/grub/grub.cfgauf (sofern vorhanden).
- ersetzt ggf.
-
Setzt das Btrfs-Default-Subvolume auf
@, sodass das System von@bootet. -
Stellt sicher, dass die benötigten Mountpoints auch im aktuellen Root existieren (
/home,/var/lib/docker, …). -
Validiert die neue
/etc/fstabautomatisch mitfindmnt --verify(rein lesend, mountet nichts live um) und bricht bei Problemen ab, bevor du versehentlich mit einer kaputten fstab neu startest.
Das Ergebnis:
- Root läuft von
@(Timeshift-kompatibel). - Wichtige Pfade wie
/home,/var/log,/var/lib/docker,/var/wwwliegen auf eigenen Subvolumes.
- Debian oder Debian-basiertes System mit:
aptsystemd
- Root-Dateisystem ist Btrfs auf einem einzelnen Device (z. B. eine Btrfs-Partition
/dev/vda2); LVM nicht für das Root-Dateisystem aktivieren. - Das Skript wird als root ausgeführt.
Bei Bedarf installiert das Skript automatisch:
rsyncbtrfs-progs
In einem interaktiven Lauf kann das Skript außerdem optionale APT-Pakete (timeshift, snapper, btrbk, btrfsmaintenance, duperemove) anbieten, sofern sie in den konfigurierten Paketquellen verfügbar sind. In automatisierten/nicht interaktiven Läufen wird diese Auswahl übersprungen.
Am unkompliziertesten auf einer frischen Server-Installation, da dort alle Verzeichnisse klein/leer sind. Das Skript funktioniert aber auch auf bereits laufenden Systemen, sofern genug freier Speicherplatz vorhanden ist (wird automatisch geprüft – jedes Byte auf
/wird während der Migration kurzzeitig dupliziert). Für eine konsistente Kopie werden bekannte Datenbank-, Datastore- und Container-Dienste vor ihrer jeweiligen Datenkopie automatisch gestoppt; im inkrementellen Modus nachmount -aneu gestartet und im initialen Migrationsmodus bis zum Reboot gestoppt gelassen.Trotzdem gilt auf laufenden Systemen: mach vorher ein Backup, plane ein Wartungsfenster für den abschließenden Neustart ein, und bedenke, dass Anwendungen außerhalb dieser Liste (z. B. ein eigener Webserver-Prozess mit offenen Dateien in
/srvoder/var/www) während der Kopie weiterlaufen und dadurch theoretisch eine inkonsistente Momentaufnahme in ihr Subvolume bekommen könnten.
-
Debian so installieren, dass du erhältst:
- eine kleine EFI-Partition (z. B.
/dev/vda1) - eine große Btrfs-Partition als Root (z. B.
/dev/vda2) - LVM für das Root-Dateisystem nicht ausgewählt/aktiviert ist
- eine kleine EFI-Partition (z. B.
-
Als root anmelden (oder
sudoverwenden). -
Repository klonen:
git clone https://github.com/debian-btrfs/layout-script.git cd btrfs-layout -
Skript ausführbar machen:
chmod +x setup-btrfs.sh
-
Skript ausführen:
sudo ./setup-btrfs.sh
-
/etc/fstabprüfen und sicherstellen, dass:/mitsubvol=@eingetragen ist,- die zusätzlichen Pfade (
/home,/var/log,/var/lib/docker,/var/www, …) passende Einträge mit den erwarteten@…-Subvolumes haben.
-
Mounts anwenden und testen:
systemctl daemon-reload mount -a
Es sollten keine Fehler erscheinen.
-
Neustart:
reboot
-
Nach dem Neustart prüfen:
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS / findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS /home /var/log /var/lib/docker /var/www
Erwartung:
/von...[/@]mitsubvol=@/homevon...[/@home]usw.
Damit ist das Layout für Timeshift und Container-Workloads vorbereitet.
setup-timeshift.sh verbindet eine vorhandene Timeshift-Btrfs-Konfiguration mit grub-btrfs. Das Skript errät oder überschreibt weder das konfigurierte Backup-Gerät noch die Snapshot-Zeitpläne.
- Prüft, dass
/von einem benannten Btrfs-Subvolume läuft und Timeshift im Btrfs-Modus mit ausgewähltem Backup-Gerät konfiguriert ist. - Erstellt vor Änderungen einen read-only Guard-Snapshot.
- Installiert bei Bedarf
timeshiftundinotify-toolsund verwendet eine vollständige manuellegrub-btrfs-Installation weiter, wenn das Paket über APT nicht verfügbar ist. - Korrigiert das bekannte
grub-btrfs-Parserverhalten, das Kommas aus Timeshift-Kommentaren entfernt; der ursprüngliche Generator wird unter/var/lib/btrfs-layout/gesichert. - Aktiviert den ereignisbasierten Dienst
grub-btrfsdfür neue, gelöschte und geplante Snapshots und erzeugt die initiale GRUB-Konfiguration. - Installiert einen verwalteten
/usr/local/bin/timeshift-launcher. Er verwendet die vorhandene Timeshift-Authentifizierung, wartet auf das Schließen der GUI und aktualisiert danach einmal das GRUB-Snapshot-Menü, damit nachträglich gespeicherte Kommentare ohne Polling übernommen werden. - Deaktiviert bei einer Aktualisierung den bisherigen
timeshift-grub-btrfs-sync.service. - Ist idempotent und startet den Rechner nicht automatisch neu.
- Debian oder Debian-basiertes System mit
aptundsystemd. - Root-Dateisystem bereits auf einem benannten Btrfs-Subvolume.
- Timeshift bereits im Btrfs-Modus mit ausgewähltem Backup-Gerät konfiguriert.
- Das Skript als root ausführen.
chmod +x setup-timeshift.sh
sudo ./setup-timeshift.shFür einen automatisierten Lauf ohne Terminal:
sudo LAYOUT_SCRIPT_ASSUME_YES=1 ./setup-timeshift.shIntegration prüfen:
systemctl status grub-btrfsd
command -v timeshift-launcher
grub-script-check /boot/grub/grub.cfg
grep -n 'Description' /boot/grub/grub-btrfs.cfgEinen Snapshot mit timeshift --create --comments "after update" oder über die GUI erstellen und danach einen Kommentar speichern. Bei GUI-Snapshots Timeshift nach dem Speichern schließen; der Launcher erzeugt dann einmal die GRUB-Snapshot-Konfiguration neu. Ein direkter Start von /usr/bin/timeshift-gtk umgeht diesen GUI-Nachlauf. GRUB startet Snapshots read-only; dieses Setup ist kein automatischer System-Rollback.
setup-snapper.sh macht aus einem Debian-, Ubuntu- oder anderen Debian-basierten Server, dessen Root-Dateisystem bereits von einem benannten Btrfs-Subvolume läuft (z.B. via setup-btrfs.sh oben), ein SUSE-artiges Snapper-Setup: automatische Timeline-Snapshots, Snapshots rund um jede apt-Paketänderung und Snapshots, die direkt aus dem GRUB-Menü über grub-btrfs bootbar sind.
Auf einem Debian(-basierten) System, dessen / bereits auf einem benannten Btrfs-Subvolume liegt, macht das Skript Folgendes:
- Prüft, dass
/Btrfs ist und von einem benannten Subvolume läuft (z.B.@); bricht mit Hinweis aufsetup-btrfs.shab, falls nicht. - Erstellt vor der ersten Änderung einen read-only Btrfs-Guard-Snapshot des aktuellen Root-Subvolumes (z.B.
@.before-snapper-setup-...) als manuellen Rücksetzpunkt, falls während der Einrichtung etwas schiefgeht. - Installiert
snapperundinotify-tools(vongrub-btrfsdbenötigt, um neue Snapshots zu erkennen), falls nicht vorhanden. - Fragt in einem interaktiven Terminal ausdrücklich nach Bestätigung (Eingabe von "ja"), bevor irgendetwas verändert wird. Ohne Terminal bricht das Skript ab, außer
LAYOUT_SCRIPT_ASSUME_YES=1ist gesetzt. - Legt die Snapper-Konfiguration
rootan (idempotent — wird übersprungen, falls schon vorhanden); dabei entsteht.snapshotsals nested Btrfs-Subvolume. - Trägt
.snapshotsals eigenen Eintrag in/etc/fstabein und mountet es. Die altefstabwird vorher gesichert und beifindmnt --verify- odermount -a-Fehlern automatisch zurückgespielt. - Setzt eine SUSE-artige Timeline-Policy in
/etc/snapper/configs/root(TIMELINE_CREATE,TIMELINE_CLEANUP,NUMBER_CLEANUPsowie konservativeTIMELINE_LIMIT_*-Werte für stündlich/täglich/wöchentlich/monatlich/jährlich). - Installiert eigene
apt-Hooks (DPkg::Pre-Invoke/DPkg::Post-Invoke), die rund um jede Paketänderung ein Pre-/Post-Snapshot-Paar anlegen — Debian/Ubuntu liefert diese Integration anders als daszypp-Plugin von openSUSE nicht mit, weshalb das Skript dafür kleine Wrapper-Skripte schreibt. - Aktiviert die systemd-Timer
snapper-timeline.timerundsnapper-cleanup.timer. - Installiert
grub-btrfs, falls das Paket in den konfigurierten APT-Quellen verfügbar ist, konfiguriertgrub-btrfsdfür die Überwachung von Snapper-/.snapshotsund führtupdate-grub(bzw.grub-mkconfig) aus, damit Snapshots als bootbare, read-only-Einträge im GRUB-Menü erscheinen. Timeshift ist für diesen Pfad nicht erforderlich. Ist das Paket nicht verfügbar, läuft die Snapper-Einrichtung ohne GRUB-Menü-Integration weiter.
Snapshot-Browsing, das Diffen einzelner Dateien und ein read-only-Boot eines Snapshots über das GRUB-Menü (grub-btrfs) funktionieren mit diesem Setup, sofern grub-btrfs verfügbar ist. Der Guard-Snapshot ist bewusst read-only und dient als manueller Rücksetzpunkt: Für eine Wiederherstellung von einem Rettungssystem booten, das Btrfs-Top-Level mounten, aus dem Guard-Snapshot einen neuen schreibbaren Root-Snapshot erzeugen und Bootloader/fstab passend zurückstellen. Ein vollständiger bootbarer System-Rollback, wie ihn snapper rollback unter openSUSE macht, setzt zusätzlich voraus, dass Root aus einem .snapshots/<N>/snapshot-Subvolume läuft — das ist bei einem einfachen @-Layout nicht automatisch der Fall und müsste bei Bedarf manuell nachgezogen werden.
- Debian oder Debian-basiertes System mit
aptundsystemd. - Root-Dateisystem bereits auf einem benannten Btrfs-Subvolume (falls nicht, zuerst
setup-btrfs.shoben ausführen). - Das Skript als root ausführen.
Das Skript installiert bei Bedarf folgende Pakete: snapper, inotify-tools, optional grub-btrfs.
-
Sicherstellen, dass
/bereits von einem benannten Btrfs-Subvolume läuft (siehesetup-btrfs.shoben). -
Skript ausführbar machen und starten:
chmod +x setup-snapper.sh sudo ./setup-snapper.sh
Für automatisierte Läufe ohne Terminal:
sudo LAYOUT_SCRIPT_ASSUME_YES=1 ./setup-snapper.sh
-
Prüfen:
snapper list-configs snapper create -d test && snapper list && snapper delete <Nummer> systemctl status snapper-timeline.timer snapper-cleanup.timer grub-btrfsd systemctl cat grub-btrfsd.service
Bei einer reinen Snapper-Einrichtung muss der wirksame
ExecStartgrub-btrfsd --syslog /.snapshotsenthalten und darf nicht--timeshift-autoenthalten.setup-snapper.shundsetup-timeshift.shverwalten dasselbe Drop-in; das Skript für den ausgewählten Snapshot-Manager ausführen.Ein kleines Paket installieren/entfernen, um zu prüfen, dass die
apt-Hooks ein Pre-/Post-Snapshot-Paar erzeugen, und neu starten, um zu prüfen, dass das GRUB-Menü ein Snapshot-Untermenü zeigt.
Dieses Projekt steht unter der GNU General Public License v3.0 oder später (GPL-3.0-or-later).
Details siehe Datei LICENSE.