Configuration de l'environnement de déploiement
Collecter, borner et vérifier les variables d'environnement nécessaires au déploiement.
Cette page est le guide opérateur des variables d'environnement de déploiement. Utilisez-la lors de la création d'un projet Vercel, de la restauration d'un environnement production, de la vérification d'une prévisualisation avec le même câblage fournisseur que la production, ou de la préparation du runtime Docker auto-hébergé.
Règles
- Ne commitez jamais de secrets dans
.env,.env.productionou un fichier suivi. - Stockez les secrets Vercel production et preview dans les variables d'environnement du projet Vercel.
- Stockez les secrets production auto-hébergés dans le magasin de secrets de
l'orchestrateur. Pour la base Compose, utilisez un fichier non suivi
.env.self-hostcopié depuis.env.self-host.example. - Stockez les secrets locaux dans
.env.localou dans un.env.localrécupéré avecvercel env pull. - Gardez les valeurs
NEXT_PUBLIC_*non secrètes: elles sont exposées au bundle navigateur. - Préférez les réglages admin/runtime pour les non-secrets opérationnels lorsque
le dashboard les supporte. Par exemple, les réglages dépôt GitHub pour l'accès
au code se gèrent depuis
/dashboard/admin/billing-settings; les variables d'environnement ne sont que des replis.
Workflow Vercel
Liez le checkout local au bon projet Vercel avant de récupérer ou pousser des variables:
vercel link --yes --project <project-name-or-id> --scope <team-or-user>Ajoutez les secrets depuis le dashboard Vercel ou la CLI. Bornez les valeurs production-only à Production, les valeurs preview à Preview et les valeurs de développement local à Development:
echo "<secret-value>" | vercel env add VARIABLE_NAME production
echo "<secret-value>" | vercel env add VARIABLE_NAME preview
echo "<secret-value>" | vercel env add VARIABLE_NAME developmentAprès ajout ou modification de variables, redéployez l'environnement Vercel concerné. Les déploiements existants ne reçoivent pas automatiquement les nouvelles valeurs.
Récupérez une copie locale pour le développement:
vercel env pull .env.local --environment=development --yesRécupérez les valeurs production uniquement pour un audit explicite sur une machine de confiance:
vercel env pull .env.production.local --environment=production --yesVérifiez que chaque clé listée dans .env.example est présente localement:
while IFS='=' read -r key _; do
[[ -z "$key" || "$key" == \#* ]] && continue
grep -q "^${key}=" .env.local || echo "Missing in .env.local: $key"
done < .env.exampleWorkflow Docker Auto-Hébergé
La base portable utilise Docker Compose avec Postgres, MinIO/S3, le serveur app Next.js standalone, un worker Page AI et Caddy:
cp .env.self-host.example .env.self-host
docker compose --env-file .env.self-host -f docker-compose.self-host.yml --profile setup run --rm migrate
docker compose --env-file .env.self-host -f docker-compose.self-host.yml up --buildLes builds Docker utilisent NEXT_BUILD_WORKERS=1 par défaut pour une
génération statique Next.js stable sur de petits hôtes. Sur une machine plus
large, vous pouvez l'augmenter, par exemple:
NEXT_BUILD_WORKERS=2 docker compose --env-file .env.self-host -f docker-compose.self-host.yml up --buildLes builds Docker auto-hébergés fixent aussi
NEXT_STATIC_PAGE_GENERATION_TIMEOUT=180 par défaut. Cela donne aux hôtes lents
assez de temps pour pré-rendre de grosses pages docs sans déclencher le timeout
Next.js de 60 secondes. Baissez-le sur des builders CI rapides ou augmentez-le
uniquement si les logs montrent des pages statiques légitimes en timeout.
Les builds Docker auto-hébergés rendent les pages Fumadocs dynamiquement au lieu de prégénérer toute la documentation pendant la construction d'image. Cela évite aux petits hôtes Coolify ou Docker de dépenser l'essentiel du budget de déploiement sur les docs tout en les servant normalement au runtime.
Les fichiers Compose taguent les cibles app et worker avec YAYAW_APP_IMAGE et
YAYAW_WORKER_IMAGE. Gardez le même tag worker pour les services migrate et
worker afin que Docker ou Coolify puisse réutiliser la cible worker au lieu de
la construire deux fois.
Le déploiement Coolify managé par Yayaw utilise des images précompilées plutôt
qu'un build sur la VM production. GitHub Actions construit les images app et
worker sur des runners ubuntu-24.04-arm pour la plateforme linux/arm64 du
Mac mini, pousse les images vers GHCR, les fait tirer par le serveur Coolify via
le runner auto-hébergé privé, met à jour YAYAW_APP_IMAGE et
YAYAW_WORKER_IMAGE, puis demande à Coolify de lancer le déploiement Compose.
Cela conserve la release automatique sur main, déplace le build coûteux hors
de la VM Mac mini et évite le quota de stockage artifacts GitHub Actions.
Coolify doit stocker ces tags d'image comme valeurs build-time et runtime,
parce que Docker Compose interpole les entrées image: pendant la préparation
du déploiement.
Le profil setup lance la synchronisation de schéma non interactive
drizzle-kit push --force, le seed, puis
bun run dynamic-data:repair-deployed-storage. Relancez-le avant le démarrage
d'une base auto-hébergée fraîche et après les changements de schéma. Ce n'est
pas un runner de migrations Drizzle versionnées; l'étape dynamic-data couvre les
tables natives MCP ydm_* qui ne font volontairement pas partie du schéma
Drizzle statique.
Ne commitez pas .env.self-host. En production, déplacez les mêmes valeurs dans
le secret manager de l'hôte cible ou l'environnement Compose. Générez
BETTER_AUTH_SECRET avant le premier build Docker, par exemple avec
openssl rand -hex 32; le Dockerfile échoue immédiatement lorsqu'il est vide.
Le flag --env-file rend les mêmes valeurs publiques disponibles aux arguments
de build Docker. BETTER_AUTH_SECRET est aussi passé à next build pour éviter
que l'évaluation des routes Better Auth ne retombe sur un secret de
développement pendant la construction d'image. Reconstruisez l'image quand les
valeurs NEXT_PUBLIC_* changent.
Migration Rolling Coolify
docker-compose.coolify.yml reste l'unité de déploiement historique pendant la
validation du chemin rolling. Il remplace ensemble migrate, l'app, le worker et
Caddy; il ne peut donc pas fournir une release sans interruption. Ne repointez pas
les workflows automatiques development ou production vers les nouvelles
ressources avant que le workflow rolling manuel ait validé le rollback.
Migrez d'abord development:
- Sauvegardez Postgres et MinIO. Conservez l'UUID de la ressource Compose
Coolify existante afin de réutiliser ses volumes
postgres_dataetminio_data. - Activez Connect to Predefined Network sur la ressource d'infrastructure
existante. Notez les hostnames résolus
postgres-<resource-uuid>etminio-<resource-uuid>. - Créez une Application Coolify Docker Image depuis l'image immuable
ghcr.io/<owner>/yayaw-app:<sha>. Exposez le port conteneur3000, sans mapping de port hôte, sans nom de conteneur, et connectez-la au réseau prédéfini. Configurez les identifiants du registre GHCR dans Coolify si le package est privé; les identifiants de pull temporaires du workflow ne configurent pas le registre de l'Application. - Copiez l'environnement runtime de l'app vers cette Application. Remplacez les
hôtes de
DATABASE_URLetS3_ENDPOINTpar ceux de l'infrastructure. Utilisez d'abord un domaine development temporaire. - Gardez les healthchecks actifs. L'image Docker vérifie
/api/ready, qui ne renvoie200que si Postgres répond et si le SHA immuable de l'image correspond au SHA demandé./api/healthreste limité à la liveness. - Configurez une période de grâce d'arrêt de 20 à 30 secondes dans Coolify.
Next.js traite
SIGTERMet termine les requêtes en vol pendant cette fenêtre. - Déplacez le worker Page AI vers une ressource séparée basée sur
ghcr.io/<owner>/yayaw-worker:<sha>. Il ne doit pas rester dans la stack d'infrastructure qui survit aux releases web. - Sur un clone de la base, vérifiez que
drizzle.__drizzle_migrationsreprésente fidèlement les migrations SQL déjà appliquées. Le runner rolling refuse de migrer une base non vide dont le journal est absent ou vide. Ne fabriquez pas de baseline directement en production. - Ajoutez
COOLIFY_ROLLING_APPLICATION_UUIDetNEXT_SERVER_ACTIONS_ENCRYPTION_KEYà l'environnement GitHubdevelopment. Générez la seconde valeur une fois avecopenssl rand -base64 32et conservez la même valeur entre les builds. - Lancez
Coolify Rolling Deploypourdevelopment. Il tire les deux images avec retry, exécute la préparation de schéma Better Auth, les migrations Drizzle versionnées, le seed et la réparation dynamic-data pendant que l'ancienne app sert encore, puis met à jour l'Application Docker Image. Un échec de déploiement ou du smoke public sur le SHA restaure automatiquement le tag précédent; les changements de base ne sont pas annulés. - Après le succès du rollout web, promouvez la ressource worker séparée vers le
tag immuable
yayaw-worker:<sha>émis par le workflow. Gardez l'ancien worker actif jusqu'à ce que le processus de remplacement soit sain; toutes les évolutions du worker doivent rester compatibles avec le schéma migré pendant cette bascule. - Validez volontairement une mauvaise image ou un échec de readiness et confirmez que l'ancien SHA public reste disponible. Répétez ensuite la procédure en production.
Une fois la nouvelle app et le worker sains, changez la ressource Compose
existante vers docker-compose.coolify.infrastructure.yml. Définissez
MINIO_MEDIA_FQDN sur l'origine publique suivie de /media et
MINIO_ORGANIZATION_LOGOS_FQDN sur la même origine suivie de
/organization-logos; Coolify crée les routeurs de chemin stables vers MinIO.
Retirez le domaine de l'ancien Caddy et assignez le domaine racine à l'Application
Docker Image pendant la même bascule. Le fichier d'infrastructure n'expose aucun
port hôte et ne doit pas être redéployé lors des releases applicatives normales.
Chaque migration de ce chemin doit suivre expand/contract: ajoutez d'abord un schéma compatible, déployez du code tolérant les deux versions, puis supprimez l'ancien schéma seulement après la disparition de tous les anciens conteneurs et workers. Le rollback automatique d'image ne peut pas annuler une migration de base destructive.
Environnements CI Coolify
Les déploiements Coolify auto-hébergés sont pilotés depuis GitHub Actions:
- les pull requests déploient vers une application Coolify
developmentpartagée après réussite de la CI - les pushes vers
maindéploient vers l'application Coolifyproductionaprès réussite de la CI
Configurez deux environnements GitHub avec des UUID d'applications Coolify séparés:
| Environnement GitHub | Secret ou variable requis | Usage |
|---|---|---|
development | COOLIFY_URL | Origine API Coolify. |
development | COOLIFY_API_TOKEN | Token autorisé à mettre à jour et déployer l'app development. |
development | COOLIFY_APPLICATION_UUID | UUID de l'app development partagée. |
development | COOLIFY_ROLLING_APPLICATION_UUID | UUID de l'Application Docker Image utilisée par le workflow manuel de validation rolling. |
development | DEVELOPMENT_BASIC_AUTH_USERNAME | Username HTTP Basic de l'app development protégée. |
development | DEVELOPMENT_BASIC_AUTH_PASSWORD | Password HTTP Basic de l'app development protégée. |
development | variable DEVELOPMENT_URL | URL optionnelle de smoke test. Défaut https://dev.yayaw.app; utilisez une URL joignable par le runner interne si le DNS public n'est pas encore routé. |
production | COOLIFY_URL | Origine API Coolify. |
production | COOLIFY_API_TOKEN | Token autorisé à déployer l'app production. |
production | COOLIFY_APPLICATION_UUID | UUID de l'app production. |
production | COOLIFY_ROLLING_APPLICATION_UUID | UUID de l'Application Docker Image production après validation en development. |
development, production | BETTER_AUTH_SECRET | Secret build-time requis par le build de l'image Docker Next.js. |
development, production | DATABASE_URL | URL de base build-time pour l'évaluation des routes serveur. |
development | POSTGRES_ROTATION_DATABASE_URL | URL candidate temporaire utilisée seulement par la rotation des identifiants et la synchronisation runtime. Gardez DATABASE_URL sur l'identifiant fonctionnel courant jusqu'au succès du premier déploiement après rotation. |
development, production | secrets build NEXT_PUBLIC_* | Valeurs publiques intégrées au bundle client Docker. |
development, production | NEXT_SERVER_ACTIONS_ENCRYPTION_KEY | Clé AES base64 stable intégrée pendant next build afin que les instances superposées acceptent les mêmes payloads Server Actions. |
development, production | variable NEXT_BUILD_WORKERS | Nombre de workers de build. Défaut 1 pour stabiliser les builds Docker auto-hébergés. |
development, production | variable NEXT_STATIC_PAGE_GENERATION_TIMEOUT | Timeout de génération statique. Défaut 180. |
development, production | variable COOLIFY_SERVER_SSH_HOST | Override optionnel pour charger les images sur la VM Coolify. Défaut 127.0.0.1 depuis le runner Mac mini. |
development, production | variable COOLIFY_SERVER_SSH_PORT | Port SSH optionnel. Défaut 2222. |
development, production | variable COOLIFY_SERVER_SSH_USER | Utilisateur SSH optionnel. Défaut yannis. |
development, production | variable COOLIFY_SERVER_SSH_KEY_PATH ou secret COOLIFY_SERVER_SSH_KEY | Clé SSH optionnelle. Le runner Mac mini utilise par défaut /Users/yannis/.ssh/coolify_vm_ed25519. |
development, production | variable COOLIFY_SERVER_KNOWN_HOSTS_PATH | Known-hosts optionnel. Défaut /Users/yannis/.ssh/known_hosts_coolify. |
Le préflight de release CMS synchronise aussi le contrat base, stockage privé, preview signé, personnalisation et maintenance worker vers l'app et le worker Coolify. Configurez ces secrets d'environnement GitHub :
S3_ACCESS_KEY_ID,S3_ENDPOINTetS3_SECRET_ACCESS_KEYCMS_PREVIEW_SIGNING_SECRET,CMS_PERSONALIZATION_RATE_LIMIT_SECRETetCMS_PERSONALIZATION_FORM_CONTEXT_SECRET, chacun d'au moins 32 caractères ; gardez le secret de contexte de formulaire dédiéSTORAGE_TRANSFER_SIGNING_SECREToptionnel lorsque les tokens de transfert stockage ne doivent pas partager le secret de signature des previewsDATABASE_URLdans les deux environnementsMINIO_ROOT_PASSWORD,POSTGRES_PASSWORDet le temporairePOSTGRES_ROTATION_DATABASE_URLetPOSTGRES_ROTATION_PREVIOUS_PASSWORDendevelopment
Configurez STORAGE_PROVIDER=s3, STORAGE_MEDIA_BUCKET=media,
STORAGE_MEDIA_STAGING_BUCKET=media-staging,
STORAGE_CMS_FORM_BUCKET=cms-form-submissions,
CMS_PERSONALIZATION_CLIENT_IP_HEADER=x-real-ip,
PAGE_AI_WORKER_MAINTENANCE_MS=60000, S3_REGION=us-east-1 et
S3_FORCE_PATH_STYLE=true comme variables d'environnement GitHub.
STORAGE_PUBLIC_BASE_URL est optionnel si NEXT_PUBLIC_BASE_URL désigne déjà
la même origine publique. S3_SIGNED_PUBLIC_ENDPOINT est une variable
optionnelle pour une origine d'upload direct explicitement configurée. Ne
persistez pas de phase de rollout comme variable GitHub : les workflows de
déploiement et de rollout dérivent et valident la phase sûre reader, freeze
ou exact à partir de la flotte active avant de synchroniser les flags runtime
correspondants.
Préparez une seule fois les identifiants development, hors déploiement :
database_password="$(openssl rand -hex 32)"
storage_password="$(openssl rand -hex 32)"
database_fingerprint="$(
printf '%s' "$database_password" | shasum -a 256 | awk '{print $1}'
)"
rotation_database_url="$(
printf 'postgresql://yayaw:%s@postgres:5432/yayaw' "$database_password"
)"
printf '%s' "$database_password" | gh secret set POSTGRES_PASSWORD --env development
printf '%s' "$rotation_database_url" \
| gh secret set POSTGRES_ROTATION_DATABASE_URL --env development
printf '%s' "$storage_password" | gh secret set MINIO_ROOT_PASSWORD --env development
printf '%s' "$storage_password" | gh secret set S3_SECRET_ACCESS_KEY --env development
gh variable set CMS_DATABASE_CREDENTIALS_FINGERPRINT \
--env development \
--body "$database_fingerprint"Le mot de passe de base est volontairement une valeur hexadécimale brute de
32 octets afin de ne pas nécessiter d'encodage URL. Pour un volume development
existant, laissez DATABASE_URL sur l'identifiant fonctionnel courant pendant
le build des images de PR. Le workflow transmet cette URL active à l'étape de
rotation, qui en extrait le mot de passe brut en mémoire sans l'exposer dans les
logs. Définissez POSTGRES_ROTATION_PREVIOUS_PASSWORD explicitement seulement
si l'URL active emploie un encodage de mot de passe non pris en charge. Le job
de déploiement n'utilise POSTGRES_ROTATION_DATABASE_URL qu'une fois les
images disponibles : il teste l'identifiant candidat via l'alias privé
yayaw-postgres-development; si nécessaire, il utilise un fichier env distant
en permission 0600 pour modifier le rôle, reteste le nouvel identifiant puis
synchronise l'URL candidate vers Coolify. Il s'arrête avant toute mutation des
env Coolify si aucun identifiant ne fonctionne.
Après le premier déploiement development réussi avec l'identifiant tourné, promouvez l'URL candidate conservée puis supprimez le secret candidat temporaire :
printf '%s' "$rotation_database_url" \
| gh secret set DATABASE_URL --env development
gh secret delete POSTGRES_ROTATION_DATABASE_URL --env developmentSupprimez également POSTGRES_ROTATION_PREVIOUS_PASSWORD si le fallback
explicite a été configuré.
Pour un volume neuf sans application en cours d'exécution, définissez aussi
DATABASE_URL avec la même URL candidate avant le premier build. Ne remplacez
jamais seulement DATABASE_URL et POSTGRES_PASSWORD sur un volume existant
avant la fin du workflow de rotation.
Les workflows ont aussi besoin des permissions packages du dépôt: les jobs de
build utilisent packages: write pour publier ghcr.io/<owner>/yayaw-app:<sha>
et ghcr.io/<owner>/yayaw-worker:<sha>, tandis que les jobs de déploiement
Coolify utilisent packages: read pour tirer ces images depuis le runner
auto-hébergé.
L'app development partagée est volontairement mutable: chaque pull request force
la branche technique coolify/development du dépôt vers le SHA de tête de la
PR, met à jour la git_branch de l'app dans Coolify vers cette branche stable
et déploie sans forcer de rebuild. Cela évite les échecs lorsqu'une branche PR
mergée est supprimée avant que Coolify clone le dépôt, tout en laissant BuildKit
réutiliser les layers entre development et production. GitHub Actions sérialise
les déploiements development avec le groupe de concurrence
development-coolify-deploy, ce qui garde l'environnement prévisible pendant
que les nouvelles runs attendent la fin du déploiement en cours.
Gardez l'origine development privée. Préférez un hostname Tailscale-only ou
activez HTTP Basic au niveau de l'app Coolify tout en renvoyant
X-Robots-Tag: noindex, nofollow, noarchive. Le smoke test part du runner
auto-hébergé avec les secrets Basic Auth development; ce runner doit donc
atteindre l'URL protégée.
Socle Production
Ces valeurs sont requises avant qu'un déploiement production puisse servir l'app correctement:
| Variable | Où la récupérer | Indication |
|---|---|---|
NODE_ENV | Runtime Vercel | Généralement défini par la plateforme. Ne surchargez pas sauf pour déboguer un runtime non Vercel. |
NEXT_PUBLIC_BASE_URL | Domaines Vercel | Définir sur l'origine publique canonique, par exemple https://yayaw.app. |
BETTER_AUTH_SECRET | Secret manager | Valeur longue, aléatoire et stable pour cookies et tokens Better Auth. |
DATABASE_URL | Fournisseur Postgres | Utiliser la connection string poolée production lorsque le fournisseur en expose une. |
BETTER_AUTH_TRUSTED_ORIGINS | Domaines de déploiement | Ajouter les origines preview/local en liste séparée par virgules. L'hôte canonique et sa variante www sont dérivés de NEXT_PUBLIC_BASE_URL. |
CADDY_HOST_PORT | Env application Coolify | Port hôte du conteneur Caddy Compose. Défaut production 3080; utilisez par exemple 3081 pour l'app development partagée. |
MINIO_API_HOST_PORT | Env application Coolify | Port hôte de l'API S3-compatible MinIO. Défaut production 9000; utilisez par exemple 9100 en development. |
MINIO_CONSOLE_HOST_PORT | Env application Coolify | Port hôte de la console MinIO. Défaut production 9001; utilisez par exemple 9101 en development. |
VERCEL_URL | Runtime Vercel | Défini automatiquement par Vercel. Garder hors du .env local sauf reproduction plateforme. |
Réglages optionnels de pool base:
| Variable | Quand la définir |
|---|---|
DATABASE_POOL_MAX | Augmenter seulement si le fournisseur DB supporte plus de connexions par runtime. |
DATABASE_IDLE_TIMEOUT_SECONDS | Ajuster le cycle de vie idle pour les déploiements non-serverless. |
DATABASE_MAX_LIFETIME_SECONDS | Ajuster la rotation de connexions pour les runtimes long-lived. |
DATABASE_CONNECT_TIMEOUT_SECONDS | Ajuster le démarrage sur réseaux privés lents. |
DATABASE_STATEMENT_TIMEOUT_SECONDS | Ajouter un timeout serveur par statement pour chaque connexion DB. |
DATABASE_PREPARE_STATEMENTS | Garder false pour les connexions production pooler/serverless sauf support explicite du fournisseur. |
CMS_DASHBOARD_FULL_METRICS | Garder false sauf si la base est optimisée pour les agrégats complets de publication et activité CMS. |
Base De Données
DATABASE_URL est requis par le runtime applicatif, les scripts setup, les seeds
et les opérations Drizzle.
Pour le déploiement Coolify auto-hébergé, la synchronisation de schéma et les
seeds production tournent dans le service Compose migrate avant le démarrage
de l'app et du worker. Gardez le DATABASE_URL production dans Coolify ou le
secret store de l'orchestrateur afin que l'étape de setup résolve les noms de
services Docker internes comme postgres.
Pour les fournisseurs hébergés qui n'exécutent pas la pile Compose auto-hébergée, lancez l'opération de schéma Drizzle choisie depuis un runner capable d'atteindre la base production avant de promouvoir la nouvelle version.
Pour les fournisseurs Postgres hébergés:
- Créez la base production.
- Ouvrez le panneau des connection strings.
- Copiez la connection string poolée lorsqu'elle existe.
- Stockez-la comme
DATABASE_URLdans Vercel Production et Preview, ou dans le secret store auto-hébergé. - Utilisez une base de développement séparée pour Vercel Development,
.env.locallocal ou.env.self-host.
Si le fournisseur expose des URL directes et poolées, préférez l'URL poolée pour les fonctions Vercel. L'app utilise déjà un pool production conservateur de trois connexions par runtime afin d'éviter d'épuiser les limites serverless.
Hôte Canonique Et Auth
Définissez:
NEXT_PUBLIC_BASE_URL=https://yayaw.app
BETTER_AUTH_TRUSTED_ORIGINS=https://*.yayaw.app,https://*.vercel.appNEXT_PUBLIC_BASE_URL pilote les URL canoniques, l'URL de base Better Auth, les
métadonnées OAuth, les liens sitemap/robots et les URL absolues de ressources.
Ne définissez pas NEXT_PUBLIC_SITE_URL; l'application ne le lit pas. Ne
définissez pas BETTER_AUTH_URL pour les nouveaux déploiements; Better Auth
reçoit son URL de base depuis NEXT_PUBLIC_BASE_URL.
Le domaine de prévisualisation branch-backed est https://preview.yayaw.app et
suit la branche durable preview.
Les hôtes .eu retirés peuvent rester attachés uniquement comme redirections
Vercel 308 vers leurs remplaçants .app, comme yayaw.eu et www.yayaw.eu
vers yayaw.app. Ils ne doivent pas servir de trafic dashboard/auth ni figurer
dans BETTER_AUTH_TRUSTED_ORIGINS.
Stripe Billing
Stripe a trois secrets requis lorsque la facturation est activée:
| Variable | Où la récupérer | Notes |
|---|---|---|
STRIPE_SECRET_KEY | Stripe Dashboard, Developers, API keys | Utilisez sk_live_... en production et sk_test_... en staging/local. |
STRIPE_WEBHOOK_SECRET | Stripe Dashboard, Developers, Webhooks, signing secret endpoint abonnement | Utilisé par l'endpoint webhook Better Auth Stripe. |
STRIPE_ONE_TIME_WEBHOOK_SECRET | Stripe Dashboard, Developers, Webhooks, signing secret endpoint achat ponctuel | Utilisé par l'endpoint custom one-time checkout. |
Créez deux endpoints webhook Stripe pour la production:
https://yayaw.app/api/auth/stripe/webhook
https://yayaw.app/api/billing/stripe/webhookUtilisez le signing secret du premier endpoint pour STRIPE_WEBHOOK_SECRET et
celui du second pour STRIPE_ONE_TIME_WEBHOOK_SECRET. Ne réutilisez pas le
secret d'un endpoint pour l'autre.
L'endpoint abonnement doit recevoir les événements de checkout abonnement et de
cycle de vie billing. L'endpoint one-time a seulement besoin de
checkout.session.completed pour les achats lifetime.
Les prix des produits de facturation sont gérés depuis
/dashboard/admin/billing-products ou via le plan de contrôle MCP. Les Stripe
Price IDs sont stockés en base après synchronisation catalogue; ce ne sont pas
des secrets de déploiement.
Liens Livrables D'Accès Au Code
Ces valeurs sont des URL non secrètes optionnelles affichées sur
/dashboard/organization/code-access après un achat payant qui débloque l'accès
au code:
| Variable | Exemple | Quand l'utiliser |
|---|---|---|
BILLING_CODE_ACCESS_REPOSITORY_URL | https://github.com/Yayaw-eu/yayaw | Lien vers le dépôt privé après attribution de l'accès GitHub. |
BILLING_CODE_ACCESS_DOWNLOAD_URL | https://github.com/Yayaw-eu/yayaw/releases | Lien vers artifacts de release ou archives. |
BILLING_CODE_ACCESS_DOCUMENTATION_URL | https://docs.yayaw.app | Lien vers la documentation de setup ou d'usage. |
BILLING_CODE_ACCESS_SUPPORT_URL | mailto:support@yayaw.app | Lien support pour les problèmes d'accès. |
Laissez une valeur vide lorsque le livrable requiert un provisioning manuel.
GitHub Code Access
L'accès dépôt production doit utiliser une GitHub App, pas un personal access
token. L'app permet à Yayaw d'inviter les clients payants dans le dépôt
configuré avec l'accès lecture seule pull, sans stocker les identifiants
GitHub d'un utilisateur humain.
Créer La GitHub App
Créez l'app depuis le compte qui possède le dépôt privé:
GitHub organization -> Settings -> Developer settings -> GitHub Apps -> New GitHub AppValeurs recommandées:
| Champ | Valeur |
|---|---|
| GitHub App name | Yayaw Code Access |
| Homepage URL | URL de production, par exemple https://yayaw.app |
| Webhook | Désactivé sauf future fonctionnalité GitHub callbacks |
| Where can this GitHub App be installed | Only on this account |
Permissions de dépôt:
| Permission | Accès |
|---|---|
| Administration | Read and write |
| Metadata | Read-only, accordé automatiquement par GitHub |
Administration: Read and write est requis car Yayaw appelle l'API GitHub
collaborators pour inviter le username demandé dans le dépôt. L'app n'a pas
besoin de permission Contents pour le flux actuel: le client reçoit l'accès
dépôt normal via son propre compte GitHub.
Installer La GitHub App
Après création:
- Générez une clé privée depuis les réglages de l'app et téléchargez le
.pem. - Installez l'app sur le compte ou l'organisation propriétaire.
- Sélectionnez uniquement le dépôt auquel les clients payants doivent accéder.
- Copiez l'App ID depuis les réglages.
- Copiez l'installation ID depuis l'URL d'installation.
L'URL d'installation ressemble généralement à ceci pour une organisation:
https://github.com/organizations/Yayaw-eu/settings/installations/12345678Le segment numérique final est l'ID d'installation de la GitHub App.
Stocker Le Secret GitHub App
Stockez la clé privée dans l'environnement cible. Pour Vercel:
vercel env add BILLING_CODE_ACCESS_GITHUB_APP_PRIVATE_KEY production
vercel env add BILLING_CODE_ACCESS_GITHUB_APP_PRIVATE_KEY previewLe dashboard Vercel est l'endroit le plus sûr pour coller une valeur PEM
multiligne avec le fournisseur hébergé. Pour un .env.local ou fichier secret
auto-hébergé, collez la clé multiligne entre guillemets ou échappez les sauts de
ligne sur une ligne:
printf 'BILLING_CODE_ACCESS_GITHUB_APP_PRIVATE_KEY="%s"\n' "$(perl -0pe 's/\n/\\n/g' yayaw-code-access.pem)" >> .env.localLe runtime accepte les séquences \n échappées et les reconvertit en vrais
sauts de ligne avant de signer le JWT GitHub App. Si une plateforme aplatit le
PEM en une ligne avec des espaces entre header, body et footer, Yayaw le
normalise en PEM au runtime.
Configurer Les Valeurs Non Secrètes GitHub
Préférez l'UI admin pour les valeurs non secrètes:
/dashboard/admin/billing-settingsDéfinissez:
| Réglage admin | Valeur |
|---|---|
| Enabled | On |
| Repository | Yayaw-eu/yayaw ou le dépôt cible exact |
| GitHub App ID | App ID numérique depuis les réglages GitHub App |
| GitHub App installation ID | Installation ID numérique depuis l'URL d'installation |
Des replis d'environnement existent pour les déploiements qui ont besoin de config au démarrage:
BILLING_CODE_ACCESS_GITHUB_REPOSITORY=Yayaw-eu/yayaw
BILLING_CODE_ACCESS_GITHUB_APP_ID=123456
BILLING_CODE_ACCESS_GITHUB_APP_INSTALLATION_ID=12345678
BILLING_CODE_ACCESS_GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"Repli Token Local Ou Staging
Utilisez BILLING_CODE_ACCESS_GITHUB_TOKEN uniquement pour les environnements
locaux ou staging sans GitHub App:
BILLING_CODE_ACCESS_GITHUB_REPOSITORY=Yayaw-eu/yayaw
BILLING_CODE_ACCESS_GITHUB_TOKEN=github_pat_...Le propriétaire du token doit pouvoir ajouter des collaborateurs au dépôt. Pour un token fine-grained, accordez l'accès au seul dépôt cible et incluez la permission d'administration de dépôt nécessaire aux invitations. N'utilisez pas ce repli en production sauf contournement d'incident avec plan de rotation.
RESEND_API_KEY active les e-mails transactionnels d'invitation, reset, magic
link et facturation.
Pour la récupérer:
- Vérifiez le domaine d'envoi dans Resend pour l'e-mail production.
- Créez une clé API server-side dans Resend.
- Stockez-la comme
RESEND_API_KEYdans l'environnement cible. - Envoyez un e-mail de test depuis la surface admin des e-mails transactionnels après déploiement.
Définissez EMAIL_SENDER sur un expéditeur vérifié du domaine Resend, par
exemple team@yayaw.app. Définissez EMAIL_SUPPORT sur l'adresse support
affichée dans les modèles et EMAIL_USERNAME sur le nom affiché. Ces variables
sont des défauts bootstrap et replis; après la première connexion admin, Admin >
Site Settings > Email est prioritaire au runtime.
L'absence de RESEND_API_KEY ne casse pas le traitement des webhooks de
facturation, mais ignore les e-mails transactionnels.
Fournisseurs OAuth
Ces valeurs sont optionnelles et requises uniquement lorsque le fournisseur correspondant est activé:
| Fournisseur | Variables | Où les récupérer |
|---|---|---|
| GitHub OAuth | GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET | Réglages GitHub OAuth App. Distinct de la GitHub App d'accès au code. |
| Google OAuth | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | Client OAuth Google Cloud Console. |
| Facebook OAuth | FACEBOOK_CLIENT_ID, FACEBOOK_CLIENT_SECRET | Réglages Meta developer app. |
Utilisez l'origine production de NEXT_PUBLIC_BASE_URL lors de la configuration
des redirect URIs OAuth.
Object Storage
Le stockage média est optionnel jusqu'à l'utilisation d'upload, miniatures,
logos ou génération d'images. Définissez STORAGE_PROVIDER=s3 pour MinIO, S3,
R2 ou un autre fournisseur compatible S3.
Variables communes:
| Variable | Où la récupérer |
|---|---|
STORAGE_PROVIDER | Définir sur s3. |
STORAGE_MEDIA_BUCKET | Nom du bucket des ressources média. Défaut media. |
STORAGE_MEDIA_STAGING_BUCKET | Bucket privé des téléversements directs en staging. Le self-host fourni utilise media-staging. |
STORAGE_CMS_FORM_BUCKET | Bucket privé durable des pièces jointes client. Le self-host fourni utilise cms-form-submissions. |
STORAGE_PUBLIC_BASE_URL | Origine publique des objets pour stockage compatible S3, servant /<bucket>/<key>. Utilisez l'origine app ou CDN seulement si ces préfixes de bucket sont routés vers le stockage objet. |
STORAGE_TRANSFER_SIGNING_SECRET | Secret dédié facultatif des grants privés same-origin opaques. Il se replie sur le secret de preview ou d'auth et doit fournir au moins 32 caractères en production. |
CMS_PERSONALIZATION_FORM_CONTEXT_SECRET | Secret dédié obligatoire pour la provenance éphémère des formulaires CMS publics. Générez au moins 32 caractères aléatoires et ne l'exposez jamais au navigateur ou au contenu CMS. |
S3_SIGNED_PUBLIC_ENDPOINT | Origine d'API S3 publique explicite et facultative pour les uploads signés directs quand l'hébergeur app ne supporte pas la limite CMS de 250 Mo. Ne jamais renseigner l'endpoint Docker interne. |
Pour un stockage S3 same-origin ou derrière CDN, proxifiez chaque préfixe de
bucket public vers le stockage objet avant le repli app. Les buckets publics
intégrés sont /media/* pour les médias téléversés et
/organization-logos/* pour les logos d'organisation. Si
STORAGE_PUBLIC_BASE_URL pointe directement vers une origine de stockage objet
dédiée, cette origine doit servir les mêmes chemins /<bucket>/<key>.
Créez les buckets de staging et de formulaires avant d'activer leurs écritures
et ne leur accordez aucun accès anonyme. Limitez le nettoyage par cycle de vie
du fournisseur au bucket ou préfixe de staging ; le worker Page AI pilote le
ledger de rétention à 180 jours des photos de formulaires et reprend les
suppressions interrompues. Définissez
CMS_PERSONALIZATION_CLIENT_IP_HEADER=x-real-ip avec le Caddy fourni, qui
écrase ce header, ou utilisez un autre header mono-valeur possédé par le proxy
seulement après avoir vérifié que l'ingress retire les valeurs client. Gardez
le worker actif avec PAGE_AI_QUEUE_DRIVER=db-worker en self-host.
Les transferts privés utilisent par défaut un grant applicatif same-origin
opaque, donc S3_ENDPOINT peut rester privé. Sur une plateforme dont la limite
de corps entrant est plus faible, définissez S3_SIGNED_PUBLIC_ENDPOINT sur
une origine d'API S3 HTTPS publique et sûre ; seuls les uploads deviennent des
PUT directs conditionnels, tandis que les téléchargements privés restent
derrière le proxy applicatif. Autorisez l'origine app, PUT, Content-Type,
Content-Length et If-None-Match dans la politique CORS de ce bucket. Les
octets de staging promus restent un tombstone sans écrasement pendant
l'expiration du grant et une stabilisation de 24 heures. Le reaper répète la
suppression et n'enregistre le nettoyage qu'après son DELETE final.
Activez les écritures de prototypes exacts dans cet ordre :
- Déployez le reader compatible avec
CMS_LEGACY_PROTOTYPE_WRITES_ENABLED=trueetCMS_PROTOTYPE_RUNTIME_V2_WRITES_ENABLED=false. - Vous pouvez lancer le workflow manuel
CMS Prototype Runtime Rolloutavecreaderet le SHA complet déjà déployé pour prouver la flotte reader. - Lancez ensuite ce workflow de confiance avec
exact. Il vérifie ou crée les buckets privés, synchronisefreeze, redéploie chaque ressource app/worker typée sur le SHA complet demandé et enregistre UUID de ressource, UUID de déploiement, digest, nom d'image, commit et jeu complet d'identifiants des conteneurs actifs dans un reçu durable version 1. Chaque conteneur actif doit prouver séparément le SHA et les valeurs legacy, v2, staging et opération de rollout attendues. - Après avoir revérifié qu'aucun déploiement plus récent n'a invalidé la
preuve de drain, le workflow fait passer le reçu de
issuedàactivating, synchronise legacyfalse, v2true, staged uploadstrueetCMS_PROTOTYPE_ROLLOUT_OPERATION_ID, puis redéploie et revérifie toutes les ressources. L'UUID de déploiement exact doit être nouveau ; UUID de ressource typée, digest, nom d'image et SHA complet restent identiques. - Le workflow vérifie l'état runtime final, réinspecte tous les conteneurs
exacts et transmet ce JSON frais directement à la consommation du reçu dans
la même étape shell. La consommation active le floor de base avant toute
écriture de gate. Seule l'opération consommée courante peut autoriser un
nouveau
prototypeGateV2.
Le workflow récupère toujours ses scripts de control plane depuis le main de
confiance courant ; le SHA de déploiement demandé est une preuve, jamais du code
de workflow exécutable. Si une exécution échoue après activating, le handler
d'échec peut seulement restaurer puis redéployer freeze. Reprenez
explicitement la même opération avec resume_operation_id et sa chaîne de
confirmation. La reprise exige le même environnement, dépôt, SHA de
déploiement, ressources typées et images, ainsi qu'une nouvelle tentative de
preuve live avec sa propre expiration. Le parent immuable conserve le SHA de
control plane qui l'a émis ; la tentative enfant reprise enregistre et valide
le SHA du main de confiance courant. Elle ne peut ni créer un reçu actif
concurrent ni revenir au reader.
Si la flotte a déjà avancé vers un SHA descendant strict alors qu'un ancien
reçu reste activating, ne reprenez pas l'ancien SHA et ne faites pas de
rollback. Lancez exact sur le descendant live avec
superseded_operation_id, superseded_deploy_sha et la confirmation
exact:<nouveau-sha>:supersede:<ancien-sha>:<ancien-operation-id>. Le workflow
prouve l'ascendance Git, redéploie et revérifie le descendant en freeze, puis
crée et active atomiquement le reçu de remplacement en liant l'ancien comme
terminal superseded. Le remplacement conserve les UUID de ressources typées
et prouve de nouveaux UUID de déploiement. La supersession ne fait jamais
avancer le runtime floor ; seule la consommation du remplacement le fait.
Le déploiement automatique normal de production reste réservé au reader. Le
déploiement de PR development partagé résout sa phase avec les scripts du
main de confiance : il garde bootstrap/reader en reader, ou préserve freeze
uniquement lorsque la configuration Coolify et chaque conteneur app/worker live
prouvent déjà freeze. Il ne peut initier freeze depuis reader ou exact et
n'active jamais exact.
Pour une évolution ultérieure du renderer en development :
- Lancez
CMS Prototype Runtime Rolloutavecfreezesur le SHA complet actuellement déployé. - Relancez le déploiement de la PR cible. Sous le lock partagé
development-coolify-deploy, il préserve freeze, déploie le nouveau SHA immuable de la PR, puis prouve que chaque conteneur app/worker live expose ce SHA et les flags freeze. Une ressource Compose development unique est prouvée comme un seul déploiement contenant les deux images attendues, avec un digest d'image agrégé stable et le jeu complet d'IDs de conteneurs app/worker. - Lancez
CMS Prototype Runtime Rolloutavecexactsur ce même SHA de PR. Il crée et consomme le reçu suivant, fait avancer l'opération courante et conserve l'opération initiale du floor.
Pour une évolution ultérieure du renderer en production :
- Lancez
CMS Prototype Runtime Rolloutavecfreezesur le SHA complet actuellement déployé. - Déclenchez manuellement
Coolify Rolling Deployavec le SHA complet cible appartenant à l'historique demainetfreeze-upgrade:<sha-complet>. Le workflow refuse de construire tant que l'état configuré et chaque conteneur app/worker live ne sont pas déjà gelés. Build, migration, rollout worker et rollout app restent ensuite sous le lock freeze partagé, puis l'étape finale prouve que le SHA et les images cibles sont toujours live en freeze. - Lancez
CMS Prototype Runtime Rolloutavecexactsur ce même SHA. Il crée et consomme le reçu suivant, fait avancer l'opération courante et conserve l'opération initiale du floor.
Le job normal ne simule jamais cette transition. Une fois le floor actif, n'utilisez jamais reader comme reset et ne réactivez jamais les writers legacy.
Les migrations 0047_cms_prototype_runtime_floor et
0049_cms_prototype_rollout_receipt_supersession rendent cette frontière
durable. Elles persistent les reçus parents et tentatives immuables,
contraignent chaque état à sens unique issued → activating → consumed, ou
la branche de récupération terminale explicite activating → superseded,
puis verrouillent les writers de sessions pendant le backfill sûr de tout gate
exact préexistant avec une opération initiale/courante synthétique
irréversible. La consommation d'un reçu active le singleton indépendant. Son
timestamp d'activation et sa première
opération sont immuables ; l'ID du premier contexte reste nul jusqu'au premier
nouveau gate exact, puis devient immuable. Les reçus consommés ultérieurs ne
peuvent que faire avancer current_v2_rollout_operation_id. Les sessions
exactes existantes continuent leurs mises à jour ordinaires sans rejouer la GUC
transactionnelle ; un gate exact nouvellement ajouté doit porter l'opération
courante. La chaîne synthétique de backfill ne constitue jamais une
autorisation suffisante : l'opération courante doit aussi correspondre à un
reçu réellement consommé avant l'ajout d'un autre gate exact. Le floor ne peut
être ni supprimé, ni tronqué, ni réinitialisé, ni
annulé par l'expiration/suppression de la session d'origine. Des triggers de
base de données et des gardes writer dans la
même transaction sérialisent les écritures legacy de session, composant, page,
review, publication et média sur ce singleton. Réinitialiser un flag
d'environnement ne peut donc pas rouvrir les mutations legacy. Les lectures
legacy, dry-runs purs, lectures idempotentes d'uploads terminés,
annulations/expirations et nettoyages média restent disponibles. Un commit
média refusé par ce floor supprime l'objet promu, tandis que le nettoyage d'un
upload préparé reste repris par le reaper.
Le workflow manuel constitue aussi la frontière de sûreté des binaires en
rolling : chaque ressource doit exécuter le SHA immuable en freeze avant
qu'une ressource passe en exact. Ne modifiez pas ces flags directement et ne
contournez pas ce workflow, car les anciens binaires ne contiennent pas toutes
les gardes applicatives du floor.
Le préflight stockage de l'image worker requiert HeadBucket, l'optionnel
CreateBucket, GetBucketPolicy, GetBucketAcl, PutObject, GetObject et
DeleteObject sur les buckets staging et formulaires. Il n'affiche jamais les
identifiants de stockage ni les erreurs provider complètes.
Pendant le setup, bun run seed téléverse les ressources par défaut de variables
globales de site dans le bucket média sous global/site-variables/* et écrit ces
URL publiques dans l'entrée site-variables/main. Les URL de ressources
personnalisées existantes sont préservées lorsque le seed est relancé.
Variables de stockage compatible S3:
| Variable | Où la récupérer |
|---|---|
S3_ENDPOINT | Endpoint fournisseur, par exemple http://minio:9000. |
S3_REGION | Région fournisseur. Utilisez us-east-1 pour MinIO sauf configuration différente. |
S3_ACCESS_KEY_ID | Identifiant de stockage server-side. |
S3_SECRET_ACCESS_KEY | Identifiant de stockage server-side. |
S3_FORCE_PATH_STYLE | Définir true pour MinIO et la plupart des endpoints compatibles S3 locaux. |
N'exposez jamais S3_ACCESS_KEY_ID ou S3_SECRET_ACCESS_KEY au navigateur ni
dans une variable NEXT_PUBLIC_*.
S3_SIGNED_PUBLIC_ENDPOINT est optionnel et n'est jamais déduit de
S3_ENDPOINT. En production, sa présence impose HTTPS, un hostname DNS public
multi-label, sans credentials, query ni fragment. Il active uniquement les PUT
directs signés ; les downloads restent derrière le proxy same-origin de l'app.
Avant de définir cette variable, configurez le CORS du bucket pour l'origine de
l'app, PUT et les headers Content-Type, Content-Length et
If-None-Match. STORAGE_TRANSFER_SIGNING_SECRET peut fournir un secret dédié
aux tokens opaques de transfert ; sinon le runtime se replie volontairement sur
CMS_PREVIEW_SIGNING_SECRET, puis BETTER_AUTH_SECRET. Le secret effectif en
production doit contenir au moins 32 caractères.
Domaines Publics
Les domaines publics d'organisation utilisent PUBLIC_DOMAIN_PROVIDER.
| Variable | Usage |
|---|---|
PUBLIC_DOMAIN_PROVIDER | vercel pour la gestion Vercel project-domain ou manual-dns pour la vérification DNS auto-hébergée. |
APP_MANAGED_HOSTS | Hôtes possédés par l'app, séparés par virgules, que les clients ne peuvent pas réclamer. |
RESERVED_PUBLIC_DOMAIN_SUFFIXES | Suffixes supplémentaires que les clients ne peuvent pas réclamer. .vercel.app est toujours réservé. |
PUBLIC_DOMAIN_CNAME_TARGET | Cible CNAME DNS manuel affichée aux opérateurs. |
PUBLIC_DOMAIN_IPV4_TARGETS | Cibles A-record DNS manuel séparées par virgules. |
PUBLIC_DOMAIN_TXT_PREFIX | Préfixe TXT de vérification, défaut _yayaw. |
VERCEL_TOKEN | Requis uniquement pour le fournisseur Vercel. |
VERCEL_PROJECT_ID | Requis uniquement pour le fournisseur Vercel. |
VERCEL_TEAM_ID | Scope équipe Vercel optionnel. |
manual-dns génère un challenge TXT de propriété et vérifie le DNS public. Il
n'automatise ni les changements chez le fournisseur DNS ni l'émission de
certificats TLS.
OpenAI
Les fonctions de génération IA requièrent:
OPENAI_API_KEY=Créez la clé depuis la page API keys de la plateforme OpenAI et stockez-la côté serveur dans l'environnement cible. Elle active le repli IA de composants, Page AI et la génération d'images lorsque les feature flags et réglages runtime correspondants sont actifs.
Toggles runtime IA optionnels:
| Variable | Défaut | Usage |
|---|---|---|
OPENAI_COMPONENTS_AI_FALLBACK | true | Active le repli IA pour inférence et classification de composants. |
OPENAI_IMAGE_GENERATION_ENABLED | true | Active la génération d'images du page builder lorsqu'une clé API existe. |
OPENAI_IMAGE_MODEL | gpt-image-1.5 | Modèle de génération d'images. |
PAGE_AI_QUEUE_DRIVER | Auto | direct localement, vercel-queue sur Vercel, ou db-worker pour un worker long-lived. La production auto-détecte Vercel et choisit sinon db-worker. |
PAGE_AI_DEEP_REFINEMENT | false | Toggle qualité interne, non exposé dans les réglages admin. |
PAGE_AI_WORKER_POLL_MS | 1500 | Intervalle de polling pour le driver worker base de données. |
PAGE_AI_WORKER_MAINTENANCE_MS | 60000 | Intervalle de rétention durable, nettoyage des objets orphelins et purge des buckets anti-abus. |
PAGE_AI_WORKER_ID | Vide | Identifiant optionnel pour un worker long-lived. |
Analytics
Choisissez un fournisseur analytics et un mode de capture:
NEXT_PUBLIC_ANALYTICS_PROVIDER=umami
NEXT_PUBLIC_ANALYTICS_CAPTURE_MODE=hybridFournisseurs supportés: posthog, umami, none. Le mode de capture peut être
hybrid, server ou client. hybrid est le défaut et enregistre des
événements facturation/auth fiables côté serveur tout en gardant l'analytics
produit navigateur. server ne rend pas de scripts analytics navigateur et
envoie les vues CMS plus les conversions depuis le serveur applicatif. client
conserve la capture uniquement navigateur.
Les événements de conversion serveur incluent checkout_started,
purchase_completed, subscription_started, subscription_updated,
subscription_cancel_scheduled, subscription_canceled et payment_failed.
Les événements de facturation incluent revenue, value, currency, plan,
product_key et les IDs Stripe pour la réconciliation. Les événements Stripe en
mode test sont suivis avec billing_mode=test et is_test_data=true, mais ne
comptent pas comme conversion, revenue ou value sauf activation du réglage
admin Track Stripe Test Billing Analytics. Le montant test original reste dans
test_amount_cents et test_revenue pour le débogage.
PostHog
La capture client et les feature flags utilisent les valeurs PostHog publiques:
NEXT_PUBLIC_POSTHOG_KEY=
NEXT_PUBLIC_POSTHOG_HOST=https://eu.i.posthog.com
NEXT_PUBLIC_POSTHOG_ENABLE_LOCAL=falseLes analytics dashboard côté serveur utilisent les valeurs PostHog privées:
POSTHOG_PERSONAL_API_KEY=
POSTHOG_PROJECT_ID=
POSTHOG_API_HOST=https://eu.posthog.com
POSTHOG_ORG_ID_PROPERTY=organization_id
POSTHOG_FLAG_LOOKUP_TIMEOUT_MS=Récupérez la clé projet publique et l'ID projet depuis les réglages PostHog.
Créez une personal API key avec l'accès suffisant à l'API Query et stockez-la
comme POSTHOG_PERSONAL_API_KEY. Gardez
POSTHOG_ORG_ID_PROPERTY=organization_id sauf changement de la propriété
d'événement analytics dans le produit. Définissez
POSTHOG_FLAG_LOOKUP_TIMEOUT_MS uniquement si les lookups de feature flags
PostHog côté serveur ont besoin d'un timeout différent du défaut 1500
millisecondes.
Umami
La capture client utilise les valeurs Umami publiques:
NEXT_PUBLIC_UMAMI_HOST_URL=https://analytics.example.com
NEXT_PUBLIC_UMAMI_SCRIPT_URL=
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
NEXT_PUBLIC_UMAMI_DOMAINS=
NEXT_PUBLIC_UMAMI_AUTO_TRACK=trueLes lectures dashboard côté serveur et la capture serveur utilisent les valeurs Umami privées:
UMAMI_API_URL=https://analytics.example.com
UMAMI_WEBSITE_ID=
UMAMI_API_TOKEN=
UMAMI_API_KEY=
UMAMI_USERNAME=
UMAMI_PASSWORD=
UMAMI_CMS_EVENT_PAGE_SIZE=1000Utilisez soit UMAMI_API_TOKEN (ou l'alias legacy UMAMI_API_KEY), soit
UMAMI_USERNAME plus UMAMI_PASSWORD pour les lectures de données dashboard.
La capture d'événements serveur utilise Umami /api/send; elle a donc seulement
besoin de UMAMI_API_URL et UMAMI_WEBSITE_ID.
Plan De Contrôle MCP
Le MCP production ne requiert pas de variable d'environnement dans le runtime
applicatif. Les clients se connectent à /api/mcp avec une clé API Better Auth
ou un access token OAuth.
Les tests stdio locaux peuvent utiliser:
YAYAW_MCP_API_KEY=
YAYAW_MCP_LOCAL_USER_ID=Créez, inspectez et révoquez les clés MCP avec:
bun run mcp:keyStockez les clés client de confiance hors du dépôt et passez-les au client comme
YAYAW_MCP_API_KEY.
Transforms Runtime Dynamic Data
Définissez DYNAMIC_DATA_RUNTIME_TRANSFORM_SECRET uniquement lorsque des routes
runtime dynamiques déployées utilisent des transforms de valeur hmac_sha256,
par exemple un code de pairing transformé en code_hash stocké.
DYNAMIC_DATA_RUNTIME_TRANSFORM_SECRET=$(openssl rand -hex 32)Stockez la valeur comme secret server-only dans l'orchestrateur. Sa rotation change les futures sorties HMAC; faites-la donc avec une migration de données spécifique au produit ou une fenêtre d'expiration des pairing sessions.
Mode Maintenance
Le mode maintenance est optionnel:
MAINTENANCE_MODE=false
MAINTENANCE_MODE_END_DATE=Définissez MAINTENANCE_MODE=true uniquement lorsque l'app doit servir la
surface de maintenance. Utilisez MAINTENANCE_MODE_END_DATE pour le contexte
opérateur.
Métadonnées De Déploiement
Les déploiements Vercel reçoivent automatiquement les métadonnées runtime. Les déploiements auto-hébergés peuvent fournir des métadonnées statiques:
| Variable | Usage |
|---|---|
DEPLOYMENT_PROVIDER | vercel, static ou local; vide auto-détecte. |
DEPLOYMENT_URL | URL publique de déploiement hors Vercel. |
DEPLOYMENT_ENV | Label d'environnement, par exemple production ou preview. |
DEPLOYMENT_GIT_COMMIT_SHA | SHA de commit pour statut dashboard/plan de contrôle. |
DEPLOYMENT_GIT_COMMIT_REF | Ref ou nom de branche. |
Checklist De Déploiement
Avant promotion:
- L'environnement cible possède chaque variable requise de
.env.exampleou.env.self-host.example. - La prévisualisation a soit des valeurs fournisseurs équivalentes à la production, soit des valeurs staging explicites.
NEXT_PUBLIC_BASE_URLcorrespond à l'origine HTTPS publique de l'environnement.- Stripe a deux endpoints webhook et chaque secret d'endpoint est mappé à la variable correspondante.
- L'accès au code GitHub a soit les réglages admin plus
BILLING_CODE_ACCESS_GITHUB_APP_PRIVATE_KEY, soit les replis d'environnement explicites pour dépôt, App ID, installation ID et clé privée. - Les variables Resend, PostHog, S3, OpenAI et OAuth ne sont présentes que lorsque ces fonctions sont activées.
- Coolify ou l'orchestrateur possède le
DATABASE_URLruntime utilisé par le service Composemigrate, et les environnements GitHub possèdent la valeur build-timeDATABASE_URLrequise parnext build. - Un nouveau déploiement ou redémarrage de conteneur a été déclenché après la dernière modification de variable.
- Lancez les barrières qualité locales avant de merger des changements de config de déploiement:
bun run check
bun run docs:generate
bun run docs:check-links
bun run docs:check-translations
bun run docs:llm:check
bunx tsc --noEmit
bun run buildRéférences Fournisseurs
- Vercel environment variables
- Vercel CLI environment commands
- Next.js self-hosting
- Next.js standalone output
- Docker Next.js guide
- Stripe API keys
- Stripe webhooks
- GitHub App registration
- GitHub App private keys
- GitHub repository collaborators API
- Resend API keys
- MinIO S3 compatibility
- OpenAI API authentication