Table des matières :
- FrankenPHP : un serveur d’application PHP (pas juste un “remplaçant de PHP-FPM”)
- Pré-requis concrets pour PrestaShop (et les limites du core face aux modes “workers”)
- Déploiement Caddy + FrankenPHP : configuration minimale, HTTP/3, et points qui cassent en prod
- HTTPS automatique : ce que Caddy fait bien… et ce qu’il ne fera pas à votre place
- Performance : où FrankenPHP peut aider (et où OPcache/SQL font 80% du boulot)
- Exploitation : reverse proxy, haute dispo, logs, et stratégie de rollback
- Checklist de bascule FrankenPHP pour une boutique PrestaShop (interop, sécurité, SEO)
FrankenPHP : un serveur d’application PHP (pas juste un “remplaçant de PHP-FPM”)
FrankenPHP ne se contente pas d’exécuter des scripts PHP derrière un serveur web classique : il embarque directement le runtime PHP dans un binaire basé sur Caddy. La définition à garder en tête est celle d’un serveur d’application : la couche qui gère la réception HTTP, le routage, TLS, la compression, le support HTTP/2/HTTP/3, puis l’exécution applicative (ici PHP) avec un cycle de vie contrôlé (process/threads/workers, recyclage, limites mémoire, etc.). Autrement dit, vous déplacez une partie de l’orchestration “nginx + php-fpm” dans une seule unité opérationnelle.
Le point clé côté infra : vous supprimez le protocole FastCGI et la séparation stricte webserver/PHP-FPM. Dans le meilleur des cas, ça réduit la complexité (moins de sockets, moins de configuration, moins de points de panne) et une partie de la latence “glue” (acceptation de la connexion → proxy → FPM → retour). Dans le pire des cas, vous coupez des options d’isolation et de scaling que les équipes maîtrisent déjà (pool FPM par vhost, tuning du backlog, séparation de responsabilités entre reverse proxy et PHP).
Sur la promesse produit, la doc officielle résume bien l’intention : « FrankenPHP is a modern application server for PHP built on top of the Caddy web server » (README du projet FrankenPHP : https://github.com/dunglas/frankenphp). Caddy, de son côté, se positionne explicitement comme un serveur web orienté production et automatisation TLS : « Caddy is a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go » (site officiel Caddy : https://caddyserver.com/). Ces deux phrases posent le cadre : app server PHP + HTTPS automatique + HTTP/2/HTTP/3.
Concrètement, en exploitation, ce “binaire unique” change aussi votre façon de raisonner sur :
- L’artefact de déploiement : au lieu d’un paquet nginx + un paquet PHP-FPM + une conf de reverse proxy, vous déployez un binaire (souvent containerisé) qui fait front + exécution. C’est séduisant en staging et en environnements éphémères, mais ça implique d’être rigoureux sur la version de binaire, les modules PHP intégrés, et la reproductibilité.
- Les limites de debug : quand ça casse, vous n’avez plus “nginx d’un côté / FPM de l’autre”. Il faut donc prévoir des logs structurés (accès + erreurs PHP) et des métriques pour attribuer une latence (réseau, TLS, file_server, PHP, DB).
- Le modèle de sécurité : vous devez revalider les “invariants” que vous aviez acquis avec votre stack (fichiers exposés, répertoires sensibles, règles de blocage, rate limiting, isolation par vhost).
L’objectif n’est pas d’annoncer “FrankenPHP = plus rapide” par défaut, mais de comprendre où la simplification peut vous faire gagner du temps (opérations) et où elle peut vous coûter (surprises sur les chemins, les règles de réécriture, l’isolement).
Pré-requis concrets pour PrestaShop (et les limites du core face aux modes “workers”)
Pour rester factuel : PrestaShop n’a pas été conçu historiquement comme une application “long-running”. Sur PrestaShop 8.x et 9.x, on a un mix legacy (classes statiques, singletons, caches in-memory implicites) et Symfony (Back‑Office, services). FrankenPHP peut fonctionner en mode “classique” (un cycle PHP par requête) sans changer vos hypothèses. En revanche, dès que vous cherchez à activer des modes de workers/persistance applicative, vous devez auditer tout ce qui fuit entre requêtes (état global, connexions DB persistantes, caches statiques). En e‑commerce, une fuite mémoire lente vaut souvent un incident à J+3 en pleine charge.
Un moyen simple de cadrer l’audit “compat long‑running” (sans réécrire PrestaShop) est de se poser, module par module, ces questions très opérationnelles :
- Est-ce qu’on utilise des variables statiques pour cache/local state (ex. “memoization maison”) ?
- Est-ce qu’on garde des ressources ouvertes (handlers, fichiers, sockets) sans fermeture explicite ?
- Est-ce que des services/objets sont réutilisés entre requêtes alors qu’ils contiennent de l’état utilisateur (panier, devises, langue, contexte) ?
- Est-ce que des outils de profiling ou de debug (toolbar, modules BO) accumulent des données en mémoire ?
- Est-ce que la boutique s’appuie sur des sessions sur filesystem (risque en HA / besoin de sticky) ?
Niveau versions, gardez une matrice simple : PrestaShop 8.1/8.2 et PrestaShop 9 (y compris 9.2 en cours de stabilisation) tournent correctement sur des PHP 8.x, mais les versions exactes “recommandées” changent et la doc n’est pas toujours cohérente. Avant toute bascule, alignez-vous sur une source interne et versionnée ; à défaut, recoupez avec l’article : PrestaShop 9 : versions PHP recommandées et incohérences de documentation. Côté extensions PHP, ne partez pas du principe que “FrankenPHP embarque tout” : vous devez valider les modules requis (intl, gd/imagemagick selon stack, bcmath, curl, mbstring, zip, etc.) et les contraintes Apache/nginx historiques (modrewrite) deviennent des contraintes de réécriture Caddy. Pour les prérequis système (y compris GeoIP, bcmath), voir : Exigences système : prérequis modrewrite, bcmath et GeoIP nouveau format et Exigences système : compatibilités PHP, MariaDB et Elasticsearch minimales.
Enfin, gardez en tête un risque opérationnel spécifique à PrestaShop : le front-office sert beaucoup de statiques (images produits, thèmes, assets compilés), et les chemins ne sont pas “/public/” à la Symfony. Toute erreur de root/réécriture va se traduire par des 404 massifs, des pages “vides” (erreurs PHP masquées) et une dégradation SEO rapide. Si vous avez déjà vu l’impact, l’article Page vide : causes fréquentes et impact sur l’indexation Google est un bon rappel : côté serveur, un mauvais routage PHP finit en “soft 404”, en erreurs 500/503, et Google ne pardonne pas.
Un exemple très concret : sur une boutique où les images produits sont dans /img/p/…, un simple mauvais root (ou une réécriture trop agressive qui renvoie tout vers index.php) peut transformer des milliers d’URLs d’images en pages PHP, dégrader le cache navigateur/CDN, et faire exploser le CPU — tout en cassant l’expérience utilisateur et les signaux SEO (temps de chargement, erreurs, ressources bloquées).
Déploiement Caddy + FrankenPHP : configuration minimale, HTTP/3, et points qui cassent en prod
Le modèle le plus simple en 2026 reste : un binaire FrankenPHP (Caddy inclus) en frontal, qui sert les fichiers statiques et exécute PHP. Exemple de Caddyfile pour une boutique PrestaShop installée dans /var/www/prestashop (sans réorganisation en /public) :
{
# Active FrankenPHP (directive globale)
frankenphp
# Bonnes pratiques de logs en prod (à adapter)
log {
output file /var/log/caddy/access.log
format json
}
}
shop.example.com {
root * /var/www/prestashop
# HTTP/3 : Caddy l'annonce via Alt-Svc lorsque HTTPS est actif.
# Attention : il faut ouvrir UDP/443 sur le firewall, sinon fallback TCP.
# Gestion PHP (FrankenPHP)
php_server
# Statique
file_server
# Sécurité minimale (à compléter)
header {
X-Content-Type-Options nosniff
Referrer-Policy strict-origin-when-cross-origin
}
}
Trois points à vérifier immédiatement : (1) droits sur le filesystem (cache, upload, img, var), (2) réécritures (PrestaShop a besoin d’URL rewriting pour le SEO), (3) taille d’upload (max body) et timeouts côté serveur. Caddy n’est pas nginx : vos réflexes client_max_body_size ou fastcgi_read_timeout ne se traduisent pas 1:1. En pratique, vous testez : upload d’image produit, régénération thumbnails, import CSV, checkout, BO, et vous comparez aux logs.
Pour éviter les régressions “invisibles”, prenez 10 minutes pour établir une mini-table d’équivalence (utile en revue de conf) :
| Besoin courant (nginx/FPM) | Ce que vous vérifiez côté Caddy/FrankenPHP | Symptôme si oublié |
|---|---|---|
Limite upload (client_max_body_size) |
limites “request body” côté serveur + upload_max_filesize/post_max_size PHP |
imports CSV qui échouent, uploads image KO |
Timeouts FPM (fastcgi_read_timeout) |
timeouts serveur + max_execution_time PHP |
checkout qui “tourne” puis 504/502 |
Réécritures .htaccess |
règle de front controller et exclusions statiques | pages catégories/produits en 404 |
| Blocage fichiers sensibles | interdiction d’accès à certains patterns/dirs | fuite de fichiers de config, templates, etc. |
| Logs séparés access/error | access logs JSON + logs PHP exploitables | diagnostic difficile, “on ne sait pas où ça casse” |
Côté statiques, vous pouvez aussi gagner vite sur la bande passante en activant la compression côté serveur (à valider avec votre CDN si vous en avez un). L’idée n’est pas de “tout compresser” aveuglément, mais de s’assurer que CSS/JS/HTML sont bien servis avec un encodage moderne là où c’est pertinent.
Pour HTTP/3, évitez les affirmations “ça va tout accélérer”. HTTP/3 est défini comme un mapping HTTP sur QUIC : « This document defines HTTP/3, an HTTP semantic mapping that uses QUIC as the transport protocol » (IETF, RFC 9114 : https://www.rfc-editor.org/rfc/rfc9114). Dans un contexte e‑commerce, le gain se voit surtout sur réseaux mobiles instables (moins de head-of-line blocking au niveau transport) et sur les premiers handshakes. Mais si votre TTFB est dominé par MySQL/Redis/templating, HTTP/3 ne compensera pas un backend lent.
Dernier point “prod” souvent sous-estimé : si vous activez HTTP/3, n’oubliez pas que ça implique UDP/443. Dans un contexte d’entreprise (pare-feu strict, certains load balancers, ou protections anti-DDoS), vous pouvez vous retrouver avec un HTTP/3 annoncé mais inutilisable. Ce n’est pas dramatique (fallback HTTP/2), mais c’est typiquement le genre de détail qui pollue les tests si vous ne le notez pas explicitement dans le runbook.
HTTPS automatique : ce que Caddy fait bien… et ce qu’il ne fera pas à votre place
Caddy est crédible sur l’automatisation TLS parce qu’il gère ACME (Let’s Encrypt, ZeroSSL, etc.) et renouvelle en continu. Let’s Encrypt rappelle l’objectif : « Let’s Encrypt is a free, automated, and open Certificate Authority » (site officiel : https://letsencrypt.org/). Dans un flux DevOps, ça vous évite un pan entier d’“opérations certifs” (cron de renouvellement, reload, erreurs humaines). Concrètement, pour une boutique PrestaShop, le bénéfice principal est la réduction du risque de certificat expiré (incident conversion + SEO).
Deux implications pratiques (et testables) à intégrer à votre checklist :
- ACME a besoin d’un chemin de validation : typiquement accès entrant sur 80/443 selon le challenge utilisé. Si vous êtes derrière un proxy/LB, il faut s’assurer que le challenge est correctement routé.
- Les environnements de staging : en test, vous pouvez rapidement atteindre des limites si vous recréez des certificats en boucle (selon l’autorité). Cela pousse à stabiliser les noms de domaines de test et à automatiser proprement.
Mais HTTPS automatique n’est pas “durcissement automatique”. Si vous exposez le Back‑Office, les endpoints AJAX, les webhooks de paiement, et l’API, vous devez durcir à plusieurs niveaux : en-têtes HTTP (HSTS, CSP, frame-ancestors), restrictions d’accès, rate limiting, et idéalement WAF. Pour les en‑têtes côté applicatif et leur impact sécurité, voir : HTTP Security Headers en PHP : guide CSP, HSTS, X-Frame-Options. Et pour une approche pragmatique anti faux positifs sur checkout : WAF PrestaShop : réduire les faux positifs et sécuriser le checkout.
Autre angle souvent ignoré : l’automatisation TLS augmente la surface “config by default”. Par exemple, si vous hébergez plusieurs vhosts sur la même instance et que vos DNS pointent mal, vous pouvez obtenir/servir un certificat sur un mauvais host avant de vous en rendre compte. En prod, verrouillez : enregistrement DNS, CAA si vous maîtrisez, et process de validation (monitoring du CN/SAN servi). Le durcissement du core PrestaShop reste indispensable (modules exposés, contrôleurs, XSS). À ce sujet : XSS : checklist de durcissement PrestaShop, CSP et encodage contexte et, si vous devez gérer une correction ciblée, Sécurité PrestaShop : corriger la CVE-2026-54159 et durcir psfacetedsearch.
Un point de méthode utile : séparez “TLS OK” et “surface d’attaque réduite”. Une boutique peut être 100% HTTPS… et rester vulnérable via un Back‑Office trop exposé, des endpoints non limités en débit, ou des modules tiers non maintenus. La migration de serveur est souvent l’occasion de faire ce tri, parce que vous repassez de toute façon sur la liste des endpoints exposés.
Performance : où FrankenPHP peut aider (et où OPcache/SQL font 80% du boulot)
Dans une stack PrestaShop, la performance “ressentie” se joue sur TTFB, cache applicatif, requêtes SQL, et payload front (images, JS/CSS, CWV). FrankenPHP peut réduire la friction d’exécution (moins de couches), mais ne corrige ni les N+1 ni les index manquants. Avant d’attribuer un gain à FrankenPHP, instrumentez : temps de génération PHP, nombre de requêtes, temps MySQL, taux de hit cache, p95/p99. Pour le cadrage e‑commerce et Core Web Vitals : PrestaShop performance : optimiser gros catalogues et Core Web Vitals.
Le levier “facile” côté PHP reste OPcache. Si vous migrez depuis FPM, vos réglages OPcache doivent être revalidés, pas recopiés aveuglément : taille du cache, interned strings, validatetimestamps, maxaccelerated_files, etc. Votre objectif est d’éviter les invalidations permanentes (CPU) et les évictions (thrash) sous charge. Référence directe : PHP OPcache : paramètres recommandés pour optimiser les performances.
Pour donner un ordre de grandeur réaliste : sur une boutique correctement cachée (pages publiques via cache HTTP/CDN, backend optimisé), les gains d’un nouveau serveur d’exécution se voient surtout sur les routes non cachables (panier, checkout, BO). Attendez-vous à des différences p95 plutôt que “moyenne” : par exemple une réduction de quelques dizaines de ms sur la partie “serveur web → PHP”, mais un écart de plusieurs centaines de ms si vous avez aussi corrigé des verrous MySQL ou un cold-start OPcache. Si vous utilisez Redis (sessions, cache), revalidez aussi le dimensionnement et la sécurité : Redis PrestaShop : configurer le cache sur VPS ou serveur dédié.
Une façon pragmatique de ne pas se tromper d’objectif est de distinguer :
- Ce qui améliore le débit (RPS) : réduction de surcoût entre couches, meilleure gestion de workers, OPcache stable.
- Ce qui améliore le temps de réponse (p95/p99) : DB plus prévisible, caches chauds, réduction des “lentes” (queries, IO disque, appels externes).
- Ce qui améliore l’expérience : poids des pages, images, cache navigateur, CDN. (FrankenPHP ne remplace pas une stratégie média et front.)
Si votre but est SEO + conversion, c’est souvent la combinaison “caching + DB + front” qui paie le plus. FrankenPHP est intéressant quand il s’intègre à une démarche de mesure (avant/après) et à un plan de remédiation (ce que vous faites si la perf se dégrade sur certains endpoints).
Exploitation : reverse proxy, haute dispo, logs, et stratégie de rollback
En production, vous aurez rarement FrankenPHP “nu” sur Internet. Un pattern fréquent : HAProxy en frontal (TLS termination, rate limiting, observabilité Prometheus) puis FrankenPHP derrière, ou l’inverse selon contraintes. Si vous êtes déjà équipés HAProxy, évitez de refaire le monde : gardez vos primitives (ACL, stick tables, restrictions IP admin) et utilisez FrankenPHP comme moteur d’exécution PHP. Référence utile pour une terminaison TLS + rate limiting propre : HAProxy reverse proxy : terminaison TLS, rate limiting et supervision Prometheus.
En haute dispo, le sujet qui revient vite avec PrestaShop n’est pas “comment scaler le binaire”, c’est l’état :
- sessions (filesystem vs Redis),
- cache (Redis, fichiers, invalidation),
- médias (uploads) : stockage local, NFS, objet, ou sync,
- tâches asynchrones (crons, workers) : une seule exécution ou exécutions parallèles contrôlées.
Si vous basculez d’un serveur unique vers plusieurs instances FrankenPHP derrière un LB, ce sont ces points-là qui déterminent si le checkout reste fiable.
Côté supervision, ce qui casse le plus souvent lors d’une migration serveur PHP n’est pas “HTTP/3”, c’est le basique : erreurs 503, saturation CPU, files d’attente, timeouts DB, disque plein (logs), et permissions sur cache. Prévoyez une boucle courte : logs JSON (Caddy), logs PHP (stderr/journald), métriques système (CPU steal, IOwait), et alerting. Pour une démarche orientée incident : Erreur HTTP 503 : diagnostic serveur, logs et ressources et PrestaShop monitoring d’erreurs : logs PHP, MySQL, JavaScript et alertes e-mail.
Une bonne pratique simple : définissez à l’avance vos SLO de migration (même “artisanaux”) sur une fenêtre courte :
- taux d’erreur 5xx max,
- TTFB p95 sur 3–5 pages typiques,
- temps de réponse sur 2–3 endpoints BO sensibles (ex. recherche, liste commandes),
- taux de succès checkout (sandbox).
Enfin, ne migrez pas “en une nuit” sans filet. Utilisez un plan blue/green ou au minimum un basculement DNS/Load Balancer avec retour arrière clair (TTL, stickiness, sessions). Les migrations PrestaShop ont assez d’inconnues (modules, overrides, comportements en BO) pour justifier une stratégie de rollback propre. Référence : Migration PrestaShop : audit technique et plan incrémental blue/green.
Le détail qui fait la différence en rollback : préparez un retour arrière “sans débat”. Par exemple : “si p95 checkout > X ms pendant 10 minutes” ou “si 5xx > Y%”, on rebascule. Ce n’est pas une question de panique, c’est un garde-fou pour éviter de brûler une journée à investiguer en live avec des clients qui payent.
Checklist de bascule FrankenPHP pour une boutique PrestaShop (interop, sécurité, SEO)
Commencez par figer un périmètre : PrestaShop (version exacte), PHP (version exacte), modules critiques (paiement, transport, facettes), et contraintes réseau (CDN, WAF, LB). Dans un runbook, notez explicitement : ports ouverts (TCP/443, UDP/443 pour HTTP/3), chemins d’écriture (cache, upload), et variables d’environnement (clé cookie, DB, mail). Tant que cette base n’est pas écrite, vous êtes en train de “tester un serveur” au lieu de “valider une exploitation”.
Ensuite, validez en staging avec des scénarios reproductibles et mesurables : (1) crawl de pages catégories/produits (statuts HTTP, canonical, temps), (2) checkout complet (paiement sandbox), (3) import (CSV), (4) BO (indexation, recherche, modules). Mesurez au minimum : TTFB p95, taux d’erreur 5xx, temps MySQL, hit ratio OPcache. Pour le volet indexation/SEO et éviter de générer des pages incohérentes, gardez un œil sur les fondamentaux (sitemap, statuts, contenu servi) — voir : Plan de site : optimiser l’indexation Google avec un sitemap clair et, si vous déployez IndexNow côté e‑commerce : IndexNow : intégration PrestaShop et stratégie d’indexation pour e-commerce.
Pour éviter les “surprises SEO” lors de la bascule, ajoutez ces contrôles rapides (souvent oubliés) :
- Statuts HTTP sur un échantillon d’URLs (home, catégories profondes, produits, pages CMS, images) : pas de 302/301 inattendus, pas de 404 sur assets.
- En-têtes de cache : ne pas rendre le checkout cachable par erreur (proxy/CDN), ne pas casser les statiques (cache trop court).
- Canonical et robots : vérifier que l’environnement prod ne sert pas un
noindexrésiduel de staging.
Enfin, terminez par la sécurité “opérationnelle” : rotation/stockage des secrets, limitation d’accès au BO (IP allowlist/VPN), rate limiting sur endpoints sensibles, et tests de régression sur les modules exposés. Le cœur PrestaShop n’est pas magique : une meilleure stack serveur ne corrige pas les défauts applicatifs (XSS, accès cassés, IDOR). Si vous voulez une checklist transversale, recoupez avec : Broken access control : prévenir IDOR et élévation de privilèges et Sécurité PrestaShop : plan de réponse à incident et containment immédiat. À ce stade, FrankenPHP devient un choix rationnel (simplicité d’exploitation + HTTP/3 + TLS automatisé), pas un pari.
