Déploiement
Le Labo du Yeti est conçu pour un déploiement une instance = un client sur un VPS Plesk (Linux). Le serveur Node tourne en permanence, expose une API sur un port interne, et Plesk fait office de reverse proxy HTTPS. Ce guide couvre l'installation complète, du clone Git au premier compte owner.
JWT_SECRET, son propre domaine. Aucune donnée n'est mutualisée entre clients. La mise à jour se fait par git pull manuel ou via un tag de release.1. Prérequis serveur
Le CMS est volontairement léger en dépendances système. Une instance fonctionne sur un VPS partagé Plesk modeste (1 vCPU, 1 Go RAM, 10 Go SSD) pour un site jusqu'à quelques milliers de pages générées.
1.1 Logiciels requis
| Composant | Version | Notes |
|---|---|---|
| Node.js | 22 LTS | Obligatoire. Plesk fournit Node 22 via /opt/plesk/node/22/. better-sqlite3 dispose de prebuilds pour Node 22 → pas de compilation native. |
| npm | 10+ | Livré avec Node 22. Sur Plesk, accessible via /opt/plesk/node/22/bin/npm. |
| SQLite | intégré | Aucune installation séparée. better-sqlite3 embarque le moteur. Mode WAL activé au boot. |
| Git | 2.30+ | Pour cloner et mettre à jour le dépôt. |
| SMTP | optionnel | Recommandé pour 2FA email, reset password et notifications cocon. Voir Réglages SMTP. |
1.2 Dimensionnement indicatif
- Site vitrine (10-50 pages) : 512 Mo RAM, 5 Go disque suffisent.
- Site cocon (500-2000 pages générées) : 1 Go RAM, 10 Go disque, prévoir bande passante pour les batchs IA.
- Site blog actif (100+ articles avec featured images) : 1 Go RAM, 20 Go disque (médiathèque), CDN recommandé pour
public/.
2. Variables d'environnement (.env)
Le fichier .env à la racine du projet pilote toute la configuration sensible. Sur Plesk, il est préférable de déclarer ces variables dans le panel Node.js (section Variables d'environnement) plutôt que de committer un fichier — Plesk les injecte au démarrage du process.
.env dans Git. Le .gitignore du projet l'exclut explicitement. Un JWT_SECRET qui fuit = tous les comptes admins compromis.2.1 Variables disponibles
| Variable | Obligatoire | Valeur par défaut / exemple | Rôle |
|---|---|---|---|
PORT | recommandé | 3001 | Port d'écoute du serveur Node. Plesk proxifie ce port en HTTPS. |
NODE_ENV | oui | production | Désactive les logs verbeux, active les caches, force le mode strict d'Express. |
JWT_SECRET | oui | chaîne ≥ 24 caractères | Clé de signature des JWT. Doit être unique par instance. Voir génération ci-dessous. |
JWT_EXPIRES_IN | non | 7d | Durée de vie des tokens JWT. Format ms (1h, 30m, 7d). |
CORS_ORIGIN | oui | https://client.exemple.com | Domaine front autorisé. Peut être une liste séparée par virgules. |
SMTP_HOST | optionnel | smtp.mailgun.org | Serveur SMTP pour 2FA, reset password, notifications cocon. |
SMTP_PORT | optionnel | 587 | Port SMTP. 465 pour TLS direct, 587 pour STARTTLS. |
SMTP_USER | optionnel | compte SMTP | Identifiant SMTP. |
SMTP_PASS | optionnel | mot de passe SMTP | Mot de passe ou clé d'app SMTP. |
SMTP_FROM | optionnel | "CMS <no-reply@client.com>" | Expéditeur des emails sortants. |
NPM_BIN | Plesk | /opt/plesk/node/22/bin/npm | Chemin absolu vers npm. Utilisé par le loader d'extensions quand npm n'est pas dans le PATH du process Node Plesk. |
2.2 Génération d'un JWT_SECRET fort
Le secret JWT doit être imprévisible. La commande Node ci-dessous génère une chaîne hex de 96 caractères (48 octets aléatoires) :
node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"
Copier la sortie dans JWT_SECRET. Un secret de moins de 24 caractères fait échouer le démarrage avec une erreur explicite dans les logs : le serveur refuse de démarrer en mode NODE_ENV=production avec un secret faible.
2.3 Exemple .env minimal
PORT=3001
NODE_ENV=production
JWT_SECRET=a7f3b9c1d8e2f4a6b9c3d1e5f7a9b2c4d6e8f1a3b5c7d9e2f4a6b8c1d3e5f7a9b2c4d6e8f1a3b5c7d9
JWT_EXPIRES_IN=7d
CORS_ORIGIN=https://client.exemple.com
# SMTP (recommandé)
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=postmaster@mg.client.exemple.com
SMTP_PASS=xxxxxxxxxxxxxxxx
SMTP_FROM="Le Labo du Yeti <no-reply@client.exemple.com>"
# Plesk uniquement, si extensions npm install échoue
NPM_BIN=/opt/plesk/node/22/bin/npm
3. Setup Plesk pas à pas
Plesk gère le reverse proxy HTTPS, le process Node (démarrage / redémarrage automatique), et l'injection des variables d'environnement. Voici la procédure complète.
3.1 Créer le domaine
- Dans Plesk, Sites Web et Domaines → Ajouter un domaine.
- Saisir le nom de domaine (ex.
client.exemple.com) et créer un utilisateur FTP/SSH dédié. - Activer le SSL (Let's Encrypt) dès la création — Plesk renouvelle automatiquement le certificat.
- Activer la redirection HTTPS forcée dans Hébergement & DNS.
3.2 Cloner le dépôt
Via SSH ou l'extension Git de Plesk, cloner le dépôt dans le répertoire du domaine :
cd /var/www/vhosts/client.exemple.com/
git clone https://github.com/ton-org/cms-ia.git httpdocs-app
cd httpdocs-app
frontend/dist/ fait partie du dépôt (voir commit "Add frontend/dist build + update gitignore for Plesk deploy"). Plesk ne fait pas de build npm à l'install — la RAM des hébergements partagés ne suffit pas pour vite build. Le build est fait en local ou en CI, puis commité.3.3 Configurer le Document Root
Le serveur Node compile les pages statiques dans public/. Plesk doit pointer son Document Root sur ce sous-dossier — pas sur la racine du projet. Cela isole le code source des fichiers servis publiquement.
- Sites Web et Domaines → ton domaine → Paramètres d'hébergement.
- Répertoire racine du document :
/httpdocs-app/public(ou le chemin équivalent selon ton clone). - Sauvegarder.
.env, content/cms.db, ou les sources backend en tapant l'URL. Avec public/ comme racine, seuls les fichiers compilés et la médiathèque sont exposés.3.4 Activer Node.js
- Onglet Node.js du domaine (extension Plesk).
- Version Node.js : 22.x LTS.
- Mode applicatif :
production. - Racine de l'application :
/httpdocs-app(racine du clone, paspublic/). - URL applicative : laisser le défaut (Plesk gère le proxy).
- Fichier de démarrage de l'application :
backend/src/server.js.
3.5 Installer les dépendances
Dans le panneau Node.js de Plesk, cliquer sur NPM install. Plesk lance npm install --omit=dev dans la racine de l'application. La commande compile better-sqlite3 (prebuild Node 22, pas de compilation native si Node 22 est correctement détecté), sharp, bcrypt.
Si NPM install échoue (cas observé sur certaines installations Plesk où le PATH du process Node ne contient pas npm), définir NPM_BIN=/opt/plesk/node/22/bin/npm dans les variables d'environnement Plesk puis relancer. Le loader d'extensions utilise cette variable pour exécuter npm install dans les sous-dossiers d'extensions sans dépendre du PATH. Voir le commit "Fix(extensions): résoudre npm via sibling de node (Plesk-safe)".
3.6 Déclarer les variables d'environnement
Dans le panneau Node.js, section Variables d'environnement personnalisées, ajouter une à une les variables du .env (cf. section 2.3). Plesk les injectera au démarrage. Ne pas committer .env.
3.7 Démarrer / redémarrer l'application
Cliquer sur Redémarrer l'application dans le panel Node. Vérifier les logs (Logs dans le panel Node) — le démarrage normal affiche :
[boot] SQLite WAL ready
[boot] stores seeded
[boot] extensions loaded: hello-world
[boot] server listening on :3001
[boot] CORS allowed: https://client.exemple.com
4. Premier accès et bootstrap
À l'installation initiale, la base est vide : aucun utilisateur, aucune page. Le CMS détecte cet état et bascule en mode bootstrap, qui force la création du premier compte owner.
4.1 Accéder à l'admin
Visiter https://client.exemple.com/admin. La SPA React détecte l'absence d'utilisateurs (via GET /api/auth/status qui retourne needs_bootstrap: true) et affiche l'écran Bootstrap au lieu du login.
4.2 Créer le premier owner
L'écran demande : nom complet, username, email, mot de passe (8 caractères minimum, avec majuscule + chiffre). À la validation, l'API POST /api/auth/bootstrap crée le compte et lui attribue automatiquement le rôle owner — c'est le seul rôle capable de modifier les paramètres Sécurité et de promouvoir d'autres utilisateurs.
POST /api/auth/bootstrap retourne 403. Pour créer un second owner, se connecter en tant que owner et utiliser Réglages → Administrateurs → Ajouter.4.3 Configurer SMTP (recommandé immédiatement)
Une fois connecté, aller dans Réglages → Général → SMTP et renseigner les identifiants. Le bouton Tester l'envoi envoie un email de test à l'adresse du compte courant. Sans SMTP, la 2FA email est désactivée, et les rappels cocon vers admin / webmaster ne partent pas.
4.4 Activer le mode production
Dans Réglages → Sécurité (accessible uniquement au owner), basculer Mode de development à production. Cela :
- force la 2FA email sur toutes les connexions (impossible de la désactiver par utilisateur) ;
- active la rotation forcée des tokens API expirés ;
- verrouille les paramètres Sécurité (toute modification ultérieure nécessite une re-saisie du mot de passe).
5. Sauvegarde et restauration
Toutes les données utilisateur tiennent dans trois emplacements : content/cms.db (base SQLite), uploads/ (médias), extensions/installed/ (extensions installées par l'utilisateur). Le CMS offre deux mécanismes de backup.
5.1 Backup via l'UI
Dans Réglages → Sécurité → Sauvegardes, le bouton Exporter le site (.zip) génère un ZIP contenant la DB (checkpointée en WAL TRUNCATE avant export), les médias, et les extensions. Téléchargement direct. Réservé au rôle owner.
Le bouton Restaurer depuis un .zip remplace l'état courant par le contenu du ZIP. Avant chaque restore, un safety backup automatique est créé dans backups/safety/ côté serveur — récupérable en cas de mauvaise manipulation. Rate-limité à 1 restauration par minute pour éviter les accidents.
5.2 Backup côté Plesk
En complément, configurer une sauvegarde Plesk hebdomadaire qui inclut le dossier complet de l'application. Cela couvre aussi les variables d'environnement et la configuration Node Plesk.
6. CI/CD et mises à jour
6.1 Workflow manuel : git pull + restart
Le workflow le plus simple pour mettre à jour une instance :
# Via SSH
cd /var/www/vhosts/client.exemple.com/httpdocs-app
git pull origin main
# Si dépendances modifiées : NPM install via le panel Plesk
# Sinon : juste Redémarrer l'application via le panel Plesk
Ou tout faire depuis Plesk : extension Git → Tirer maintenant, puis Node.js → Redémarrer l'application.
6.2 Données préservées par git pull
Le .gitignore exclut toutes les données utilisateur — un git pull ne peut pas écraser :
content/cms.db*(base SQLite + WAL)uploads/*(médiathèque)public/*(HTML compilé, sauf assets versionnés)brouillons/templates/pages|articles|cocon/*extensions/installed/*(saufhello-worldversionné comme exemple).envnode_modules/
6.3 Pipeline GitHub Actions (roadmap)
Un workflow build-release.yml est planifié (cf. Roadmap) pour automatiser :
npm cidansfrontend/etbackend/;vite build→frontend/dist/;- commit + push de
frontend/dist/sur une brancherelease; - tag semver pour suivi des versions clients.
Les instances Plesk pourront alors git pull origin release au lieu de main, garantissant un frontend testé et buildé.
7. Checklist de mise en production
À cocher avant d'annoncer le site comme livré :
- Node 22 LTS sélectionné dans le panel Plesk.
- Document Root pointe sur
public/, pas sur la racine. - SSL Let's Encrypt actif et HTTPS forcé.
JWT_SECRETunique, généré viacrypto.randomBytes(48), jamais commité.CORS_ORIGINrenseigné avec le domaine exact (pas de wildcard).NODE_ENV=productiondans les variables Plesk.- SMTP configuré et testé depuis l'UI.
- Premier owner créé via le bootstrap (compte personnel, pas générique).
- Mode production activé dans Réglages → Sécurité (2FA forcée).
- Backup Plesk hebdo programmé.
- Au moins un export ZIP manuel téléchargé et archivé hors-serveur.
- Logs Plesk Node vérifiés sans erreur au démarrage.
- Test complet : connexion, création page, build, vue publique du site.
8. Dépannage Plesk-specific
| Symptôme | Cause probable | Solution |
|---|---|---|
npm install échoue depuis l'UI extensions | PATH du process Node ne contient pas npm | Ajouter NPM_BIN=/opt/plesk/node/22/bin/npm dans les variables Plesk. |
better-sqlite3 erreur NODE_MODULE_VERSION mismatch | Modules compilés pour une autre version de Node | Supprimer node_modules/ et relancer NPM install avec Node 22 sélectionné. |
404 sur /admin | Document Root pointé à la racine au lieu de public/ | Corriger le Document Root dans Paramètres d'hébergement. |
| CORS bloque le frontend | CORS_ORIGIN manquant ou incorrect | Vérifier la valeur exacte du domaine (avec https://, sans slash final). |
| 2FA jamais reçue après bascule production | SMTP non configuré ou identifiants invalides | Bloquer en SSH, repasser auth.security.mode = development dans la DB, retester SMTP. |
App ne redémarre pas après git pull | Plesk ne détecte pas le changement de fichier | Cliquer manuellement Redémarrer l'application dans le panel Node. |
Pour les anti-patterns à éviter en production (auto-pull main, build frontend sur Plesk, etc.), consulter la page Anti-patterns. Pour le détail des paramètres de sécurité, voir Sécurité.