Ton code est identique que tu sois sur ton laptop ou en production. Mais la base de données, les clefs d'API, les URLs de service - tout ça change selon l'endroit où tourne le code. Les variables d'environnement sont le mécanisme qui sépare la configuration du code. Sans elles, tu te retrouves à patcher du code à chaque déploiement, ou pire, à committer des secrets dans Git.
Le principe 12 Factor App
La référence sur le sujet, c'est le 12 Factor App (2011, Heroku). Un de ses principes fondateurs : stocker la config dans l'environnement, pas dans le code.
L'idée en une phrase : ton code est identique en dev, preview et prod. Seule la configuration change. Si tu dois modifier du code pour déployer vers une cible différente, c'est un signe que quelque chose est dans le mauvais endroit.
Les trois environnements modernes
Toute application moderne tourne dans trois contextes distincts. Il ne faut pas les mélanger.
Les trois environnements et leurs bases de données.
Development : ton laptop. La base de données est locale ou sur un projet Supabase de test. Pas d'utilisateurs réels. Tu peux casser ce que tu veux.
Preview (Vercel) : chaque branche ou pull request génère une URL unique. C'est l'environnement de validation avant la mise en prod. Il pointe souvent vers une base de données clone, ou vers la production en lecture seule. Les équipes l'utilisent pour tester sans risquer les données réelles.
Production : le truc qui sert tes vrais utilisateurs. On y touche le moins souvent possible. Chaque déploiement en prod est précédé d'un passage en preview.
Les variables d'environnement
Une variable d'environnement est une valeur lue par ton programme au démarrage, depuis le contexte dans lequel il tourne. Exemples courants :
DATABASE_URL- l'adresse de connexion à la base de données (différente en dev, preview et prod)STRIPE_SECRET_KEY- ta clef secrète Stripe (une clef de test en dev, la vraie en prod)NEXT_PUBLIC_API_URL- l'URL publique de ton API (exposée au navigateur)
En local, elles vivent dans des fichiers .env. En production, elles sont injectées par la plateforme (Vercel, Railway, Render) avant de lancer ton serveur.
.env, .env.local, Vercel Settings : lequel pour quoi
| Fichier / Endroit | Commité dans Git ? | Usage |
|---|---|---|
.env | oui | Valeurs par défaut non-secrètes. Partagées avec l'équipe via Git. Jamais de secrets ici. |
.env.local | non (gitignored) | Tes secrets de dev : vraies clefs API, mots de passe base locale. Un fichier par développeur. |
.env.production | non (selon projet) | Valeurs de prod locales, rarement utile en dehors de scripts de migration. |
| Vercel > Settings > Env Vars | jamais en Git | Valeurs preview et prod, chiffrées au repos. La bonne façon de gérer les secrets en production. |
La règle simple : si c'est un secret, ça ne va jamais dans un fichier commité. Ton .gitignore doit contenir .env.local et tout fichier .env.*.local.
Pourquoi pas dans le code
Trois raisons concrètes de ne jamais écrire une valeur secrète directement dans le code source :
Exposé publiquement. Si tu commites ta clef Stripe dans GitHub, elle est publique même sur un repo privé dans certains cas - et l'historique Git est permanent. Un git rm ne suffit pas : l'historique garde la trace. La seule vraie réparation c'est la rotation (révoquer la clef, en générer une nouvelle). C'est une corvée.
Couplage au provider. Si tu changes de fournisseur de paiement (Stripe vers Paddle), avec des secrets dans le code tu dois modifier le code. Avec des variables d'env, tu changes juste la valeur dans Vercel Settings, sans toucher au code source.
Un code, trois configs. Si dev et prod n'ont pas la même URL de base de données, et que c'est dans le code, tu as deux branches à maintenir. Avec des variables d'env, un seul code, trois configs injectées par la plateforme.
NEXT_PUBLIC_ et les prefixes framework
Les frameworks modernes (Next.js, Vite, Remix) ont une convention importante : seules les variables avec un préfixe spécial sont exposées au navigateur. Tout le reste reste strictement côté serveur.
NEXT_PUBLIC_SITE_URL=https://monsite.com- visible dans le bundle JS livré au navigateurDATABASE_URL=...- accessible uniquement côté serveur (API routes, Server Components)STRIPE_SECRET_KEY=...- accessible uniquement côté serveur
Si tu commites un secret par accident
Ça arrive. Voici quoi faire dans l'ordre, sans panique :
- Révoquer immédiatement. Va sur le dashboard du service concerné (Stripe, Supabase, OpenAI) et invalide la clef. Fais-le avant même de toucher à Git. Le mal est déjà fait si le repo est public, agir vite limite l'exposition.
- Générer une nouvelle clef. Crée un remplacement, note-la dans ton gestionnaire de secrets (1Password, Bitwarden) et injecte-la dans Vercel Settings.
- Ne pas juste faire
git rm. L'historique Git est permanent. Ungit rmretire le fichier du prochain commit mais l'historique reste consultable. Si le repo est public et qu'un bot a déjà scanné (GitHub scanne en quelques secondes), la rotation est la seule vraie réponse. - Purger l'historique si nécessaire. Pour un repo privé non exposé,
git filter-repopeut réécrire l'historique. C'est une opération destructive qui demande de forcer-pusher - à faire en accord avec ton équipe.
GitHub active le secret scanning par défaut sur tous les repos publics. Il te notifie automatiquement si un token connu (Stripe, AWS, GitHub...) est détecté dans un push. Sur les repos privés, c'est disponible selon le plan.
Fuentes
Relacionado
Concepts-ponts
Le meme concept (cles secretes, URLs, flags) gere a quatre niveaux : le concept fullstack, ton shell local, ta plateforme de deploiement, ta base de donnees managee.