Sonntag, 10. August 2025

Nextcloud Migration zu All-in-One

Mein finales Migrationsziel soll eine Nextcloud AIO Installation sein. Dafür gibt es ein gutes Migrationsdokument (unbedingt zur Vorbereitung lesen). Auch hier steht wieder der explizite Hinweis, dass eine komplette Migration (Datenbank und Dateien) schwieriger ist und nicht unbedingt funktionieren muss. Es hat aber bei meiner Migration von einem auf den anderen Server auch funktioniert und ich hatte auch hiermit Erfolg. 

Anders als bei meiner Migration auf Docker Microservice wird hier nicht die komplette Installation sondern nur das Datenverzeichnis übernommen. Ganz nebenbei hatte ich dabei das Gefühl einer gewissen "Reinigung", hartnäckige Einträge im Protokoll waren nach dieser Migration erstmal verschwunden. 

Ich habe den Code aus dem Originaldokument etwas ergänzt und angepasst und noch ein paar Feinheiten aus anderen Quellen zusammengetragen.

Vorbereitung Quellsystem

Da mein Quellsystem mit Mariadb läuft, muss zunächst die Datenbank noch Postgres konvertiert werden. Ich habe dazu die docker-compose.yml einfach um einen postgres Container (explizit gleiche Version 17.5 wie im Quellsystem) mit der Bezeichnung db2 erweitert (Quelle: docker hub).

Ich habe diese Migration intern gemacht, mit einer Kopie des Produktivstems. Um die Passwörter muss man sich damit keine Sorgen machen, man kann die Codezeilen so verwenden wie sie sind. Anderenfalls muss man unbedingt gute Passwörter eintragen!

  db2:
    image: postgres:17.5
    restart: always
    # set shared memory limit when using docker compose
    shm_size: 128mb
    environment:
      POSTGRES_PASSWORD: example

docker container starten

docker compose up -d

Alles weitere entspricht diesem Dokumentes.

Datenbank erzeugen

export PG_USER="ncadmin"                  # This is a temporary user ...
export PG_PASSWORD="my-temporary-password"
export PG_DATABASE="nextcloud_db"

docker exec -u postgres -i docker-db2-1 psql <<END
CREATE USER $PG_USER WITH PASSWORD '$PG_PASSWORD' CREATEDB;
CREATE DATABASE $PG_DATABASE WITH OWNER $PG_USER TEMPLATE template0 ENCODING 'UTF8';
GRANT ALL PRIVILEGES ON DATABASE $PG_DATABASE TO $PG_USER;
GRANT ALL PRIVILEGES ON SCHEMA public TO $PG_USER;
END

Datenbank konvertieren

docker exec -u www-data -i docker-app-1 php \
occ db:convert-type --all-apps --password "$PG_PASSWORD" pgsql "$PG_USER" db2 "$PG_DATABASE"

Dump erzeugen

docker exec -u postgres docker-db2-1 pg_dump "$PG_DATABASE"  > ./database-dump.sql

Da nicht die komplette Installation sondern nur das Datenverzeichnis übernommen werden, müssen alle Apps die im Quellsystem installiert waren - vor der Migration - auf dem Zielsystem installiert werden.

Anstatt in der Web-UI zu suchen kann man eine Liste der installierten Apps von beiden Systemen  erzeugen, vergleichen und fehlende Apps installieren. Diesen Befehl für den Quellcontainer docker-app-1 und den Zielcontainer nextcloud-aio-nextcloud ausführen, bei mir auf separaten Host Systemen.

docker exec <nextcloud Container> php occ app:list

Jetzt wird das Zielsystem gestartet und falls noch nicht erfolgt, fertig installiert.

Zielsystem installieren

Ich betreibe die Nextcloud später hinter einem Reverse Proxy, das muss beim Start berücksichtigt werden (Quelle). Die Installation erfolgt einfach durch Start eines Mastercontainers, dieser orchestriert die restlichen Container selbst (dauert etwas). Entweder als Kommandozeile:

docker run \
--init \
--sig-proxy=false \
--name nextcloud-aio-mastercontainer \
--restart always \
--publish 8080:8080 \
--env APACHE_PORT=11000 \
--env APACHE_IP_BINDING=0.0.0.0 \
--env APACHE_ADDITIONAL_NETWORK="" \
--env SKIP_DOMAIN_VALIDATION=false \
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
--volume /var/run/docker.sock:/var/run/docker.sock:ro ghcr.io/nextcloud-releases/all-in-one:latest

Oder durch eine docker-compose.yml, hier als gut kommentiertes Grundgerüst verfügbar.

Die Installation/Deinstallation der Apps kann man auch mittels occ Befehl durchführen. Ich habe nicht herausgefunden, wie man an den app Namen einer nicht installierten und nicht deaktivierten App herankommt.

Ist die Installation der Apps abgeschlossen wird im AIO Interface ein backup gestartet und die Container werden nicht wieder gestartet! Mit Hilfe von temporären Containern werden die nächsten Schritte erledigt. 

Da ich auf zwei Systemen arbeite, muss ich die Daten vom Quellsystem zunächst kopieren. 

mkdir data && cd data
scp root@192.168.xx.yy:docker/database-dump.sql ./
rsync -av --delete -e ssh root@192.168.xx.yy:docker/DocRoot ./

Im Dump muss der Pfad zum data Pfad angepasst werden.

sed -i "s|/var/www/html|/mnt/ncdata|" database-dump.sql

Der Dump wird im Container so platziert, dass er beim nächsten Start in die Datenbank importiert wird und die alten Daten ersetzt.

docker run --rm --volume nextcloud_aio_database_dump:/mnt/data:rw alpine rm /mnt/data/database-dump.sql
docker cp database-dump.sql nextcloud-aio-database:/mnt/data/
docker run --rm --volume nextcloud_aio_database_dump:/mnt/data:rw alpine chmod 777 /mnt/data/database-dump.sql
docker run --rm --volume nextcloud_aio_database_dump:/mnt/data:rw alpine rm /mnt/data/initial-cleanup-done

Das data Verzeichnis im Zielsystem wird gelöscht und durch die Daten vom Quellsystem ersetzt.

docker run --rm --volume nextcloud_aio_nextcloud_data:/mnt/ncdata:rw alpine sh -c "rm -rf /mnt/ncdata/*"
docker cp --follow-link /root/data/DocRoot/data/. nextcloud-aio-nextcloud:/mnt/ncdata/

Berechtigungen setzen

docker run --rm --volume nextcloud_aio_nextcloud_data:/mnt/ncdata:rw alpine chown -R 33:0 /mnt/ncdata/
docker run --rm --volume nextcloud_aio_nextcloud_data:/mnt/ncdata:rw alpine chmod -R 750 /mnt/ncdata/

Werte aus der alten config lesen

passwordsalt=$(awk -F"'" '/passwordsalt/{print $4}' DocRoot/config/config.php)
secret=$(awk -F"'" '/secret/{print $4}' DocRoot/config/config.php)
instanceid=$(awk -F"'" '/instanceid/{print $4}' DocRoot/config/config.php)

und in die neue config schreiben.

docker run --rm --volume nextcloud_aio_nextcloud:/var/www/html:rw alpine \
sed -i "s/'passwordsalt' => '.*'/'passwordsalt' => '$passwordsalt'/;\
s/'secret' => '.*'/'secret' => '$secret'/;\
s/'instanceid' => '.*'/'instanceid' => '$instanceid'/" /var/www/html/config/config.php

Jetzt die Container im AIO Interface wieder starten, beim Start wird die Migration durch den automatischen Import der Datenbank beendet.

Feinheiten

Die url der AIO Installation kann man nicht einfach in der config ändern. Dies muss für ein Testszenario berücksichtigt werden.

Die url in der config.php ändern - ich bin noch nicht sicher was in welcher Reihenfolge Beachtung findet

docker run --rm --volume nextcloud_aio_nextcloud:/var/www/html:rw alpine \
sed -i "s/old.domain.tld/new.domain.tld/" /var/www/html/config/config.php

Entscheidend ist die configuration.json im Mastercontainer 

docker run --rm --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config:rw alpine \
sed -i "s/old.domain.tld/new.domain.tld/" /mnt/docker-aio-config/data/configuration.json

Falls der Fehler in der Überprüfung nach dem Start steht: die Telefon Region ist nicht gesetzt - so geht es:

docker exec -u www-data -it nextcloud-aio-nextcloud php occ config:system:set default_phone_region --value="DE"

ToDo

Code


Keine Kommentare:

Kommentar veröffentlichen