English version · Version Markdown, lisible par un agent · v0.3.0
Migrer depuis Supabase
Cette page déplace un projet Supabase vers un projet Bastide : le schéma et les données, les utilisateurs de l'authentification, les seaux et les objets du stockage. Votre application garde supabase-js : elle change l'adresse et la clé du projet.
Ce qu'il faut avant de commencer
- Un projet Bastide créé avec son backend (
project_create_with_backend), vierge : l'importeur refuse un projet cible déjà occupé, avant d'écrire. - L'adresse de connexion directe de la base source (rôle
postgres, connexion directe ou mode session), sa cléservice_role, et sa cléanonsi vous voulez garder les clés historiques. - Un exploitant : pendant la bêta sur invitation, l'import est un geste d'exploitant, pas une opération du registre. Il ouvre la base du locataire en administrateur pour installer les extensions.
- Lisez d'abord la section « Incompatibilités connues » plus bas : un client qui s'appuie sur SAML, sur le point S3 ou sur
postgres_changesne passe pas tel quel.
1. Lancer l'import
Les secrets de la source ne passent pas par la ligne de commande, que ps montre à tout utilisateur de l'hôte : ils se lisent dans l'environnement.
SUPABASE_DB_URL='postgres://postgres:<mot-de-passe>@db.<ref>.supabase.co:5432/postgres' SUPABASE_SERVICE_ROLE_KEY='<service_role>' SUPABASE_ANON_KEY='<anon>' pnpm importer:supabase <bak_…> --stockage https://<ref>.supabase.co --rapport rapport.json
--stockage est exigé dès que la source a un seau ; sans lui l'import s'interrompt et le dit. L'ordre des étapes n'est pas libre : inventaire et cible jugée vierge, utilisateurs, schéma et données (politiques et droits recomposés, en une transaction), stockage (une somme par objet), comparaison du catalogue et recomptage des lignes, rapport.
Le code de sortie dit l'issue : 0 importé, 3 importé avec des écarts à lire dans le rapport, 1 interrompu ou échoué, 2 pas fait (argument ou variable manquants). En cas d'échec, l'importeur ne défait rien : il écrit dans un projet neuf, que vous retirez si besoin ; chaque étape qui écrit le fait dans une transaction, et le rapport dit laquelle s'est arrêtée.
L'importeur n'écrit rien à la source : ni jeton révoqué, ni passage en lecture seule.
2. Double exécution : faire tourner les deux côtés avant de basculer
Tant que vous ne basculez pas, la source reste votre application vivante. La procédure :
1. Importer comme ci-dessus. L'import est une copie à un instant donné. 2. Garder les clés d'origine. Fournies à l'import, SUPABASE_ANON_KEY et SUPABASE_SERVICE_ROLE_KEY sont rangées par leur empreinte et restent acceptées douze mois, chaque réponse portant Deprecation: true et Sunset (voir LIM-09). Une copie de votre application peut donc viser Bastide sans changer ses clés : seule l'adresse du projet change. 3. Faire tourner une copie de l'application sur Bastide, à côté de la production qui reste sur Supabase : la même adresse de projet remplacée, les mêmes clés, le même parcours. Rejouez vos parcours ordinaires : inscription, confirmation, connexion, lecture, écriture, téléversement. 4. Comparer. Lisez le rapport (--rapport) : catalogue comparé, lignes recomptées, somme de chaque objet. Comparez ce que vos parcours rendent des deux côtés. 5. **Passer aux clés sb_publishable_… et sb_secret_…** (backend.key.create) avant l'échéance des douze mois, puis révoquez les clés historiques. 6. Basculer. Aucune réplication continue n'existe : les écritures faites à la source après l'import ne suivent pas. La fenêtre de lecture seule de la source (TR-194, EX-MIG-140) est prévue au lot L2 et n'existe pas encore. Pour basculer sans perte, suspendez vous-même les écritures de l'application, lancez l'import dans un NOUVEAU projet Bastide vierge, vérifiez le rapport, puis changez l'adresse de production.
Un retour arrière avant l'étape 6 est sans effet sur la source : ne rien faire côté Supabase, et retirer le projet Bastide.
3. Brancher l'application
Remplacez l'adresse et la clé du projet. Les chemins de Supabase sont tenus sans réécriture : https://<projet>.<domaine>/rest/v1/…, /auth/v1/…, /realtime/v1/…. Les en-têtes de supabase-js sont ceux de Supabase : la clé dans apikey, un jeton de session dans Authorization.
Incompatibilités connues
Chaque limite ci-dessous est reproduite par un test (pnpm limites) ; la page publique est https://bastide.app/limites-supabase.
LIM-01: une réponse REST porte au plus 1000 lignes, tronquée sans erreur ; paginez (Range, oulimitetoffset).LIM-02: une ressource ne s'embarque que le long d'une clé étrangère déclarée, sinon 400PGRST200; déclarez la clé, ou exposez une vue.LIM-03: en mode transaction du mutualiseur (celui des connexions directes, par défaut),NOTIFYn'atteint pas un client qui faitLISTEN; écoutez depuis une connexion en mode session.LIM-04: en mode transaction,pg_advisory_lockn'exclut pas une autre connexion du même projet ; employezpg_advisory_xact_lock, ou le mode session.LIM-05: en mode transaction, l'état de session n'est pas isolé (SET, table temporaire, curseurWITH HOLD) ; employezSET LOCAL,ON COMMIT DROP, ou le mode session.LIM-06: ne sont pas servis la connexion d'entreprise SAML (signInWithSSO), la liaison d'une identité (linkIdentity) et/auth/v1/settings(404,chemin_auth_inconnu). Une connexion d'entreprise passe par Keycloak en OpenID Connect. Les douze fournisseurs designInWithOAuthet la double authentification sont servis.LIM-07: le point compatible S3 (/storage/v1/s3) n'est pas servi (404,chemin_inconnu) ; il viendra avecEX-DATA-370(lot L2). Le stockage destorage-jsest servi.LIM-08: le temps réel sert la diffusion et la présence, pas l'écoute des changements : un abonnementpostgres_changesest refusé. Employezselect realtime.diffuser_les_changements('public.ma_table').LIM-09: les clés historiquesanonetservice_rolene valent que pour un projet importé, deux clés d'origine seulement, douze mois. Toute autre reçoit 401cle_refusee.LIM-10:updateUserne change que le mot de passe ; une adresse ou des métadonnées sont refusées (400,changement_d_adresse_ailleurs,metadonnees_non_rangees). EmployezPOST /auth/v1/user/email, et une table du projet pour les métadonnées.LIM-11: une table n'est accordée aux rôles de l'API que si elle porte la sécurité au niveau des lignes ET au moins une politique ; les rôles portent le nom de la base en préfixe, donc ungrant … to authenticatedécrit tel quel est refusé (code42704).
Autres écarts mesurés : l'utilisateur rendu ne porte pas last_sign_in_at (le champ est absent, pas nul) ; ne sont ni mesurés ni servis les codes de secours, le web3 et le changement d'adresse par le client. Le taux de la suite d'intégration officielle de supabase-js (95 % exigés par EX-DATA-090) n'est pas encore joué : elle suppose des clés asymétriques avec un point JWKS, prévues au lot L2.
Les briques sous le plan de données sont six, épinglées par empreinte (matrice des briques) : PostgreSQL 17, pgvector, Supavisor, PostgREST, imgproxy (édition libre) et SeaweedFS. Le client éprouvé est @supabase/supabase-js 2.117.2. L'import ne reprend que les extensions admises par le palier du projet cible.
Voir aussi : Migrer depuis Vercel, Sortir de Bastide.