Guide de déploiement prod : VM Debian nue (sans Docker), service systemd, déploiement par push Git (bare repo + post-receive), branchement rsync/SSH en lecture seule à la prod Grav, reverse proxy HTTPS, dimensionnement VM.
portfolio-maker (stack)
Dépôt d'orchestration de l'environnement du générateur de portfolios PDF de Figures Libres. Il ne contient pas de code applicatif : il câble ensemble, via Docker Compose, l'app et le CMS Grav d'exemple qui lui sert de source de contenu.
Trois dépôts, un environnement
Ce dépôt attend deux autres checkouts posés côte à côte (chacun a son propre dépôt git et n'est pas versionné ici) :
portfolio-maker/ # CE dépôt (stack)
├── docker/grav/Dockerfile # Image PHP+Apache servant grav-reference/
├── docker-compose.yml # Services grav-reference (8089) + generator (8091)
├── docker-compose.prod.yml # Surcouche déploiement (build Nitro + rsync prod)
├── generator/ ←──────── dépôt À PART : l'app Nuxt (Dockerfile inclus) = le livrable
└── grav-reference/ ←──────── dépôt À PART : le vrai site Grav (~4,8 Go), monté :ro
generator/— le générateur (Nuxt). Détails d'architecture : voir son propreREADME.md/CLAUDE.md. Poussé sur le gitea figureslibres.io.grav-reference/— CMS Grav d'exemple, en lecture seule (monté:ro). C'est la source de contenu, pas l'app à développer.
⚠️ Tout tourne dans Docker : Node, build Nuxt, Playwright/Chromium, Ghostscript, ffmpeg, rsync — rien n'est installé sur l'hôte.
📦 Non versionné dans ce dépôt :
generator/etgrav-reference/(dépôts séparés, à cloner côte à côte), ainsi quedocs/(PDF de référence + spec déjà réalisée). LeDockerfilede l'image Grav, lui, reste versionné dansdocker/grav/.
Lancer en dev
docker compose up -d # grav-reference + generator
- Grav de référence : http://localhost:8089
- Générateur de portfolios : http://localhost:8091 — mot de passe partagé :
figureslibres(variablePORTFOLIO_PASSWORD)
Le générateur lit directement grav-reference/user/pages/02.projets/ (mode DEV
de ContentSource). Le bouton « Rafraîchir » relit le contenu local.
Commandes utiles (toujours via le conteneur) :
docker compose run --rm --no-deps generator npm install # dépendances
docker compose exec generator npm run build # build de prod
docker logs -f figureslibres-portfolio-generator # logs du dev server
Parcours utilisateur
- Se connecter (mot de passe partagé) — on arrive sur la liste des portfolios.
- Créer un portfolio : ajouter des projets via la modale « Ajouter un
projet » (recherche plein texte, filtres catégorie/tag — seuls les projets
publiés sont proposés). Chaque projet = deux pages ou plus, fidèles au
gabarit
book_v3(PDF de référence dansdocs/, non versionné) :- une page couverture : bandeau 55 mm couleur de la catégorie (titre en fonte d'« utilité » — Playfair/Manifont/Avara —, pastille, présentation Syne 12/16 pt) + image de couverture (celle de la grille du CMS) ;
- des pages grille : filet 5 mm, marges 8 mm, gouttières 3,8 mm, images entières (jamais tronquées) calées sur la grille — 8 dispositions au choix, présentées par icônes. Les vidéos ne sont pas sélectionnables. Couleur de bandeau et texte noir/blanc réglables (palette du gabarit + couleurs du site). Pages spéciales : couverture, sommaire, page libre. Aperçu WYSIWYG A3 paysage, sauvegarde automatique.
- Générer le PDF (nom de fichier personnalisable) : rendu Playwright/Chromium
au format A3 paysage (1190,55 × 841,89 pt, comme le gabarit), images
redimensionnées à 2× leur taille d'affichage (sharp), post-traitement
Ghostscript, métadonnées. Le contenu utilisé est figé
(
data/frozen/<id>/) : régénérer redonne le même PDF ; « Réactualiser depuis Grav » resynchronise volontairement.
Déploiement (mode PROD)
Le contenu est tiré de la prod par rsync/SSH en lecture seule vers
generator/data/content-cache/, déclenché par le bouton « Rafraîchir ».
# .env (non versionné)
PORTFOLIO_PASSWORD=…
SESSION_SECRET=…
INTERNAL_TOKEN=…
SYNC_REMOTE=user@prod:/chemin/vers/user/pages/02.projets/
SYNC_SSH_KEY_FILE=/chemin/local/vers/cle_privee
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d generator
Données
Tout est sur disque dans generator/data/ (sauvegarde = copie du dossier) :
portfolios/*.json (compositions), exports/*.pdf, frozen/<id>/ (snapshots),
cache/ (miniatures, posters vidéo — régénérable), content-cache/ (rsync prod).