Comment passer de Supabase à une base de données hébergée chez Hodi ?
Les outils de développement assistés par IA (Lovable, Bolt, v0, Cursor, Claude Code…) proposent presque toujours Supabase par défaut pour la base de données, si vous ne leur donnez pas d'instructions particulières. C'est pratique pour démarrer, mais cela vous lie à un service externe, hébergé hors de votre juridiction, avec un autre abonnement à gérer.
Bonne nouvelle : Supabase, c'est du PostgreSQL. Et votre hébergement Hodi inclut PostgreSQL. Vous n'avez donc pas une migration à faire, mais un déménagement, ce qui change tout.
L'IA qui a écrit votre application peut s'en charger, à condition de bien la piloter. Voici comment.
Vous démarrez tout juste votre développement ?
Le plus simple reste de ne jamais passer par Supabase. Dès votre premier prompt, demandez à votre IA d'utiliser directement une base de données de votre cPanel, PostgreSQL ou MySQL. Vous vous épargnez tout ce qui suit.
Je développe cette application et je l'hébergerai sur un hébergement cPanel Hodi.
Elle sera déployée avec Hodifly. N'utilise ni Supabase, ni aucun service de base
de données externe.
Utilise directement :
- une base PostgreSQL 13 (ou MySQL/MariaDB) hébergée sur le même serveur,
accessible uniquement sur localhost ;
- le pilote pg (node-postgres) pour PostgreSQL, ou mysql2/promise pour MySQL,
avec un pool de connexions ;
- des requêtes paramétrées uniquement, jamais de SQL concaténé ;
- une couche serveur qui authentifie l'utilisateur et vérifie ses droits sur
chaque route : la base n'est jamais appelée depuis le navigateur ;
- des identifiants lus depuis des variables d'environnement
(PGHOST, PGDATABASE, PGUSER, PGPASSWORD) ;
- pour les fichiers envoyés : un dossier persistant dont le chemin vient de la
variable UPLOAD_DIR (ex. /home/moncompte/files/), situé hors de la racine web
et jamais dans le dossier du projet, qui est remplacé à chaque déploiement.
Cible PostgreSQL 13 : n'utilise aucune syntaxe introduite après cette version.
La suite s'adresse à ceux dont l'application utilise déjà Supabase.
Le prompt de déménagement
Copiez ce prompt dans votre outil de développement (Claude Code, Cursor…), avec votre projet ouvert. Il contient tout : les contraintes de votre hébergement et l'ordre des opérations.
Cette application utilise Supabase. Je veux l'héberger sur mon hébergement cPanel Hodi,
avec une base PostgreSQL et un déploiement automatique via Git (Hodifly).
Je n'ai ni Supabase, ni service externe.
Contraintes d'architecture
- PostgreSQL 13, accessible uniquement depuis le serveur (localhost).
N'utilise aucune syntaxe introduite après la version 13.
- La base n'est jamais appelée depuis le navigateur : écris une couche serveur (API)
qui authentifie l'utilisateur et vérifie ses droits sur chaque route.
- Pilote pg (node-postgres) avec pool de connexions, requêtes paramétrées uniquement.
- Identifiants de base via variables d'environnement : PGHOST, PGDATABASE, PGUSER, PGPASSWORD.
- Fichiers envoyés : dossier persistant dont le chemin vient de la variable UPLOAD_DIR
(ex. /home/moncompte/files/), hors de la racine web, et jamais dans le dossier du projet,
qui est intégralement remplacé à chaque déploiement.
- gen_random_uuid() est disponible nativement, tu peux le conserver.
Procède dans cet ordre, en me montrant ton travail à chaque étape :
1. Inventaire. Liste tout ce qui dépend de Supabase (fichier + ligne) : requêtes, auth,
stockage, temps réel, politiques d'accès (RLS), clés. Pour chaque politique d'accès,
écris la règle métier qu'elle exprime. Précise ce qui est appelé depuis le navigateur.
2. Plan. Propose l'architecture cible et explique les compromis.
3. Schéma. Adapte le schéma à PostgreSQL 13. Retire ce qui est propre à Supabase
(schémas internes, rôles anon/authenticated/service_role, politiques RLS).
Conserve types, contraintes, index et clés étrangères.
4. Accès aux données. Remplace tous les appels supabase-js par la couche serveur.
5. Auth et autorisations. Remplace Supabase Auth (mots de passe hachés en argon2id,
sessions par cookie httpOnly). Traduis chaque politique d'accès de l'étape 1 en
vérification côté serveur, centralisée dans un middleware. Le filtrage doit être
dans la requête SQL (WHERE user_id = $1), pas après coup. Donne-moi un tableau :
pour chaque route, qui lit, qui écrit, quelle vérification l'applique.
6. Fichiers et finitions. Remplace Supabase Storage selon la contrainte UPLOAD_DIR.
Propose une alternative réaliste au temps réel et dis-moi ce qui est perdu.
Retire les dépendances Supabase du package.json.
7. Vérification. Reprends l'inventaire de l'étape 1 et coche ce qui est réellement traité.
Donne-moi les tests à faire, dont : un utilisateur ne peut pas lire les données d'un
autre, et un fichier envoyé survit à un redéploiement.
Le reste de cet article explique le pourquoi de ces contraintes, et ce que vous devez faire de votre côté.
Ce qui se transporte, et ce qui reste à faire
Supabase n'est pas seulement une base de données : c'est un ensemble de services construits autour de PostgreSQL. La base se déménage presque telle quelle ; le reste demande du travail.
Ce que Supabase fournit | Chez Hodi |
|---|---|
Base PostgreSQL | ✅ Se transporte quasiment à l'identique |
Types | ✅ Identiques |
Contraintes, index, clés étrangères | ✅ Identiques |
API auto-générée / | ⚠️ À remplacer par une couche serveur |
Auth (comptes, connexion) | ⚠️ À réimplémenter côté serveur |
Règles d'accès (politiques RLS) | ⚠️ À traduire en vérifications dans votre code |
Storage (fichiers) | ⚠️ À basculer sur le système de fichiers |
Realtime (temps réel) | ⚠️ Rarement transposable tel quel |
Et pour vous, concrètement ? Votre schéma, vos données et vos types passent sans conversion. L'essentiel du travail se concentre sur la couche serveur : accès aux données, authentification et autorisations.
Pourquoi une couche serveur ?
Beaucoup d'applications générées par IA appellent Supabase directement depuis le navigateur. C'est possible parce que Supabase expose une API HTTP devant PostgreSQL, et non la base elle-même.
Chez vous, cette API n'existe plus. Une base de données ne s'expose jamais au navigateur. Il faut donc une petite API qui reçoit les requêtes, authentifie l'utilisateur, vérifie ses droits, puis interroge PostgreSQL. C'est elle qui porte désormais la sécurité de votre application, route par route.
Si votre application était un site statique parlant à Supabase, elle devient une application Node ou Python, ce qui nécessite un hébergement Site Pro. Anticipez-le avant de démarrer.
Créer votre base de données dans cPanel
Vous créez vous-même votre base, en quelques clics. Aucune demande à nous adresser.
- Dans cPanel, section Bases de données, ouvrez Bases de données PostgreSQL (ou Bases de données MySQL).
- Créez une base, puis un utilisateur avec un mot de passe solide.
- Associez l'utilisateur à la base en lui accordant les privilèges.
- Reportez les identifiants dans Hodifly → Variables d'environnement.
Un point à connaître : cPanel préfixe automatiquement les noms avec votre compte. Une base nommée app devient moncompte_app, un utilisateur api devient moncompte_api. Utilisez des noms courts, et reportez les noms complets dans votre configuration.
Pour importer votre schéma et inspecter vos données, utilisez phpPgAdmin (PostgreSQL) ou phpMyAdmin (MySQL), depuis cPanel.
Vos variables d'environnement Hodifly sont stockées sur votre propre serveur, chiffrées au repos, et jamais transmises ailleurs.
Où stocker les fichiers envoyés par vos utilisateurs
C'est le point que l'on découvre souvent trop tard, une fois les fichiers perdus.
Hodifly republie votre site à chaque push, et une restauration rejoue une version antérieure. Le dossier publié est donc remplacé, pas modifié. Tout ce que votre application y aurait écrit disparaît au déploiement suivant. Le problème est sournois : en local, tout fonctionne ; en production, les fichiers s'évaporent au push d'après.
Les fichiers envoyés par vos utilisateurs sont des données, au même titre que votre base. Ils doivent vivre dans un emplacement persistant :
- Créez un dossier
filesà la racine de votre espace personnel :
/home/moncompte/files/(remplacez moncompte par le nom de votre compte cPanel). Cet emplacement est hors de la racine web, qui est /home/moncompte/public_html/, et hors du dossier publié par Hodifly. Il n'est donc jamais remplacé par un déploiement, ni accessible directement depuis Internet.
- Déclarez-le dans Hodifly → Variables d'environnement :
UPLOAD_DIR=/home/moncompte/files/- En base, ne stockez que le nom du fichier et son chemin relatif. Le contenu reste sur le disque.
- Servez les fichiers par une route applicative qui vérifie les droits, jamais par un lien direct.
- Ajoutez ce dossier au
.gitignore.
Et pour vos sauvegardes ? Ces fichiers étant sur votre hébergement, ils suivent la politique de sauvegarde de votre offre, comme le reste de votre compte.
Le test qui tranche : envoyez un fichier, faites un git push sans rapport, puis vérifiez qu'il est toujours là.
Déménager les données existantes
- Depuis Supabase, exportez le schéma et les données séparément (
pg_dump --schema-only, puispg_dump --data-only). - Supabase tourne sur une version de PostgreSQL plus récente que la 13, et
pg_dumpest conçu pour aller vers l'avant, pas vers l'arrière. Faites donc adapter le schéma par votre IA (étape 3 du prompt) avant de l'exécuter. - Importez ensuite les données seules. C'est la partie qui se transporte le mieux : mêmes types, mêmes formats, aucune conversion.
- Si un import résiste, repliez-vous sur un export CSV par table depuis le tableau de bord Supabase.
- Vérifiez les compteurs de lignes table par table avant de basculer.
Les erreurs que fait l'IA
- Elle annonce la victoire trop tôt. Redemandez : « Reprends l'inventaire de l'étape 1 et coche ce qui est réellement traité. Que reste-t-il ? »
- Elle oublie des vérifications d'autorisation. C'est le risque principal. Exigez le tableau route par route, puis testez : connectez-vous en tant qu'utilisateur A, tentez d'accéder à une donnée de l'utilisateur B.
- Elle filtre côté client plutôt que dans la requête. Une donnée envoyée au navigateur puis masquée à l'affichage reste une donnée envoyée. Le filtrage doit être dans le
WHERE. - Elle écrit les fichiers dans le dossier du projet. L'erreur la plus coûteuse : tout marche en local, les fichiers disparaissent au déploiement suivant.
- Elle laisse des identifiants en dur. Demandez : « Cherche tout secret ou mot de passe écrit en dur et déplace-le en variable d'environnement. »
- Elle utilise de la syntaxe trop récente pour PostgreSQL 13.
Vérifier avant de mettre en ligne
- Aucune occurrence de
supabasene subsiste dans le code (grep -ri supabase .). - Un utilisateur connecté ne peut accéder qu'à ses propres données. Testez-le réellement.
- Toutes les routes sensibles refusent un utilisateur non connecté.
- Les mots de passe sont hachés, jamais stockés en clair.
- Les identifiants de base vivent uniquement dans les variables d'environnement.
- Les compteurs de lignes correspondent à ceux de Supabase.
- Un fichier envoyé survit à un redéploiement.
Et si je préfère MySQL ?
Nous supportons aussi MySQL/MariaDB, et c'est une option tout à fait légitime. C'est le moteur le plus répandu au monde : plus de documentation, plus d'exemples, et donc souvent mieux maîtrisé par les IA. Si votre assistant vous semble plus à l'aise dessus, ou si c'est ce que vous connaissez, partez dessus sans hésiter. Adaptez simplement le prompt ci-dessus (base MySQL/MariaDB, pilote mysql2/promise).
La contrepartie est honnête : vous quittez PostgreSQL, donc ça demande un peu plus de temps. Il faut convertir le schéma, remapper les types (uuid, jsonb, timestamptz et les tableaux n'ont pas d'équivalent direct), réécrire les requêtes, et importer les données par CSV.
Comment choisir ? Pour le moins de modifications, restez sur PostgreSQL : votre schéma Supabase fonctionne tel quel. Pour un moteur plus courant et plus familier à votre IA comme à votre développeur, MySQL fait très bien l'affaire, avec une étape de conversion en plus.
Mis à jour le : 16/07/2026
Merci !