Featured image of post Nextcloud-Server von einer USB-NVMe auf eine interne SATA-Festplatte migrieren – ohne Neuinstallation

Nextcloud-Server von einer USB-NVMe auf eine interne SATA-Festplatte migrieren – ohne Neuinstallation

Wie eine alternde USB-NVMe meinen Nextcloud-Server fast lahmlegte und wie sich ein laufendes Debian-System inklusive Nextcloud ohne Neuinstallation auf eine interne SATA-Festplatte migrieren lässt.

Nextcloud-Server von einer USB-NVMe auf eine interne Festplatte migrieren – ohne Neuinstallation

In meinem Fall lief Debian mitsamt Nextcloud auf einer externen NVMe im USB-Gehäuse. Ursprünglich nur als Übergangslösung gedacht, nachdem mein Laptop ausgefallen war und ich zusätzlich auf ein gutes Angebot für eine größere Festplatte wartete. Doch wie das in der IT häufig passiert: Provisorien bleiben oft länger bestehen, als ursprünglich geplant.

Mit der Zeit häuften sich die Auffälligkeiten: SSH reagierte sporadisch nicht mehr, Dienste verschwanden scheinbar grundlos aus dem Netz und die Nextcloud wurde zunehmend unzuverlässig. Nach einem Neustart lief meist wieder alles – allerdings nie dauerhaft.

Bei genauerem Hinsehen zeigte sich jedoch ein Flaschenhals: Die vermeintlich schnelle NVMe wurde effektiv nur mit USB-2.0-Geschwindigkeit angebunden – für einen produktiven Nextcloud-Server langfristig keine gute Idee.

Anstatt das komplette System neu aufzusetzen, entschied ich mich für einen anderen Weg:

Ich migriere das laufende Debian-System mitsamt Nextcloud auf eine interne 6-TB-SATA-Festplatte – ohne Neuinstallation.

Und genau diese Schritte dokumentiere ich hier.

Vorab: Was man wissen sollte

Ganz ohne Vorkenntnisse wird es schwierig. Man muss kein Linux-Profi sein, aber ein paar Dinge sollten vertraut sein:

  • ein grundlegender Umgang mit dem Terminal
  • Verständnis dafür, was Partitionen sind
  • keine Angst davor, mit rsync, mount oder fstab zu arbeiten
  • ein vollständiges Backup – ernsthaft, macht eines

Gerade der letzte Punkt ist wichtig. Auch wenn die folgenden Schritte bei mir funktioniert haben: Wer produktive Systeme migriert, sollte immer davon ausgehen, dass etwas schiefgehen kann.

Schritt 1: Bestandsaufnahme – Wo liegt eigentlich was?

Bevor man irgendetwas kopiert, sollte man sich zunächst ansehen, wie das bestehende System aufgebaut ist.

Dazu helfen folgende Befehle:

1
2
3
lsblk -f
df -h
mount

In meinem Fall sah die Situation vereinfacht so aus:

  • die Systempartition lag auf einer externen USB-NVMe
  • /srv enthielt größere Datenbestände
  • die Nextcloud-Daten lagen separat
  • /var war ausgelagert und enthielt Apache, PHP und Nextcloud-Dateien

Gerade dieser Punkt ist wichtig:

Viele Anleitungen vergessen /var. Dabei liegen dort oft genau die Dinge, die später plötzlich „verschwunden“ wirken:

1
2
3
4
/var/www/nextcloud
/var/log/apache2
/var/lib/mysql
/var/lib/postgresql

Wer /var vergisst, bekommt später oft einen Server, der zwar bootet – aber dessen Dienste nicht mehr funktionieren.

Schritt 2: Die neue Festplatte vorbereiten

Da die neue 6-TB-SATA langfristig sowohl System als auch Daten aufnehmen sollte, entschied ich mich erneut für getrennte Partitionen.

Meine Struktur:

  • / (Root) → 100 GB
  • /var → 40 GB
  • swap → 16 GB
  • /srv → 2 TB
  • Nextcloud-Daten → Rest der Platte

Partitioniert habe ich mit:

1
sudo cfdisk /dev/sda

Wichtig dabei:

Falls euer Rechner noch im klassischen BIOS-/Legacy-Modus läuft und die Platte GPT nutzt, braucht ihr zusätzlich eine kleine:

1
BIOS boot partition

Diese sollte etwa 2 MiB groß sein.

Diesen Punkt habe ich zunächst übersehen – und genau das führte später zu einem GRUB read error.

Schritt 3: Dateisysteme erstellen

Nach dem Partitionieren müssen die Dateisysteme angelegt werden.

Beispiel:

1
2
3
4
5
sudo mkfs.ext4 -L root /dev/sda1
sudo mkfs.ext4 -L var /dev/sda2
sudo mkswap -L swap /dev/sda3
sudo mkfs.ext4 -L srv /dev/sda4
sudo mkfs.ext4 -L nextcloud-data /dev/sda5

Anschließend die Partitionen mounten:

1
2
3
4
5
6
7
8
sudo mkdir -p /mnt/newroot
sudo mount /dev/sda1 /mnt/newroot

sudo mkdir -p /mnt/newroot/{var,srv,mnt/nextcloud-data}

sudo mount /dev/sda2 /mnt/newroot/var
sudo mount /dev/sda4 /mnt/newroot/srv
sudo mount /dev/sda5 /mnt/newroot/mnt/nextcloud-data

Kontrollieren lässt sich das mit:

1
mount | grep newroot

An dieser Stelle sollte bereits sichtbar sein, ob alle Zielpartitionen korrekt eingebunden wurden.

Schritt 4: Das laufende System kopieren

Hier kommt der eigentliche Trick:

Anstatt alles neu zu installieren, wird das laufende System schlicht kopiert.

Dafür eignet sich rsync, weil Rechte, Besitzer und Symlinks erhalten bleiben.

Für die Root-Partition:

1
2
3
sudo rsync -aAXHv --numeric-ids \
--exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/srv/*","/var/*"} \
/ /mnt/newroot

Danach getrennt:

1
2
sudo rsync -aAXHv --numeric-ids /srv/ /mnt/newroot/srv/
sudo rsync -aAXHv --numeric-ids /var/ /mnt/newroot/var/

Und – falls ausgelagert – die Nextcloud-Daten:

1
2
3
sudo rsync -aAXHv --numeric-ids \
/mnt/nextcloud-data/ \
/mnt/newroot/mnt/nextcloud-data/

Wichtig:

Erst nachdem alle Daten kopiert wurden, sollte man weitermachen.

Schritt 5: /etc/fstab anpassen – damit das System weiß, was wohin gehört

Nachdem sämtliche Daten kopiert wurden, folgt ein Schritt, der gern unterschätzt wird – aber darüber entscheidet, ob das neue System später überhaupt sauber startet:

Die neue Festplatte muss wissen, welche Partition wo eingehängt werden soll.

Dafür dient die Datei: /etc/fstab

Zunächst sollte man sich die UUIDs der neuen Partitionen anzeigen lassen:

sudo blkid

Die Ausgabe sieht ungefähr so aus:

1
2
3
4
5
/dev/sda1: LABEL="root" UUID="..."
/dev/sda2: LABEL="var" UUID="..."
/dev/sda3: LABEL="swap" UUID="..."
/dev/sda4: LABEL="srv" UUID="..."
/dev/sda5: LABEL="nextcloud-data" UUID="..."

Anschließend wird die fstab der neuen Installation bearbeitet – nicht die des laufenden Systems, sondern die auf der Zielplatte:

sudo nano /mnt/newroot/etc/fstab

Dort müssen die UUIDs an die neue Hardware angepasst werden.

In meinem Fall sah das vereinfacht etwa so aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Root
UUID=5da13e7f-8839-4b51-a078-1b25ff0860a3 / ext4 errors=remount-ro 0 1

# /var
UUID=56544b0f-3e1f-46a0-a746-488b1be66316 /var ext4 defaults 0 2

# Swap
UUID=f40e8bc0-9673-43e8-9a7d-da62674ee74f none swap sw 0 0

# /srv
UUID=bd85d273-63b6-46de-b373-94cca85c3cdf /srv ext4 defaults 0 2

# Nextcloud-Daten
UUID=beac83cb-0c00-4c73-a7f8-8e992bf95ddb /mnt/nextcloud-data ext4 defaults,nofail 0 2

Gerade ausgelagerte Verzeichnisse wie /srv, /var oder ein separates Nextcloud-Datenverzeichnis sollte man hier sorgfältig prüfen.

Denn wenn hier ein Fehler steckt, startet das System zwar möglicherweise – aber Dienste wie Apache, MariaDB oder Nextcloud wirken plötzlich „verschwunden“, weil ihre Daten schlicht nicht eingebunden wurden.

Ein schneller Kontrollblick lohnt sich also.


Schritt 6: GRUB installieren – wenn der neue Datenträger nicht booten will

Nachdem sämtliche Daten kopiert und die fstab angepasst wurde, fehlt noch ein entscheidender Schritt:

Der neue Datenträger muss bootfähig gemacht werden.

Genau hier bin ich selbst zunächst in eine Falle gelaufen.

Der erste Bootversuch endete schlicht in einem GRUB load read error.

Die Ursache: Zwar war das System vollständig kopiert worden – der Bootloader jedoch nicht korrekt installiert.

Zunächst müssen die notwendigen Systempfade eingebunden werden:

1
2
3
4
sudo mount --bind /dev /mnt/newroot/dev
sudo mount --bind /proc /mnt/newroot/proc
sudo mount --bind /sys /mnt/newroot/sys
sudo mount --bind /run /mnt/newroot/run

Danach wechselt man in die neue Installation mit: sudo chroot /mnt/newroot /bin/bash.

Nun kann GRUB auf der neuen Festplatte installiert werden:

1
2
grub-install /dev/sda
update-grub

Wichtig:

Wer – wie ich – noch im Legacy-BIOS-Modus mit GPT-Partitionierung arbeitet, benötigt zwingend eine kleine BIOS boot partition.

Diese sollte ungefähr 2 MiB groß sein und den Typ bios_grub besitzen.

Fehlt diese Partition, quittiert grub-install den Dienst mit einer Fehlermeldung, da GRUB keinen Platz findet, um sich korrekt einzubetten.

Nach erfolgreicher Installation kann der chroot wieder verlassen werden: exit.

Und anschließend alles sauber aushängen: sudo umount -R /mnt/newroot.

Spätestens jetzt sollte die neue Festplatte eigenständig bootfähig sein.

Ein Tipp aus eigener Erfahrung:

Beim ersten Test am besten die alte NVMe physisch abziehen oder im BIOS die Bootreihenfolge anpassen. Sonst landet man schnell versehentlich wieder auf dem alten System – und wundert sich später, warum Änderungen scheinbar „nicht übernommen“ wurden.

Troubleshooting: Wenn nach der Migration nicht sofort alles läuft

Wer glaubt, nach einem erfolgreichen rsync sei die Arbeit erledigt, wird bei produktiven Systemen oft eines Besseren belehrt. Gerade wenn eine bestehende Linux-Installation mitsamt Diensten wie Nextcloud, MariaDB oder Redis auf neue Hardware umzieht, können kleine Inkonsistenzen große Auswirkungen haben.

In meinem Fall startete das System zwar wieder, doch der Weg zurück zu einer funktionierenden Nextcloud war alles andere als geradlinig.

Apache startet nicht mehr

Der erste Stolperstein zeigte sich direkt nach dem Booten: Apache verweigerte den Dienst.

Ein Blick in die Logs brachte schnell Klarheit:

1
sudo journalctl -xeu apache2.service

Die Ursache war letztlich banal, aber folgenreich: Beim Kopieren der alten Installation war die separate /var-Partition nicht vollständig übernommen worden. Dadurch fehlten unter anderem:

  • /var/www/nextcloud
  • /var/log/apache2
  • Teile von /var/lib

Die Lösung bestand darin, die Inhalte der alten /var-Partition erneut sauber auf die neue Partition zu kopieren:

1
2
3
sudo rsync -aAXHv --numeric-ids \
/mnt/oldvar/ \
/var/

Anschließend ließ sich Apache wieder starten:

1
sudo systemctl restart apache2

MariaDB startet nicht

Kurz darauf zeigte sich das nächste Problem: Nextcloud meldete nur noch einen internen Serverfehler.

Die eigentliche Ursache offenbarte sich erst im Terminal:

1
sudo systemctl status mariadb

MariaDB konnte keine Dateien in /var/lib/mysql anlegen, weil auch hier Teile der ursprünglichen Daten fehlten.

Nach dem erneuten Kopieren von /var startete der Datenbankserver wieder problemlos:

1
sudo systemctl start mariadb

Ein schneller Funktionstest:

1
sudo -u www-data php /var/www/nextcloud/occ status

Zeigt Nextcloud hier Versionsinformationen statt einer Fehlermeldung, ist die Datenbankverbindung wiederhergestellt.


Nextcloud zeigt nur „Interner Serverfehler“

Nach erfolgreichem Datenbankstart wirkte die Nextcloud zunächst weiterhin defekt. Die Weboberfläche lud zwar, endete jedoch in einem internen Serverfehler.

In solchen Fällen lohnt sich der Blick direkt in die Nextcloud-Logs:

1
sudo tail -f /mnt/nextcloud-data/nextcloud-data/nextcloud.log

In meinem Fall war nicht das Kernsystem defekt, sondern die Office-Integration (richdocuments / Collabora Online). Während der Migration waren Teile des App-Caches beschädigt worden.

Die pragmatische Lösung:

1
2
sudo -u www-data php /var/www/nextcloud/occ app:disable richdocuments
sudo -u www-data php /var/www/nextcloud/occ app:disable richdocumentscode

Nach einem Neustart von Apache und PHP funktionierte die Nextcloud wieder normal:

1
2
sudo systemctl restart php8.4-fpm
sudo systemctl restart apache2

Die Office-Funktion kann später jederzeit neu installiert oder sauber reaktiviert werden.


Einzelne Updates funktionieren – „Alle aktualisieren“ aber nicht

Ein besonders kurioses Problem zeigte sich erst später: Einzelne App-Updates liefen problemlos durch, doch der Button „Alle aktualisieren“ quittierte den Dienst mit Fehlermeldungen.

Die Ursache lag in einer sehr konservativen PHP-FPM-Konfiguration. Standardmäßig waren nur fünf Worker-Prozesse erlaubt – für mehrere parallele Updatevorgänge deutlich zu wenig.

Die aktuelle Konfiguration prüfen:

1
grep -E "pm.max_children|pm.max_requests|pm.start_servers|pm.max_spare_servers|pm.min_spare_servers" /etc/php/8.4/fpm/pool.d/www.conf

Die Anpassung erfolgt in:

1
sudo nano /etc/php/8.4/fpm/pool.d/www.conf

Folgende Werte erwiesen sich als deutlich stabiler:

1
2
3
4
5
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500

Danach genügt ein Neustart:

1
2
sudo systemctl restart php8.4-fpm
sudo systemctl restart apache2

Anschließend funktionierte auch die Sammelaktualisierung der Apps wieder zuverlässig.


Was man aus der Migration mitnehmen sollte

Der eigentliche Umzug der Daten war am Ende der einfachste Teil. Die eigentliche Herausforderung bestand darin, versteckte Abhängigkeiten zwischen Partitionen, Diensten und Pfaden sauber wiederherzustellen.

Gerade bei älteren Linux-Systemen mit separaten Partitionen für /var, /srv oder ausgelagerten Datenverzeichnissen lohnt es sich, nach der Migration gezielt folgende Dienste zu prüfen:

1
2
3
4
sudo systemctl status apache2
sudo systemctl status mariadb
sudo systemctl status php8.4-fpm
sudo systemctl status redis-server

Denn wenn eines dieser Zahnräder fehlt, steht zwar das Betriebssystem – die eigentliche Anwendung aber oft nicht.