Aller au contenu

Backups

Pourquoi votre dump Supabase ne contient aucun utilisateur

Lancez supabase db dump tout seul et vous obtenez la forme de votre base et aucune de ses lignes, sans le schéma auth où vivent vos utilisateurs.

Vlad Tkachenko11 min de lecture
Un fichier scellé contenant trois lignes de données, et à côté un registre réglé de personnes resté dehors et coupé par le bord du cadre.

En bref

  • Supabase publie sa sauvegarde en trois commandes. Celle que vous avez sans doute lancée est la deuxième, et vos utilisateurs sont dans la troisième.
  • Lancez supabase db dump sans autre option et vous obtenez la forme de vos tables et rien de leur contenu, et le schéma auth où vivent vos utilisateurs est laissé de côté même là.
  • Une seule recherche dans le fichier que vous avez déjà vous dit laquelle de trois choses vous tenez.

Vous avez fait ce qu'il fallait. Vous avez cherché comment sauvegarder une base de données Supabase, lancé la commande trouvée et rangé le fichier en lieu sûr.

Puis un jour vous en avez besoin. Vous rejouez le fichier dans un projet neuf et la restauration se termine sans une seule erreur. Chaque table que vous avez créée est là, et chacune d'elles est vide. Vos utilisateurs sont encore plus mal lotis : la partie de la base où ils vivent, un schéma nommé auth, n'a jamais atteint le fichier.

Voici la partie que presque tous les guides sautent : supabase db dump tout seul n'est pas une copie de vos données. Sans autre option, il écrit la forme de votre base et rien de son contenu, et il laisse auth de côté même là. Supabase publie la sauvegarde en trois commandes, et vos comptes voyagent dans la troisième.

Il aide de penser à un hôtel. Vos tables sont les chambres et tout ce qu'elles contiennent. Le registre de la réception, celui où figure le nom de chaque client, appartient à l'hôtel. Et un plan vous montre chaque chambre du bâtiment sans y mettre un seul client.

Une sauvegarde Supabase contient-elle mes utilisateurs ?

Cela dépend de la commande qui a écrit le fichier, et la commande que lancent la plupart des gens ne les contient pas.

Vos utilisateurs ne sont pas des lignes de vos propres tables. Supabase les garde dans un tiroir à part de la même base, le schéma auth, avec leurs mots de passe hachés, les fournisseurs par lesquels ils se sont connectés et les sessions qu'ils tiennent. Vos tables à vous sont dans un tiroir nommé public, et chaque colonne user_id qui s'y trouve est une référence vers auth.

Un schéma est exactement cela : un tiroir nommé à l'intérieur d'une base. public est le vôtre. auth est celui de Supabase, et storage aussi, qui garde la ligne décrivant chaque fichier envoyé. La documentation de Supabase appelle ceux-là ses schémas gérés et dit qu'ils n'ont normalement pas besoin d'être récupérés sauf si vous les avez modifiés, ce qui explique pourquoi l'outillage les traite autrement que vos tables.

Cette séparation est ce qui permet à une commande de produire deux fichiers qui se ressemblent et contiennent des choses entièrement différentes.

Lancée toute seule, la commande de dump copie la forme de votre propre tiroir et s'arrête à la frontière des deux que Supabase gère.

Ce que la commande de dump écrit toute seule

Le plan. Aucune ligne, et rien de auth.

La page de référence de Supabase pour la commande le dit en deux phrases. Elle lance pg_dump avec des options supplémentaires pour exclure les schémas gérés par Supabase, et les ignorés comprennent auth, storage et ceux créés par les extensions. La même page dit ensuite que le dump par défaut ne contient ni données ni rôles personnalisés, et que vous les obtenez en les demandant avec --data-only et --role-only.

Donc ceci, qui est ce que vous avez sans doute lancé :

supabase db dump --db-url "postgresql://…your connection string…" -f backup.sql

produit un fichier rempli d'instructions CREATE TABLE. Chaque colonne, chaque index, chaque politique que vous avez écrite sur vos propres tables, et pas une seule ligne de quoi que ce soit.

La raison pour laquelle c'est pire qu'un fichier manifestement vide, c'est que ça marche. Il n'a pas l'air petit non plus : chaque définition de table, chaque index et chaque politique que vous avez écrits y figurent, ce qui pour une vraie application fait beaucoup de texte. Une sauvegarde vide s'annonce toute seule. Celle-ci se restaure proprement, et la première chose qui vous dit le contraire est une page de connexion qu'aucun compte ne franchit.

La même commande écrit les deux. Lequel vous tenez dépend d'une option, et tous les deux se restaurent sans erreur.

Comment vérifier le dump que j'ai déjà ?

Ouvrez-le dans un éditeur de texte et cherchez auth. Ce qui remonte range votre fichier dans un de trois groupes.

  1. Aucune correspondance. Le schéma auth n'est dans ce fichier sous aucune forme. C'est ce qu'écrit un supabase db dump tout court.
  2. Des correspondances, mais seulement dans des lignes commençant par CREATE, ALTER ou GRANT. Vous avez le dessin du registre et personne dedans.
  3. Une ligne COPY "auth"."users" ou COPY auth.users, avec des lignes de données en dessous jusqu'à une ligne contenant \. Ou une suite de lignes commençant par INSERT INTO "auth"."users". Vos comptes sont dedans.

Si vous préférez le faire en ligne de commande, deux greps répondent à la même question :

grep -c 'auth.*users' backup.sql
grep -n 'COPY .*auth.*users\|INSERT INTO .*auth.*users' backup.sql

Le premier dit si le schéma a atteint le fichier. Le second dit si les personnes y sont arrivées. Un zéro des deux, sur un fichier sur lequel vous comptiez, vaut mieux être découvert aujourd'hui qu'au matin où vous en avez besoin.

Cherchez storage pendant que vous y êtes, et lisez avec soin ce que vous trouvez. Ces lignes sont la liste de vos fichiers envoyés, ce qui est autre chose que les fichiers, et aucune sauvegarde de base sur aucun plan ne contient ceux-là.

Comment exporter les utilisateurs auth de Supabase ?

Avec la commande de données, qui est une autre commande que celle qui écrit le schéma.

Le guide de sauvegarde et restauration de Supabase publie la sauvegarde en trois fichiers, et il vaut la peine de les voir ensemble parce que leur forme est la réponse :

supabase db dump --db-url "postgresql://…" -f roles.sql --role-only
supabase db dump --db-url "postgresql://…" -f schema.sql
supabase db dump --db-url "postgresql://…" -f data.sql --use-copy --data-only \
  -x "storage.buckets_vectors" -x "storage.vector_indexes"

La deuxième ligne est celle qui se lance toute seule. La troisième est celle où sont vos utilisateurs.

Ces deux faits ressemblent à une contradiction et n'en sont pas. La phrase de la page de référence de Supabase sur l'exclusion de auth décrit le dump de schéma, et le dump de données parcourt ce schéma lui aussi.

Si vous ne voulez que les comptes, nommez le schéma et vous obtenez ce tiroir seul :

supabase db dump --db-url "postgresql://…" -f users.sql --data-only --use-copy --schema auth

Avant de vous fier à l'une de ces commandes, ajoutez --dry-run et lisez ce qui remonte. Elle imprime la commande pg_dump que l'outil s'apprête à lancer sans la lancer, donc vous voyez vous-même quels schémas sont inclus et lesquels sont exclus sur la version que vous avez installée. Lisez cette sortie une fois et vous n'aurez plus jamais à croire cet article, ni aucun autre, ce qui compte parce que les options bougent bel et bien entre les versions et que le fichier a la même tête dans les deux cas.

Il y a aussi la voie directe, et c'est à cela que sert un pg_dump tout court : nommez les tiroirs que vous voulez et il les prend.

pg_dump "postgresql://…" --schema public --schema auth --schema storage \
  --no-owner --file backup.sql

Une chose à noter sur le fichier de schéma, parce qu'elle explique pourquoi tout cela est séparé. Un nouveau projet Supabase arrive avec un schéma auth déjà construit, dans la version que le service de connexion fait tourner aujourd'hui. Y rejouer la version de votre ancien projet poserait un dessin plus vieux par-dessus un qui marche. Ce que vous voulez emporter, c'est le contenu du registre, et c'est le fichier de données qui le tient.

Ce qui casse au moment de remettre les utilisateurs

Deux choses, et Supabase documente les deux.

Les triggers, qui peuvent chiffrer une colonne deux fois. La commande de restauration du guide de Supabase porte en son milieu une instruction facile à prendre pour du remplissage :

psql \
  --single-transaction \
  --variable ON_ERROR_STOP=1 \
  --file roles.sql \
  --file schema.sql \
  --command 'SET session_replication_role = replica' \
  --file data.sql \
  --dbname "postgresql://…"

Cette ligne du milieu coupe les triggers le temps de l'opération, et le guide dit qu'elle est là pour empêcher des colonnes d'être chiffrées une seconde fois à l'entrée. Rejouez un fichier de données sans elle et les mots de passe arrivent déjà brouillés par un traitement qui leur avait déjà été appliqué, et rien ensuite ne le défait.

La propriété et les droits, qui arrêtent le rejeu. Un dump pris sur un projet Supabase porte des lignes qui renvoient à des rôles auxquels le nouveau projet ne vous laisse pas toucher. Les notes de dépannage du même guide disent de commenter toute ligne contenant ALTER ... OWNER TO "supabase_admin" dans schema.sql, et une ligne précise GRANT "postgres" TO "cli_login_postgres" dans roles.sql. Les deux sont une modification de texte avant de commencer, et les deux arrêtent le rejeu avec la ligne sur laquelle il a buté affichée à l'écran.

Mes utilisateurs devront-ils se reconnecter ?

Leurs mots de passe passent. Leurs sessions non, sauf si vous emportez une chose de plus avec eux.

Supabase dit que vous pouvez migrer chaque table du schéma auth, utilisateurs et mots de passe hachés compris, donc personne n'a à réinitialiser un mot de passe qu'il avait déjà. Aucun mot de passe n'est lisible à aucun moment là-dedans ; ce qui se déplace, c'est son haché.

Une session est autre chose. Elle est prouvée par un jeton signé avec le secret JWT propre à votre projet, et chaque projet a le sien. Supabase dit que si le nouveau projet signe avec un autre secret, chaque jeton déjà présent dans le navigateur de quelqu'un devient invalide et il lui est demandé de se reconnecter. Vous pouvez éviter cela en posant le secret de l'ancien projet sur le nouveau, et le prix est écrit sur la même page : changer le secret JWT régénère les clés anon et service_role de ce projet, donc il faut donner les nouvelles à votre application avant qu'elle puisse parler à quoi que ce soit. Quelle clé est laquelle, et laquelle a sa place dans votre application, c'est ce dont il faut être sûr avant d'en coller une.

La version honnête est donc qu'une restauration demande le plus souvent à tout le monde de se connecter une fois. C'est un courriel au support. Ce n'est pas un compte perdu, et la différence entre les deux tient à ce que le schéma auth ait été dans votre fichier.

Trois choses n'y sont toujours pas, quoi que vous fassiez des options. Vos fichiers envoyés, parce que Storage garde les octets hors de la base et aucun dump sur aucun plan ne les atteint. Vos edge functions, qui sont un téléchargement à part et dont les import maps, note Supabase, ne sont pas récupérés automatiquement. Et les réglages de votre projet, qui sont de la configuration et non des données et se ressaisissent à la main.

Ce qu'il faut faire cette semaine

Que faire

  • Prenez le fichier de sauvegarde le plus récent que vous ayez et cherchez-y auth. Groupe un, deux ou trois de la section ci-dessus, et vous saurez en une minute.
  • Si c'est le groupe un ou deux, prenez aujourd'hui un dump de données avec --data-only et --use-copy, et gardez-le à côté du fichier de schéma au lieu de le remplacer. Il vous faut les deux.
  • Ajoutez --dry-run à la commande que vous retenez et lisez la sortie une fois, pour savoir quels tiroirs votre version de l'outil emporte.
  • Notez l'ordre de la restauration là où vous le retrouverez : roles, puis schema, puis SET session_replication_role = replica, puis data.
  • Restaurez une fois dans un projet jetable, puis essayez de vous connecter comme un vrai utilisateur. C'est la seule vérification qui teste ce dont parle cet article.

Le faire une fois à la main en vaut la peine quelle que soit la façon dont vous sauvegardez ensuite, parce que tant que vous n'avez pas ouvert un dump vous n'avez eu que le mot sauvegarde. Continuer à la main est une autre question, et les trois voies et ce que chacune coûte est l'endroit où on y répond.

Où Reeve Care trouve sa place

Care prend la copie selon un calendrier, et le registre est dedans.

La copie tient vos tables et vos comptes. Le bouton de restauration remet vos tables et laisse les comptes là où ils sont.
  • Vos comptes sont dans la copie. Le schéma auth voyage avec vos propres tables, parce qu'une copie d'une application Supabase sans ses utilisateurs est une copie de la moitié. Les lignes storage qui décrivent vos fichiers viennent aussi, et les fichiers eux-mêmes dès que vous connectez un identifiant Storage.
  • Le bouton de restauration remet vos tables et laisse les comptes tranquilles. Rejouer auth.users sur un projet vivant déconnecte tout le monde et ramène des comptes que quelqu'un avait supprimés exprès, donc cela reste une demande avec une personne dessus. Appuyer sur le bouton dans la panique ne peut donc pas déconnecter les clients que vous vouliez aider.
  • La copie est relue avant de compter comme prise. La date sur votre tableau de bord est la dernière fois qu'une copie a été ouverte et vérifiée, jamais le moment où un travail a démarré ou un fichier est arrivé.
  • Une restauration prend d'abord un instantané de l'état actuel, donc la restauration elle-même a une annulation.

Care commence à €49 par mois pour une application. C'est un prix de liste, et la page des tarifs est parfois en dessous du chiffre indiqué ici et jamais au-dessus.

Comment une copie est prise, vérifiée et remise est dessiné étape par étape sur la page des sauvegardes Supabase.

Avant de fermer cet onglet, ouvrez votre dump le plus récent et cherchez-y auth. C'est le moyen le plus rapide de savoir si ce que vous appeliez une sauvegarde vous rendrait vos clients, et si la réponse est non, en restaurer une correctement est la prochaine lecture.

FAQ

Une sauvegarde Supabase contient-elle mes utilisateurs ?

Cela dépend de la commande qui a écrit le fichier. Vos utilisateurs vivent dans un schéma nommé auth, qui appartient au service de connexion. Un supabase db dump tout court laisse auth de côté et ne contient aucune ligne de quoi que ce soit, parce que le dump par défaut se limite au schéma. La moitié données du dump, une deuxième commande avec l'option --data-only, est celle qui porte vos utilisateurs. C'est exactement pour cela que Supabase publie la sauvegarde en trois commandes.

Pourquoi auth.users manque-t-il dans mon dump ?

Parce que vous avez presque sûrement lancé le dump de schéma. Supabase documente que la commande exclut ses schémas gérés, que auth et storage font partie des ignorés, et que le dump par défaut ne contient aucune donnée. C'est délibéré : un nouveau projet arrive avec son propre schéma auth déjà construit par le service de connexion, donc y rejouer une copie plus ancienne remplacerait quelque chose qui marche. Ce que vous voulez déplacer, c'est le contenu, et c'est le dump de données qui le porte.

Comment exporter les utilisateurs auth de Supabase ?

Avec la commande de données, qui est séparée de la commande de schéma. Lancez supabase db dump avec --data-only et --use-copy pour écrire un fichier de données, et les tables de auth viennent avec. Si vous ne voulez que les comptes, ajoutez --schema auth et vous obtenez un fichier contenant ce seul schéma. Avant de vous fier à l'une ou à l'autre, ajoutez --dry-run : elle imprime la commande pg_dump que la CLI va lancer sans la lancer, donc vous lisez quels schémas sont inclus sur la version que vous avez.

Les mots de passe survivent-ils à une restauration Supabase ?

Oui, si le schéma auth était dans le fichier. Supabase dit que vous pouvez migrer chaque table du schéma auth, mots de passe hachés compris, donc personne n'a à les réinitialiser ni à les recréer. La seule chose qui peut les ruiner, c'est de rejouer les données sans avoir désactivé les triggers, et c'est pour cela que Supabase place SET session_replication_role = replica au milieu de sa propre commande de restauration. Sautez cette ligne et une colonne déjà chiffrée se fait chiffrer une seconde fois à l'entrée.

Mes utilisateurs resteront-ils connectés après une restauration ?

Pas si le nouveau projet signe avec un autre secret. Une session est prouvée par un jeton signé avec le secret JWT du projet, et Supabase dit qu'un nouveau secret rend les jetons existants invalides, donc il est demandé à tout le monde de se reconnecter. Vous pouvez emporter l'ancien secret et les garder connectés, mais Supabase dit aussi que changer le secret JWT régénère les clés anon et service_role de ce projet, donc votre application a besoin des nouvelles.

Qu'est-ce qu'un dump Supabase laisse encore de côté ?

Vos fichiers envoyés, d'abord. Storage garde une ligne dans votre base pour chaque fichier et le fichier lui-même ailleurs, donc aucun dump de base de données sur aucun plan ne contient les octets. Les edge functions sont un téléchargement à part, et Supabase note que les import maps et les fichiers deno.json ne sont pas récupérés automatiquement. Les réglages du projet, les fournisseurs auth et les secrets sont de la configuration et non des données et vivent dans le tableau de bord, donc ils se ressaisissent à la main dans un nouveau projet.

Écrit par

Vlad Tkachenko

Fondateur de Reeve

Je passe mes journées à examiner des applications créées avec Lovable, Bolt, v0, Cursor et Replit, et la courte liste d'erreurs qui y reviennent sans cesse.

En savoir plus sur l'auteur

À lire ensuite

Tous les articles

Vous ne savez pas où en est votre propre application ?

Lancez une analyse gratuite et obtenez une note claire de A à F en une vingtaine de secondes. Sans compte, sans carte.

Analyser mon application

Vérification externe automatisée, pas un audit complet. L'absence de problème n'est pas une garantie de sécurité.