Manuellement exporter/importer des données d'un Nextcloud à l'autre

Suite à une question sur le forum CHATONS, j'ai écrit cette petite description de mon expérience.

Use case : On a deux instances de Nextcloud qui tournent :

J'avais plusieurs types de données à migrer :

Ce "tuto" n'est pas forcément la meilleure marche à suivre, mais elle a fonctionné pour moi. Restez prudent·es si vous le suivez, faites des backups et vérifiez tout bien !

Avant toute opération casse-gueule, on fait des backups !

1. Récréer les users🔗

Dans l'interface admin de new, j'ai recréé les utilisateurices à la main. Deux personnes en ont profité pour changer de login, ce qui a son importance dans la suite.

2. Transférer les fichiers🔗

Copie🔗

Le dossier data de Nextcloud a cette arborescence :

<root_dir>/data/
<root_dir>/data/<user1>/
<root_dir>/data/<user1>/cache/
<root_dir>/data/<user1>/files/
<root_dir>/data/<user1>/files_trashbin/
<root_dir>/data/<user1>/files/_versions/
<root_dir>/data/<user2>/
<root_dir>/data/<user2>/...
...

Dans mon cas, je ne voulais garder que les fichiers actuels, pas les vieilles versions ni la pouvelle. Je n'ai donc copié que les files/.

Mes deux instances de Nextcloud étaient sur la même machine, j'ai donc fait une série de :

$ rsync -a <old_dir>/data/<old_username>/files/ <new_dir>/data/<new_username>/files/

…copiant ainsi le contenu du premier dossier dans le deuxième (rsync a ce comportement si on laisse le / à la fin du premier dossier, ce qui est déroutant mais pratique).

Pensez à bien donner les fichiers au user php de new, par exemple :

$ chown -R nextcloud <new>/data

Mise à jour dans new🔗

Pour demander à Nextcloud de rescanner les dossiers à la recherche de nouveaux fichiers, il faut utiliser son utilitaire occ :

# Générique, avec le user utilisé par nextcloud
$ occ files:scan --all
# Docker
$ sudo docker exec <image_name> occ files:scan --all
# NixOS
$ sudo nextcloud-occ files:scan --all

On peut déjà vérifier à cette étape dans l'interface web que les fichiers ont bien été reconnus.

3. Inclure les données des applications🔗

Il arrive que des applications stockent des fichiers dans les dossiers des users, auquel cas tout est normalement pris en charge, car on vient de les copier, et qu'en base de données, c'est leur chemin relatif qui est stocké. Il n'a pas changé normalement.

Export SQL🔗

On va d'abord exporter les données d'old. Dans mon cas, l'ancienne instance était une instance Docker, avec PostgreSQL, j'ai donc utilisé cette commande :

$ docker exec -it <nextcloud_db> pgdumpall -U nextcloud > ~/dump.nextcloud.sql

Laïus COPY vs INSERT🔗

Par défaut, PostgreSQL utilise la commande COPY pour ses exports, spécifique à cette base de données. Elle est plus rapide, mais ne met pas à jour les SEQUENCES, ces compteurs qui "retiennent" à quel id on en est pour chaque PRIMARY KEY AUTOINCREMENT, ce qui demande de les mettre ensuite à jour automatiquement C'est sûrement une bien meilleure idée que d'utiliser l'option --inserts, qui exporte les données avec des commandes INSERT.

Je n'ai pas testé, mais je recommande fortement de commencer par essayer avec cette option. Sinon, il faut se préparer à faire des ALTER SEQUENCE <seq_name> RESTART with <new_start>, où <seq_name> est le nom de la table associée avec le suffixe _seq, et où <new_start> est l'id maximal de la table + 1.

Galère les COPY, quoi.

On préfèrera donc

$ docker exec -it <nextcloud_db> pgdumpall --inserts -U nextcloud > ~/dump.nextcloud.sql

Sous laïus🔗

Attention par contre, INSERT pourrait vous poser d'autres problèmes : je pense qu'il va refuser l'insertion d'une ligne qui fait référence à une ligne d'une autre table qui n'existe pas encore. Pour chaque app, il faudra commencer par insérer les données de tables qui ne référencent pas les autres tables.

Exemple : oc_calendarobjects_props contient une colonne objectid et une colonne calendarid, elle doit donc être remplie après les tables oc_calendarobjects et oc_calendars.

Normalement, l'export SQL doit insérer les données dans le bon ordre. Je pense que si vous préservez l'ordre des insertions, tout ira pour le mieux 😇

Sélection des données de l'export🔗

Les tables SQL relatives à un module sont préfixées du nom du module :

Calendar :

oc_calendar_appt_bookings   → vide chez moi
oc_calendar_appt_configs    → vide chez moi
oc_calendar_invitations     
oc_calendar_reminders       
oc_calendar_resources       
oc_calendar_resources_md    
oc_calendar_rooms           → vide chez moi
oc_calendar_rooms_md        → vide chez moi
oc_calendarchanges          
oc_calendarobjects          
oc_calendarobjects_props    
oc_calendars                
oc_calendarsubscriptions    → vide chez moi

Cospend :

oc_cospend_bill_owers       
oc_cospend_bills            
oc_cospend_categories       
oc_cospend_currencies       
oc_cospend_members          
oc_cospend_paymentmodes     
oc_cospend_projects         
oc_cospend_shares           

Deck :

oc_deck_assigned_labels     
oc_deck_assigned_users      
oc_deck_attachment          
oc_deck_board_acl           
oc_deck_boards              
oc_deck_cards               
oc_deck_labels              
oc_deck_stacks              

Ce n'est que ces tables que j'ai gérées. Selon les applications que vous voulez transférer, à vous de chercher les tables associées.

De l'export SQL, on ne gardera que les INSERT des tables sélectionnées, tout le reste (CREATE, ALTER, etc) est à mettre à la poubelle. Votre new s'est déjà occupé de tout ça.

(optionnel) Renommage des users dans l'export🔗

Dans mon cas, des personnes en avaient profité pour changer leur username. Dans Nextcloud, c'est le username qui sert d'id aux users. C'est donc ce username qui est présent dans toutes les clés étrangères.

Dans ce cas, il faut donc chercher toutes les clés étrangères qui référencent la table oc_users et renommer toute instance de <old_username> par <new_username>

Préparation tables de destination🔗

Je vous ne le souhaite vraiment pas, mais peut-être que votre new a déjà des données à ne pas supprimer dans toutes ces tables.

Si ce n'est pas le cas, pensez à bien vider les tables de destination.

(optionnel) Changement des ids🔗

Avant toute opération casse-gueule, on fait des backups !

Si c'est le cas, vous allez très sûrement avoir des conflits d'ids (qui doivent être uniques) entre les vieilles et les nouvelles données. Dans ce cas, une solution (très casse-gueule, mais je ne crois pas qu'il y ait le choix) est d'incrémenter manuellement tous les ids dans l'export. C'est casse-gueule car il faudra aussi incrémenter ces mêmes ids dans toutes les tables qui y font référence.

Exemple :

Si les ids d'oc_calendarobjects ont été incrémentés de 300, il va falloir incrémenter toutes les références à ces ids dans la colonne objectid des tables associées (oc_calendarobjects_props, oc_calendar_reminders, et j'en oublie peut-être)

Import du SQL dans new🔗

Dans la base de données PostgreSQL de new, on va importer les données de notre export SQL modifié comme décrit précédemment.

# Générique
$ sudo -u nextcloud psql nextcloud -f file.sql

Vérifier que tout va bien🔗

Vérifiez que vous pouvez visualiser les données, en créer de nouvelles (créez une liste Deck, un agenda, un évènement, une carte dans une liste Deck, une entrée dans Cospend, etc.)

Et ça devrait être bon (j'espère !)