Clever Cloud PHP : déployer avec Apache, PHP-FPM et CC_WEBROOT

Guide pratique pour déployer PHP sur Clever Cloud — Apache + PHP‑FPM, configuration CC_WEBROOT, bonnes pratiques de performance, déploiement et dépannage.

Écran affichant du code et des configurations PHP pour le déploiement web.

Table des matières :

  1. Stack d’exécution Clever Cloud pour PHP : Apache en frontal, PHP-FPM en backend
  2. CC_WEBROOT : contrôler le DocumentRoot sans casser vos rewrites
  3. Apache ↔ PHP-FPM : configuration, performance et limites sur une PaaS
  4. Déploiement reproductible : composer, assets, variables d’environnement et tâches post-build
  5. Observabilité et dépannage : logs, erreurs 403/500, “page blanche” et validation prod

Stack d’exécution Clever Cloud pour PHP : Apache en frontal, PHP-FPM en backend

Sur Clever Cloud, une application PHP « standard » s’exécute classiquement avec Apache HTTPD en frontal et PHP-FPM derrière, via FastCGI. Ça ressemble beaucoup à une archi “Apache + php-fpm” sur VM, sauf que vous n’avez pas la main sur le VirtualHost (DocumentRoot, MPM, modules) autrement que par les conventions de dépôt et quelques variables d’environnement exposées par la plateforme. Autrement dit : si votre appli suppose que vous pouvez éditer 000-default.conf, ce n’est pas le bon niveau d’abstraction.

Le point clé est le chemin de résolution : requête HTTP → Apache (TLS, compression, règles de réécriture) → passerelle FastCGI → pool PHP-FPM (workers) → application (framework, PrestaShop, scripts). Si vous voulez réviser précisément ce pipeline, l’article interne “PHP-FPM : comprendre le flux d’exécution avec Nginx et Apache” est une bonne base pour recaler les responsabilités entre serveur web, FastCGI et SAPI PHP.

Côté définition, PHP-FPM n’est pas “juste” un mode d’exécution ; c’est un gestionnaire de processus et de pools. La doc PHP le résume sans détour : “PHP-FPM is an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites.” (PHP Manual – PHP-FPM). En pratique, cette phrase a des conséquences directes sur Clever Cloud : votre capacité de concurrence est bornée par pm.max_children (ou l’équivalent géré par la plateforme) et par la manière dont Apache multiplexe les connexions.

Deux implications pratiques (souvent sous-estimées) quand vous passez d’une VM “à vous” à une PaaS :

  • Vous raisonnez en “contrats” plutôt qu’en réglages : par exemple, vous ne “tunez” pas Apache, mais vous pouvez rendre votre application plus tolérante (timeouts applicatifs cohérents, requêtes SQL plus courtes, pages cacheables).
  • La variabilité devient un paramètre : un même code peut être “OK” en charge légère, puis s’écrouler quand la file d’attente PHP-FPM se remplit. D’où l’intérêt de mesurer (TTFB, taux de 5xx, durée moyenne des requêtes) et d’avoir un plan clair de diagnostic (section observabilité plus bas).

Enfin, un point “GEO” qui compte vraiment (sans tomber dans la sur-promesse) : la proximité régionale entre vos utilisateurs et la zone d’hébergement réduit la latence réseau “incompressible” et simplifie la conformité (ex. hébergement au sein de l’UE pour un e-commerce ciblant majoritairement des clients européens). Ce n’est pas une recette miracle de performance, mais c’est un facteur de base : avant d’optimiser le micro-temps CPU, évitez d’ajouter des dizaines de millisecondes de RTT inutilement.

CC_WEBROOT : contrôler le DocumentRoot sans casser vos rewrites

CC_WEBROOT est la variable qui évite le grand classique : dépôt Git à la racine, mais vrai point d’entrée HTTP dans un sous-dossier (typiquement public/ pour Symfony/Laravel modernes). Sur une PaaS où vous ne pouvez pas modifier le VirtualHost, CC_WEBROOT sert à demander à la plateforme de poser le DocumentRoot ailleurs que la racine du repo. En clair : vous versionnez tout, mais vous n’exposez au web que le sous-répertoire censé contenir index.php.

Concrètement, si votre projet suit un layout type :

.
├── public/
│   ├── index.php
│   └── .htaccess
├── src/
├── vendor/
└── composer.json

alors CC_WEBROOT=public est le réglage “propre”. Vous évitez d’exposer des artefacts sensibles (composer.json, .env, scripts d’admin, dumps) et vous réduisez la surface d’attaque. Ce n’est pas un “bonus sécurité” : c’est un minimum, surtout si votre projet embarque des fichiers qui ne doivent jamais être servis statiquement.

Rewrites : le détail qui casse (ou sauve) un déploiement

Quand vous changez le webroot, deux familles de problèmes apparaissent :

  • Les règles de réécriture ne sont plus au bon endroit : le .htaccess doit être dans le répertoire effectivement servi (donc dans public/ si CC_WEBROOT=public). Un .htaccess resté à la racine ne sera souvent jamais lu.
  • Les chemins relatifs changent : ce qui fonctionnait avec une arborescence “à plat” (ex. RewriteBase /) peut devenir incohérent.

Un socle de rewrite “front controller” (classique Symfony/Laravel) ressemble souvent à ceci (à adapter à votre framework) :

RewriteEngine On

# Ne pas réécrire les fichiers/dossiers existants
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# Tout le reste vers l'index.php
RewriteRule ^ index.php [QSA,L]

Même si vous n’avez pas la main sur le VirtualHost, ces règles suffisent généralement à valider que CC_WEBROOT pointe bien au bon endroit : si les assets statiques passent et que les routes “propres” (sans .php) retombent sur index.php, vous avez le bon couple “webroot + rewrite”.

Attention aux applis qui génèrent (ou attendent) des fichiers à la racine. PrestaShop est un bon exemple d’écosystème où le “public/” n’est pas un standard historique : le core s’attend à des chemins /img, /themes, /modules, et à une .htaccess à la racine pour les réécritures. Déplacer le webroot vers public/ pour PrestaShop n’est pas un scénario supporté “nativement” : vous allez vous heurter aux chemins hardcodés, à la génération de .htaccess, et au back-office (/adminXXXX) qui suppose une topologie précise. Si votre cible est PrestaShop 9 (PHP 8.3), partez d’abord sur un déploiement “à plat” (webroot = racine) et gardez CC_WEBROOT=. ; le guide interne “PrestaShop 9 : guide de migration Symfony 6.4 et PHP 8.3” rappelle bien les contraintes de versions et d’architecture à respecter avant d’ajouter des variantes.

Checklist rapide avant de toucher CC_WEBROOT :

  • Le dossier cible contient bien index.php (ou votre front controller).
  • Le .htaccess est dans le dossier servi (pas “à côté”).
  • Les assets (CSS/JS/images) sont référencés correctement (chemins absolus/relatifs cohérents).
  • Les URLs réécrites (ex. /produit/slug) répondent sans boucles de redirection.

Apache ↔ PHP-FPM : configuration, performance et limites sur une PaaS

Le chaînage Apache → FPM passe souvent par mod_proxy_fcgi. Côté Apache, la doc est explicite : mod_proxy_fcgi “implements a proxy/gateway for FastCGI” (Apache mod_proxy_fcgi documentation). Ce module est la charnière : il décide quand Apache délègue à FPM, comment il gère les timeouts, et comment il traite les erreurs (502/504 typiquement). Sur Clever Cloud, vous ne “configurez” pas ce module au sens sysadmin, mais vous devez raisonner avec ses effets : une latence FPM devient une latence HTTP.

En termes de performance, la variable déterminante est le dimensionnement de concurrence : un worker FPM traite une requête PHP à la fois (modèle classique). Si vous saturez max_children, Apache va continuer à accepter des connexions (selon MPM, keep-alive, file descriptors), mais les requêtes PHP vont s’empiler et votre TTFB explose. Sur PrestaShop, c’est particulièrement visible sur les endpoints lourds (panier, checkout, recherche interne) et sur les hooks de modules mal maîtrisés. Avant d’incriminer l’hébergeur, faites le travail côté code : profiling SQL, cache, réduction des requêtes redondantes. L’article “Optimisation PrestaShop : accélérer pages produit et panier” est un bon rappel des goulets d’étranglement classiques.

Un repère opérationnel utile pour “penser” la capacité FPM sans sur-ingénierie :

  • Si une page critique met 400 ms de PHP “net” (hors réseau) et que vous avez N workers, vous pouvez servir au mieux ~N / 0,4 requêtes PHP/seconde sur ce type de page, avant que la file d’attente n’augmente.
    Ce n’est pas une formule scientifique (il y a de l’I/O, de la variabilité), mais c’est un bon outil mental pour comprendre pourquoi une optimisation qui fait passer une page de 800 ms à 400 ms “double” souvent la capacité ressentie.

Dans une PaaS, la limite n’est pas seulement CPU/RAM : c’est la capacité de configuration. Vous ne choisirez pas librement MPM event vs prefork, ni les valeurs exactes de ProxyTimeout, ni l’activation de modules Apache “exotiques”. Ce qui reste généralement dans votre contrôle : (1) la structure du repo (donc CC_WEBROOT), (2) les règles .htaccess si AllowOverride est activé, (3) les paramètres PHP ajustables via mécanismes supportés (fichier d’ini local, variables d’env selon plateforme), (4) le code (OPcache-friendly, autoload optimisé, caches applicatifs). Pour comparer avec une maîtrise totale sur une machine, la lecture “serveur dédié” donne un contraste utile : “Serveur dédié PrestaShop : config Nginx PHP-FPM MariaDB Redis”.

À garder en tête : sur une PaaS, “performance” = moins de travail par requête + moins de requêtes dynamiques. Deux leviers concrets et souvent gagnants sans toucher au serveur :

  • Cache HTTP / cache applicatif (quand c’est compatible métier) : réduire le nombre de hits PHP-FPM.
  • Optimiser l’autoload et l’OPcache : un composer dump-autoload -o (ou --optimize-autoloader) et un code “OPcache-friendly” évitent des surcoûts invisibles mais réels en prod.

Déploiement reproductible : composer, assets, variables d’environnement et tâches post-build

Le déploiement Clever Cloud le plus sain reste Git + build déterministe : vous poussez un commit, la plateforme reconstruit, puis bascule. Pour un projet PHP moderne (Symfony/Laravel), l’objectif est simple : composer install --no-dev --prefer-dist --optimize-autoloader doit produire le même résultat à chaque build, et les assets doivent être compilés de manière reproductible (Node/Yarn/PNPM selon stack). Si vous faites du “vendor commité” ou du build à la main avant push, vous perdez la traçabilité et vous rendez le rollback pénible.

Pour rendre ce principe réellement opérant, adoptez une logique “build artifact” :

  • Tout ce qui dépend de l’environnement (secrets, endpoints, clés) doit être injecté au runtime via variables d’environnement.
  • Tout ce qui dépend du code (vendor PHP, assets compilés, classes optimisées) doit être généré par le build.

Pour PrestaShop, c’est plus rugueux : le core et les modules sont souvent livrés “à plat”, avec des étapes d’install/upgrade qui écrivent dans le filesystem (/var/cache, /img, /modules, génération .htaccess). Sur PaaS, vous devez être strict sur la séparation : code immutable vs données persistantes. Les images produits et médias ne devraient pas dépendre d’un disque local “par chance” : externalisez (Object Storage/S3 compatible) ou montez une solution persistante si la plateforme le propose. Un PrestaShop qui écrit ses assets sur un FS non pérenne, c’est la recette pour un incident “après redéploiement” (images manquantes, cache incohérent, classes recompilées). Si vous mettez en place une chaîne CI, l’article “PrestaShop CI/CD : générer des démos à la demande en minutes” donne des patterns concrets de builds isolés et jetables.

La partie “variables d’environnement” est souvent sous-estimée. Sur Clever Cloud, vous allez typiquement définir : APP_ENV, secrets (DB, SMTP, API), et CC_WEBROOT. Deux règles pragmatiques : (1) ne stockez aucun secret en clair dans le repo ; (2) gardez un inventaire des vars et de leur portée (build vs runtime). Si vous gérez des APIs côté PrestaShop (Admin API, webservices), la moindre fuite de secret devient un incident. Voir aussi “PrestaShop Admin API : sécuriser secret et scopes par client” pour une approche propre des secrets et de l’isolement.

Pour cadrer les bonnes pratiques “secrets” de façon vendor-agnostic, la ressource la plus utile (et concrète) est le OWASP Secrets Management Cheat Sheet. Elle aide à formaliser ce qui doit être en variable d’environnement, en coffre, en rotation, et ce qui ne doit jamais se retrouver dans les logs.

Enfin, côté “tâches post-build”, restez minimaliste : si une tâche doit absolument s’exécuter après déploiement (ex. warmup de cache Symfony, migration contrôlée), documentez-la et rendez-la idempotente (exécutable plusieurs fois sans dégâts). Sur e-commerce, privilégiez des déploiements qui ne bloquent pas le front (pas de “longues migrations” surprise pendant les heures de vente).

Observabilité et dépannage : logs, erreurs 403/500, “page blanche” et validation prod

Avec Apache + PHP-FPM, vos incidents se lisent en général sur trois couches de logs : (1) accès HTTP (codes, latence), (2) erreurs Apache (rewrite loop, fichier interdit, 404/403), (3) erreurs PHP/FPM (fatal error, memory limit, timeout). Sur Clever Cloud, le point critique est d’avoir un flux de logs exploitable et centralisé (même si c’est “juste” pour la corrélation temporelle). Si vous avez déjà une stack logs, l’article “OVHcloud Managed OpenSearch : moteur NoSQL managé pour logs et recherche” est un bon guide pour structurer index, rétention et recherches (même si le fournisseur diffère).

Une façon simple d’accélérer le dépannage est de classer les symptômes “HTTP” en causes probables, puis de remonter couche par couche :

Symptôme côté navigateur Cause fréquente Où regarder en premier
404 sur toutes les routes CC_WEBROOT faux / front controller introuvable accès HTTP + arborescence du repo
403 immédiat fichier/dossier interdit, règle .htaccess, permissions logs Apache (error) + .htaccess
502/504 intermittents FPM saturé, timeout FastCGI, requête trop lente logs PHP/FPM + métriques de latence
“Page blanche” (200 mais vide) fatal error masqué / exception non affichée logs PHP + config prod (display_errors)

Deux erreurs reviennent quand on joue avec CC_WEBROOT : 403 et 404. La 404 est souvent un mauvais webroot (Apache pointe sur un dossier sans index.php). Le 403 est plus subtil : permissions, règles Apache, ou .htaccess trop agressif (ex : Require all denied au mauvais endroit). Avant de tout casser, appliquez une méthode stricte : reproduire sur un endpoint statique, vérifier la présence des fichiers, inspecter les règles de rewrite. Vous avez une checklist détaillée dans “Erreur 403 Forbidden : causes et dépannage étape par étape”.

La “page blanche” côté PrestaShop est rarement un mystère, c’est juste un fatal error masqué par la config d’affichage (production) ou par une rupture de cache (Smarty / Symfony / class index). Les symptômes typiques en PaaS : module incompatible avec la version PHP du runtime, limite mémoire trop basse, ou exécution concurrente qui fait tomber un lock. Ne perdez pas de temps à cliquer : activez le logging, récupérez la stack trace, et isolez la régression par commit. L’article “PrestaShop page blanche : diagnostiquer l’erreur fatale PHP rapidement” donne une procédure courte et orientée prod.

Enfin, valider un déploiement Apache/PHP-FPM sur Clever Cloud ne se résume pas à “la home répond”. Ajoutez une validation minimale : (1) endpoint de santé (200 + check DB), (2) test de réécriture (URL friendly), (3) contrôle TLS/headers (HSTS si applicable), (4) mesures TTFB et timeouts sur pages critiques, (5) audit des redirections (301/302) et canonical si e-commerce. Pour le volet HTTPS, votre référence interne “HTTPS SEO : bonnes pratiques, certificats SSL et audit technique” évite les erreurs habituelles (mixed content, chaînes de redirections, HSTS mal posé).

Une bonne pratique “terrain” (particulièrement utile en contexte multi-boutiques ou trafic national) : faites vos tests de validation depuis la zone géographique principale de vos clients, ou via une sonde proche. Un déploiement peut sembler sain depuis votre poste, puis révéler une latence/perte réseau différente en production selon la région — surtout si vous agrégerez des dépendances externes (paiement, marketplace, CDN, API transporteurs).

Liens externes utiles (docs officielles)


À lire aussi