Déploiement
Fournir le token de registre avant le build, configurer l'environnement de production et le reverse proxy.
Un projet LRVO se déploie comme n'importe quelle application Next.js, avec deux particularités : l'accès au registre privé au moment du build, et quelques variables qui changent de comportement en production.
1. Le token du registre, avant le build
npm ci va chercher @lrvo/core et les modules @lrvo/module-* sur le registre privé. Sans le token du .npmrc, il échoue avec un 404.
Par défaut, il n'y a rien à faire ici : le CLI d'installation laisse le .npmrc suivi par git, donc le serveur le reçoit avec le clone. Voir Secrets et git.
Si le .npmrc a été sorti de git, il faut le déposer sur la machine de build avant l'installation :
npm login --registry=https://registry.lrvo.app/
npx lrvo-key
npm ci
npm run buildOu, en CI, déposer ce .npmrc à la racine du projet et fournir le token dans la variable d'environnement LRVO_NPM_TOKEN, depuis un secret :
@lrvo:registry=https://registry.lrvo.app/
//registry.lrvo.app/:_authToken=${LRVO_NPM_TOKEN}npm ci${LRVO_NPM_TOKEN} s'écrit tel quel dans le fichier : npm le remplace par la valeur de la variable à la lecture du .npmrc. Le fichier ne contient donc aucun secret, quel que soit le shell de la machine de build.
Le token ne sert qu'à l'installation. Aucun code d'exécution ne le lit. Le fournir au démarrage de l'application ne sert donc à rien : il doit être présent avant le build.
Le token n'expire pas dans le temps. Voir lrvo-key.
2. Le build
npm run buildLe script est lrvo-modules sync && next build : la synchronisation des manifestes tourne juste avant, ce qui couvre les modules ajoutés, retirés ou mis à jour depuis le dernier déploiement.
3. Les variables de production
Le minimum :
NODE_ENV=production
NEXT_PUBLIC_URL=https://exemple.com
LRVO_NAME=Mon site
LRVO_DATABASE_URL=postgres://user:password@host:5432/prodNEXT_PUBLIC_URL doit porter l'URL publique réelle. Elle sert à la vérification CSRF : une valeur incorrecte fait refuser toutes les requêtes mutantes, avec un symptôme trompeur de formulaire qui ne répond plus.
Ce qui change en production :
| Variable | Effet |
|---|---|
NODE_ENV=production | La base passe en TLS strict contre le magasin d'autorités du système. |
LRVO_TRUST_PROXY | Nombre de reverse proxys devant l'application, pour que la limitation de débit voie l'IP réelle. Voir Le reverse proxy. |
LRVO_DEVKIT | Laisser absent ou à false. |
4. TLS de la base
Le défaut en production est strict. Si la base n'est joignable que par un réseau privé, avec un certificat auto-signé, deux options :
LRVO_DB_SSL_CA=/etc/ssl/certs/db-ca.pem # préférable : chiffre et authentifie
LRVO_DB_SSL_NO_VERIFY=true # chiffre seulementLRVO_DB_SSL_CA accepte un PEM inline ou un chemin de fichier.
Ne pas utiliser LRVO_DB_SSL_DISABLED=true en production : le trafic passerait en clair.
5. Le reverse proxy
Faire suivre les en-têtes d'origine, sinon la limitation de débit ne voit qu'une seule IP.
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}Puis déclarer côté application combien de proxys une requête traverse :
| Devant l'application | Valeur |
|---|---|
| Aucun proxy | LRVO_TRUST_PROXY=false |
| Un proxy : nginx, Caddy, ou Cloudflare relié directement à l'application | LRVO_TRUST_PROXY=true, équivalent à 1 |
| Deux proxys : Cloudflare, puis nginx | LRVO_TRUST_PROXY=2 |
Ce nombre décide de l'entrée lue dans X-Forwarded-For. Chaque proxy ajoute à la fin de l'en-tête l'adresse qui vient de le joindre, et conserve ce que le client avait déjà écrit au début. Seules les dernières entrées sont donc dignes de confiance, une par proxy. Le core lit la N-ième en partant de la droite et ignore le reste, y compris la première, que le client choisit librement.
Le compte doit être exact. Trop bas, le core lit l'adresse du proxy amont : derrière Cloudflare puis nginx avec true, tous les visiteurs d'un même nœud Cloudflare partagent un compteur et se bloquent entre eux. Trop haut, il lit une entrée que le client a écrite, et la limitation se contourne.
L'application ne doit être joignable que par son proxy. Un client qui atteint directement le port de l'application, ou nginx sans passer par Cloudflare, écrit lui-même les entrées que le core croit ajoutées par un proxy. Écouter sur 127.0.0.1, et derrière Cloudflare n'ouvrir le pare-feu de l'origine qu'aux plages d'adresses de Cloudflare.
Ne pas activer cette variable sans proxy devant. Un client pourrait alors forger un X-Forwarded-For variable et contourner la limitation de débit.
6. Initialiser la base
npx lrvo-db initÀ lancer une fois au premier déploiement. La commande est idempotente.
Aux déploiements suivants, migrate suffit et se contente de mettre le schéma à niveau :
npx lrvo-db migrateLes deux commandes prennent un verrou consultatif : plusieurs répliques qui déploient en même temps se sérialisent au lieu de se marcher dessus.
Ne jamais lancer npx lrvo-db drop en production.
7. Vérifier
| Vérification | Attendu |
|---|---|
GET /lrvo/api/health | Réponse de succès. |
/auth/login | Page servie. |
| Connexion | Aboutit, cookie posé. |
/admin | Accessible avec un compte admin. |
| Un formulaire d'admin | Enregistre. Un échec pointe vers NEXT_PUBLIC_URL. |
| Journaux du démarrage | Aucun avertissement de variable requise absente. |
Multi-instance
Deux comportements changent avec plusieurs instances.
Les tâches planifiées s'exécutent partout. Chaque instance a son propre registre cron : un job horaire tourne une fois par instance. Une tâche qui ne doit s'exécuter qu'une fois doit poser un verrou en base. Voir Planifier des tâches.
La limitation de débit est locale au processus. Les compteurs vivent en mémoire : la limite effective est multipliée par le nombre d'instances. Pour une limitation réellement partagée, il faut un magasin atomique externe. Voir Rate limit.
Sauvegardes
Sauvegarder la base et LRVO_ENCRYPTION_KEY, séparément. Une sauvegarde sans la clé est inexploitable pour les colonnes chiffrées, et il n'existe pas de récupération possible. Tester une restauration au moins une fois.
Mettre à jour
npx lrvo-updateElle monte le core et les modules ensemble, affiche ce qui change, puis enchaîne la synchronisation des manifestes, les migrations et le diagnostic. Voir Mettre à jour un projet.
Une version majeure signale un changement cassant. Lire la note de version, livrée dans node_modules/@lrvo/core/CHANGELOG.md, et vérifier en particulier le retrait éventuel d'un sous-chemin de package.json#exports, qui casse au build. Voir Publication.
Gardes d'intégration continue
Trois commandes n'écrivent rien et sortent en code 1 quand une intervention est nécessaire.
npx lrvo-update --check # une mise à jour LRVO est disponible
npx lrvo-doctor # un constat est bloquant
npx lrvo-db status # une migration est en attentelrvo-db status avant un déploiement dit si migrate aura quelque chose à faire.