Pour moderniser une installation Apache utilisant encore mod_php, installez PHP-FPM, désactivez MPM Prefork, puis activez MPM Event avec mod_proxy_fcgi. Apache continue de servir les requêtes HTTP, tandis que PHP-FPM exécute séparément le code PHP.
Cette architecture convient aux serveurs Debian et Ubuntu qui hébergent WordPress, WooCommerce ou d’autres applications PHP. Elle remplace les anciennes configurations fondées sur mod_fastcgi, mod_fcgid ou un module PHP chargé directement dans Apache.
La migration reste assez simple. Cependant, elle touche au moteur d’exécution PHP de tous les sites concernés. Effectuez-la avec une seconde session SSH ouverte, une sauvegarde de la configuration et une procédure de retour arrière prête à l’emploi.
Comprendre Apache, les MPM et PHP-FPM
Apache utilise un module de multitraitement, ou MPM, pour accepter et distribuer les connexions. Une seule implémentation MPM peut être active à la fois.
MPM Prefork
MPM Prefork utilise plusieurs processus sans threads. Chaque processus traite une requête à la fois. Cette architecture reste compatible avec les modules non thread-safe, notamment l’ancien mod_php.
Elle consomme toutefois davantage de mémoire lorsque le nombre de connexions augmente. Chaque processus Apache charge aussi les modules nécessaires, même lorsqu’il sert uniquement une image, une feuille CSS ou un autre fichier statique.
MPM Worker
MPM Worker combine plusieurs processus avec plusieurs threads par processus. Il utilise généralement moins de mémoire que Prefork pour servir un nombre équivalent de connexions.
Worker reste disponible, mais il ne constitue plus le meilleur choix général pour une nouvelle configuration Apache destinée au web.
MPM Event
MPM Event dérive de Worker. Il délègue notamment les connexions persistantes inactives à des threads d’écoute, afin de libérer les threads de travail pour les requêtes actives.
Cette architecture convient mieux à HTTP/1.1 avec Keep-Alive et aux protocoles modernes. Elle constitue donc le choix recommandé pour Apache lorsque PHP fonctionne séparément avec PHP-FPM.
Pourquoi utiliser PHP-FPM avec Apache ?
PHP-FPM, pour FastCGI Process Manager, exécute PHP dans un service distinct. Apache lui transmet uniquement les requêtes qui doivent réellement être interprétées par PHP.
Cette séparation apporte plusieurs avantages :
- Apache peut utiliser MPM Event au lieu de Prefork ;
- les processus PHP disposent de leurs propres limites de mémoire et de concurrence ;
- plusieurs versions de PHP peuvent cohabiter sur un même serveur ;
- chaque site peut utiliser un pool PHP-FPM distinct ;
- les pools peuvent fonctionner sous des utilisateurs système différents ;
- les scripts lents peuvent être enregistrés dans un journal dédié ;
- PHP peut être redémarré sans interrompre entièrement Apache ;
- la configuration se rapproche de celle utilisée avec Nginx.
PHP-FPM ne rend pas automatiquement une application PHP plus rapide. Les performances dépendent surtout du code, de la base de données, d’OPcache, du cache de page et du dimensionnement des processus. En revanche, cette architecture améliore la maîtrise des ressources et la capacité du serveur à absorber plusieurs connexions simultanées.
Architecture obtenue après la migration
Une fois la migration terminée, le chemin d’une requête PHP devient :
Navigateur
↓
Apache avec MPM Event
↓
mod_proxy + mod_proxy_fcgi
↓
socket Unix PHP-FPM
↓
processus PHP-FPM
↓
application PHP ou WordPress
Les fichiers statiques ne passent pas par PHP-FPM :
Navigateur
↓
Apache avec MPM Event
↓
image, CSS, JavaScript, police ou document statiqueLangage du code : JavaScript (javascript)
Prérequis avant de modifier Apache
Cette procédure suppose que :
- Apache 2.4 fonctionne déjà ;
- PHP est actuellement exécuté avec
mod_php, ou PHP-FPM n’est pas encore correctement activé ; - le serveur utilise Debian ou Ubuntu ;
- vous disposez d’un accès SSH avec
sudo; - vous pouvez tester tous les sites après la modification ;
- vous connaissez les éventuels modules Apache tiers installés.
Gardez la session SSH actuelle ouverte. Ouvrez également une seconde session avant de redémarrer Apache. Cette précaution évite qu’une coupure locale ou une erreur de terminal ne vous laisse sans accès pendant le diagnostic.
1. Relever la configuration actuelle
Commencez par identifier la version d’Apache :
apache2ctl -v
Affichez ensuite le MPM actif :
apache2ctl -V | grep -i 'Server MPM'Langage du code : JavaScript (javascript)
Sur une installation utilisant mod_php, le résultat indique généralement :
Server MPM: prefork
Vous pouvez aussi demander la liste des modules chargés :
apache2ctl -M | grep -E 'mpm_|php|proxy|fcgi|http2'Langage du code : JavaScript (javascript)
Une ancienne pile peut notamment afficher :
mpm_prefork_module
php_module
Relevez enfin les paquets PHP installés :
dpkg -l | grep -E '^ii\s+(php[0-9.]*|libapache2-mod-php)'Langage du code : JavaScript (javascript)
2. Détecter la version PHP utilisée
Le binaire PHP en ligne de commande permet d’obtenir la version principale et mineure :
PHP_VERSION="$(php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;')"
printf 'Version PHP détectée : %s\n' "${PHP_VERSION}"Langage du code : JavaScript (javascript)
Vérifiez que cette version correspond bien à celle attendue pour les sites. Le PHP utilisé en ligne de commande peut différer de celui chargé par Apache lorsqu’un serveur héberge plusieurs versions.
Listez tous les services PHP-FPM connus de systemd :
systemctl list-unit-files 'php*-fpm.service'Langage du code : PHP (php)
3. Sauvegarder la configuration
Créez une archive de la configuration Apache et PHP avant toute modification :
BACKUP_DIR="/root/apache-php-backup-$(date +%F-%H%M%S)"
sudo mkdir -p "${BACKUP_DIR}"
sudo cp -a /etc/apache2 "${BACKUP_DIR}/"
sudo cp -a /etc/php "${BACKUP_DIR}/"
printf 'Sauvegarde créée dans : %s\n' "${BACKUP_DIR}"Langage du code : JavaScript (javascript)
Contrôlez également la syntaxe Apache avant de commencer. Une erreur déjà présente compliquerait inutilement le diagnostic :
sudo apache2ctl configtest
Le résultat attendu est :
Syntax OK
4. Installer PHP-FPM
Mettez à jour l’index des paquets, puis installez le paquet FPM correspondant à la version détectée :
sudo apt update
sudo apt install "php${PHP_VERSION}-fpm"Langage du code : JavaScript (javascript)
Si votre distribution fournit uniquement le méta-paquet php-fpm, vous pouvez utiliser :
sudo apt install php-fpm
Le paquet versionné reste préférable sur un serveur qui héberge plusieurs versions PHP. Il rend la version ciblée explicite.
Activez et démarrez le service :
sudo systemctl enable --now "php${PHP_VERSION}-fpm.service"Langage du code : JavaScript (javascript)
Vérifiez son état :
sudo systemctl status "php${PHP_VERSION}-fpm.service" --no-pagerLangage du code : JavaScript (javascript)
Le service doit apparaître comme actif :
Active: active (running)Langage du code : HTTP (http)
5. Vérifier le socket PHP-FPM
Sur Debian et Ubuntu, le pool par défaut écoute généralement sur un socket Unix situé dans /run/php/.
Affichez la directive effective :
grep -RHE '^[[:space:]]*listen[[:space:]]*=' \
"/etc/php/${PHP_VERSION}/fpm/pool.d/"Langage du code : JavaScript (javascript)
Le pool par défaut devrait indiquer une valeur proche de :
listen = /run/php/php8.x-fpm.sockLangage du code : JavaScript (javascript)
Vérifiez que le socket existe réellement :
sudo ls -lah "/run/php/php${PHP_VERSION}-fpm.sock"Langage du code : JavaScript (javascript)
Vous pouvez aussi afficher tous les sockets PHP présents :
sudo find /run/php -maxdepth 1 -type s -ls
Ne modifiez pas arbitrairement le socket si celui fourni par le paquet convient. Une configuration simple et conforme à la distribution résiste mieux aux mises à jour.
6. Vérifier la configuration PHP-FPM
Validez la syntaxe avant d’intégrer PHP-FPM à Apache :
Un projet WordPress en tête ?
Vous avez une idée claire de ce que vous voulez, mais pas les ressources en interne pour le faire bien. Je développe des sites et extensions WordPress sur-mesure — sans délais à rallonge ni mauvaises surprises.
Décrivez-moi votre projet →sudo "php-fpm${PHP_VERSION}" -tLangage du code : JavaScript (javascript)
Selon le paquet installé, le binaire peut aussi utiliser une autre forme. Retrouvez-le avec :
command -v "php-fpm${PHP_VERSION}" ||
find /usr/sbin -maxdepth 1 -name 'php-fpm*' -type fLangage du code : JavaScript (javascript)
Après toute modification d’un pool, rechargez PHP-FPM plutôt que de le redémarrer brutalement :
sudo systemctl reload "php${PHP_VERSION}-fpm.service"Langage du code : JavaScript (javascript)
7. Activer la configuration Apache fournie par PHP-FPM
Les paquets Debian et Ubuntu fournissent généralement une configuration Apache nommée selon la version de PHP :
ls -l "/etc/apache2/conf-available/php${PHP_VERSION}-fpm.conf"Langage du code : JavaScript (javascript)
Activez cette configuration :
sudo a2enconf "php${PHP_VERSION}-fpm"Langage du code : JavaScript (javascript)
Elle associe les fichiers PHP au socket PHP-FPM avec un gestionnaire FastCGI. Cette méthode évite de répéter une directive FilesMatch dans chaque hôte virtuel lorsque tous les sites utilisent la même version PHP.
8. Désactiver mod_php et MPM Prefork
MPM Event ne peut pas être activé tant que le module Apache mod_php impose MPM Prefork.
Désactivez d’abord le module PHP correspondant :
sudo a2dismod "php${PHP_VERSION}"Langage du code : JavaScript (javascript)
Si cette commande indique que le module n’existe pas, listez les modules PHP disponibles :
find /etc/apache2/mods-enabled \
-maxdepth 1 \
-type l \
-name 'php*.load' \
-printf '%f\n'Langage du code : JavaScript (javascript)
Désactivez ensuite MPM Prefork :
sudo a2dismod mpm_prefork
Ne redémarrez pas encore Apache. Activez d’abord le nouveau MPM et les modules FastCGI.
9. Activer MPM Event et mod_proxy_fcgi
Activez MPM Event, le proxy Apache et son support FastCGI :
sudo a2enmod mpm_event proxy proxy_fcgi setenvif
Le module mod_proxy_fcgi ne démarre pas lui-même PHP. Il transmet les requêtes au service PHP-FPM, qui doit donc fonctionner indépendamment.
Vous n’avez pas besoin d’activer proxy_http pour cette communication locale avec PHP-FPM. Surtout, ne configurez pas Apache comme proxy ouvert.
10. Activer HTTP/2 lorsque le site utilise HTTPS
MPM Event permet également d’utiliser proprement le module HTTP/2 d’Apache sans dépendre de MPM Prefork.
sudo a2enmod http2
Dans chaque hôte virtuel HTTPS concerné, vous pouvez déclarer :
Protocols h2 http/1.1
Exemple minimal :
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
Protocols h2 http/1.1
<Directory /var/www/example.com/public_html>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>Langage du code : HTML, XML (xml)
La configuration TLS, les certificats et les journaux ont été omis pour garder l’exemple lisible.
11. Valider la configuration avant le redémarrage
Contrôlez d’abord PHP-FPM :
sudo systemctl is-active "php${PHP_VERSION}-fpm.service"Langage du code : JavaScript (javascript)
Puis vérifiez Apache :
sudo apache2ctl configtest
Affichez également les hôtes virtuels interprétés par Apache :
sudo apache2ctl -S
Cette commande aide à repérer un nom de domaine rattaché au mauvais fichier de configuration, un doublon de ServerName ou un hôte virtuel par défaut inattendu.
12. Redémarrer Apache
Lorsque les deux validations réussissent, redémarrez Apache :
sudo systemctl restart apache2
Vérifiez immédiatement les deux services :
sudo systemctl --no-pager --full status apache2
sudo systemctl --no-pager --full status "php${PHP_VERSION}-fpm.service"Langage du code : JavaScript (javascript)
Si Apache ne redémarre pas, consultez les journaux avant de multiplier les modifications :
sudo journalctl -u apache2 -n 100 --no-pager
sudo journalctl -u "php${PHP_VERSION}-fpm.service" -n 100 --no-pagerLangage du code : JavaScript (javascript)
13. Vérifier que MPM Event est actif
Demandez à Apache quel MPM il utilise maintenant :
apache2ctl -V | grep -i 'Server MPM'Langage du code : JavaScript (javascript)
Le résultat attendu est :
Server MPM: event
Vérifiez ensuite les modules utiles :
apache2ctl -M | grep -E 'mpm_|proxy|fcgi|php|http2'Langage du code : JavaScript (javascript)
Vous devez retrouver au minimum :
mpm_event_module
proxy_module
proxy_fcgi_module
setenvif_module
Le module php_module ne doit plus apparaître.
14. Vérifier que PHP passe bien par PHP-FPM
Créez temporairement un fichier de test dans la racine publique d’un site :
printf '%s\n' '<?php phpinfo();' |
sudo tee /var/www/example.com/public_html/phpinfo.php > /dev/nullLangage du code : JavaScript (javascript)
Ouvrez ensuite :
https://example.com/phpinfo.phpLangage du code : JavaScript (javascript)
La ligne Server API doit indiquer :
FPM/FastCGI
Supprimez immédiatement le fichier après le test. Une page phpinfo() révèle de nombreuses informations sur le serveur :
sudo rm -- /var/www/example.com/public_html/phpinfo.phpLangage du code : JavaScript (javascript)
Vous pouvez aussi tester localement sans dépendre du DNS public :
curl \
--resolve example.com:443:127.0.0.1 \
--insecure \
--head \
https://example.com/Langage du code : JavaScript (javascript)
Configurer PHP-FPM par hôte virtuel
La configuration globale fournie par Debian suffit lorsque tous les sites utilisent le même pool PHP-FPM. Toutefois, un serveur multisite gagne souvent à utiliser un pool distinct pour chaque site.
Cette isolation permet notamment :
- d’exécuter chaque site sous un utilisateur dédié ;
- d’attribuer des limites de mémoire et de processus différentes ;
- d’identifier plus facilement le site qui consomme les ressources ;
- d’utiliser plusieurs versions PHP ;
- de limiter l’impact d’une compromission entre les sites.
Créer un utilisateur système dédié
sudo adduser \
--system \
--group \
--home /var/www/example.com \
--no-create-home \
exampleLangage du code : JavaScript (javascript)
Adaptez ensuite les propriétaires des fichiers. Ne changez pas aveuglément toutes les permissions d’un site sans comprendre son déploiement actuel.
Créer le pool PHP-FPM
Créez le fichier suivant :
sudo nano "/etc/php/${PHP_VERSION}/fpm/pool.d/example.conf"Langage du code : JavaScript (javascript)
Utilisez une configuration de départ prudente :
[example]
user = example
group = example
listen = /run/php/php-example.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 500
request_terminate_timeout = 120s
request_slowlog_timeout = 5s
slowlog = /var/log/php${PHP_VERSION}-fpm-example-slow.log
catch_workers_output = yes
php_admin_value[error_log] = /var/log/php${PHP_VERSION}-fpm-example-error.log
php_admin_flag[log_errors] = on
php_admin_value[upload_tmp_dir] = /var/www/example.com/tmp
php_admin_value[session.save_path] = /var/www/example.com/tmpLangage du code : JavaScript (javascript)
Les valeurs de pm.max_children et des processus de réserve ne sont que des points de départ. Elles doivent être adaptées à la mémoire réellement consommée par les processus PHP du site.
Créez les répertoires et fichiers de journal nécessaires :
sudo install \
--directory \
--owner=example \
--group=example \
--mode=0750 \
/var/www/example.com/tmp
sudo touch \
"/var/log/php${PHP_VERSION}-fpm-example-slow.log" \
"/var/log/php${PHP_VERSION}-fpm-example-error.log"
sudo chown example:example \
"/var/log/php${PHP_VERSION}-fpm-example-slow.log" \
"/var/log/php${PHP_VERSION}-fpm-example-error.log"
sudo chmod 0640 \
"/var/log/php${PHP_VERSION}-fpm-example-slow.log" \
"/var/log/php${PHP_VERSION}-fpm-example-error.log"Langage du code : JavaScript (javascript)
Associer le pool à l’hôte virtuel
Désactivez la configuration PHP-FPM globale pour cet hôte si nécessaire, puis ajoutez le gestionnaire dans le bloc VirtualHost :
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
Protocols h2 http/1.1
<Directory /var/www/example.com/public_html>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<FilesMatch "\.php$">
SetHandler "proxy:unix:/run/php/php-example.sock|fcgi://localhost/"
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>Langage du code : HTML, XML (xml)
Le séparateur vertical placé après le chemin du socket fait partie de la syntaxe de SetHandler. Il ne s’agit pas d’un tube shell.
Validez et rechargez les services :
sudo "php-fpm${PHP_VERSION}" -t
sudo apache2ctl configtest
sudo systemctl reload "php${PHP_VERSION}-fpm.service"
sudo systemctl reload apache2Langage du code : JavaScript (javascript)
Faut-il utiliser un socket Unix ou un port TCP ?
Pour Apache et PHP-FPM installés sur le même serveur, un socket Unix constitue généralement le choix le plus simple :
listen = /run/php/php-example.sockLangage du code : JavaScript (javascript)
Il évite d’ouvrir un port réseau et utilise les permissions du système de fichiers pour contrôler l’accès.
Un port TCP peut devenir utile lorsque PHP-FPM fonctionne dans un conteneur, sur une autre machine ou dans une architecture distribuée :
listen = 127.0.0.1:9000
Dans ce cas, limitez l’écoute à une interface locale ou privée. N’exposez jamais PHP-FPM directement à Internet.
Dimensionner pm.max_children correctement
pm.max_children limite le nombre maximal de requêtes PHP pouvant être exécutées simultanément par un pool. Chaque processus PHP-FPM ne traite qu’une requête à la fois.
Une valeur trop basse provoque une file d’attente et des messages indiquant que le pool a atteint sa limite. Une valeur trop haute peut épuiser la mémoire et déclencher le tueur OOM du noyau.
Mesurer la mémoire moyenne d’un processus
Après avoir généré une charge représentative, mesurez la mémoire RSS des processus du pool :
ps \
--no-headers \
-o rss,cmd \
-C "php-fpm${PHP_VERSION}" |
awk '
/pool example/ {
sum += $1;
count++;
}
END {
if (count > 0) {
printf "Processus : %d\n", count;
printf "RSS moyen : %.1f Mio\n", sum / count / 1024;
} else {
print "Aucun processus du pool trouvé.";
}
}
'Langage du code : PHP (php)
Le RSS partagé ne constitue pas une mesure parfaite de la mémoire réellement unique. Il donne néanmoins une estimation prudente pour le dimensionnement initial.
Calculer une première limite
La formule simplifiée est :
pm.max_children =
mémoire réservée au pool /
mémoire moyenne d’un processus PHP
Par exemple, si vous réservez 2 Gio au pool et qu’un processus consomme environ 100 Mio :
2048 / 100 = 20,48
Une première valeur de 18 à 20 processus laisserait une marge raisonnable. Cependant, la mémoire doit aussi couvrir Apache, MySQL ou MariaDB, Redis, le système, les sauvegardes et les autres pools PHP-FPM.
Ne prenez donc jamais toute la mémoire disponible pour PHP-FPM. Le serveur apprécie rarement qu’on lui retire jusqu’à sa dernière chaise.
Choisir le mode de gestion des processus PHP-FPM
PHP-FPM propose trois principaux modes de gestion des processus.
Mode dynamic
pm = dynamic
PHP-FPM conserve plusieurs processus prêts et ajuste leur nombre selon la charge. Ce mode convient à la plupart des sites avec un trafic régulier ou variable.
Mode ondemand
pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 10s
Les processus démarrent lorsqu’une requête arrive, puis s’arrêtent après une période d’inactivité. Ce mode économise de la mémoire sur un serveur hébergeant de nombreux petits sites peu fréquentés.
En contrepartie, la création d’un processus peut augmenter légèrement la latence de la première requête après une période calme.
Mode static
pm = static
pm.max_children = 20Langage du code : JavaScript (javascript)
PHP-FPM maintient exactement le nombre défini de processus. Ce mode offre un comportement prévisible, mais réserve immédiatement toute la mémoire correspondante. Il convient surtout aux environnements soigneusement dimensionnés et soumis à une charge stable.
Pourquoi définir pm.max_requests ?
La directive pm.max_requests recycle un processus après un certain nombre de requêtes :
pm.max_requests = 500
Elle limite l’accumulation de mémoire causée par une extension PHP, une bibliothèque ou une application qui libère imparfaitement certaines ressources.
Une valeur comprise entre quelques centaines et quelques milliers constitue souvent un point de départ raisonnable. Mesurez ensuite les effets plutôt que de poursuivre un nombre prétendument magique.
Configurer le journal des scripts PHP lents
PHP-FPM peut enregistrer une trace lorsqu’une requête dépasse un seuil :
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/example-slow.logLangage du code : JavaScript (javascript)
Le journal lent aide à identifier :
- un plugin WordPress bloqué dans une requête externe ;
- une requête SQL lente ;
- un traitement d’image excessif ;
- un import ou une tâche cron trop lourd ;
- une boucle ou un appel récursif ;
- un verrou de session PHP.
Consultez-le avec :
sudo tail -f /var/log/php-fpm/example-slow.logLangage du code : JavaScript (javascript)
Configurer le statut PHP-FPM sans l’exposer publiquement
Le statut PHP-FPM permet de suivre les processus actifs, inactifs, les files d’attente et les limites atteintes.
Dans le pool :
pm.status_path = /fpm-status
ping.path = /fpm-ping
ping.response = pong
Dans l’hôte virtuel Apache, limitez strictement l’accès à l’adresse locale ou à une adresse d’administration :
<LocationMatch "^/(fpm-status|fpm-ping)$">
Require local
ProxyPass "unix:/run/php/php-example.sock|fcgi://localhost/"
</LocationMatch>Langage du code : PHP (php)
Vous pourrez ensuite tester localement :
curl --resolve example.com:80:127.0.0.1 \
http://example.com/fpm-ping
curl --resolve example.com:80:127.0.0.1 \
http://example.com/fpm-statusLangage du code : JavaScript (javascript)
N’exposez jamais librement cette page. Elle révèle des informations opérationnelles sur le pool PHP.
Configurer MPM Event sans valeurs arbitraires
La configuration Debian se trouve généralement dans :
/etc/apache2/mods-available/mpm_event.conf
Affichez les valeurs actives avant de les modifier :
apache2ctl -t -D DUMP_RUN_CFG
Les principales directives sont :
StartServers: nombre initial de processus Apache ;ThreadsPerChild: nombre de threads par processus enfant ;MaxRequestWorkers: nombre maximal de requêtes actives simultanées ;MinSpareThreadsetMaxSpareThreads: réserve de threads disponibles ;MaxConnectionsPerChild: nombre de connexions avant le recyclage d’un processus.
Ne copiez pas une configuration trouvée sur un autre serveur. Apache qui sert des fichiers statiques consomme bien moins qu’un pool PHP-FPM, mais les modules chargés, les certificats, les proxys et les applications influencent toujours la mémoire.
Commencez avec les valeurs fournies par Debian ou Ubuntu. Augmentez ensuite MaxRequestWorkers seulement lorsque les mesures montrent que sa limite est atteinte et que la mémoire disponible le permet.
Coordonner Apache et PHP-FPM
Apache peut accepter davantage de connexions simultanées que PHP-FPM ne peut exécuter de scripts. Cette différence n’est pas nécessairement un problème.
MPM Event peut gérer des connexions statiques et persistantes pendant qu’un nombre plus réduit de processus PHP-FPM exécute les requêtes dynamiques.
Cependant, une file PHP-FPM constamment saturée indique l’un des problèmes suivants :
pm.max_childrenest trop faible ;- les requêtes PHP sont trop lentes ;
- le cache de page ne fonctionne pas ;
- le site reçoit davantage de trafic que prévu ;
- des robots sollicitent excessivement les pages dynamiques ;
- la base de données constitue le véritable goulot d’étranglement.
Augmenter pm.max_children sans corriger les requêtes lentes peut simplement permettre à davantage de processus de bloquer simultanément MySQL. Ce n’est pas une optimisation. C’est une embouteilleuse industrielle.
Vérifier OPcache avec PHP-FPM
PHP-FPM doit utiliser OPcache pour éviter de recompiler les scripts PHP à chaque requête.
Vérifiez que l’extension est chargée dans le contexte FPM :
php-query -v "${PHP_VERSION}" -s fpm -m opcacheLangage du code : JavaScript (javascript)
Vous pouvez aussi rechercher sa configuration :
grep -RHE '^[[:space:]]*opcache\.' \
"/etc/php/${PHP_VERSION}/fpm/conf.d/" \
"/etc/php/${PHP_VERSION}/mods-available/"Langage du code : JavaScript (javascript)
Après toute modification :
sudo systemctl reload "php${PHP_VERSION}-fpm.service"Langage du code : JavaScript (javascript)
Supprimer mod_php après validation
Il n’est pas nécessaire de supprimer immédiatement le paquet libapache2-mod-php. Le désactiver suffit pour basculer vers MPM Event.
Après plusieurs jours de fonctionnement stable, vous pouvez néanmoins retirer le paquet versionné pour éviter une réactivation accidentelle :
sudo apt purge "libapache2-mod-php${PHP_VERSION}"
sudo apt autoremoveLangage du code : JavaScript (javascript)
Examinez attentivement la liste proposée par APT avant de confirmer. Ne supprimez pas un méta-paquet nécessaire à votre politique de mises à jour sans comprendre ses dépendances.
Erreur 503 Service Unavailable après la migration
Une erreur 503 indique souvent qu’Apache ne peut pas joindre PHP-FPM.
Vérifiez d’abord le service :
sudo systemctl status "php${PHP_VERSION}-fpm.service" --no-pagerLangage du code : JavaScript (javascript)
Puis le socket :
sudo ls -lah /run/php/
sudo ss -xl | grep php
Enfin, comparez le chemin configuré dans Apache avec la directive listen du pool :
grep -RHE 'SetHandler|ProxyPass.*fcgi' /etc/apache2/
grep -RHE '^[[:space:]]*listen[[:space:]]*=' \
"/etc/php/${PHP_VERSION}/fpm/pool.d/"Langage du code : JavaScript (javascript)
Erreur AH01079 ou connexion refusée
Les messages proches de ceux-ci signalent généralement un service arrêté ou une destination incorrecte :
AH01079: failed to make connection to backend
Connection refused
Contrôlez les journaux :
sudo journalctl -u apache2 -n 100 --no-pager
sudo journalctl -u "php${PHP_VERSION}-fpm.service" -n 100 --no-pagerLangage du code : JavaScript (javascript)
Si PHP-FPM écoute sur TCP, vérifiez aussi le port :
sudo ss -lntp | grep php-fpm
Erreur Permission denied sur le socket PHP-FPM
Apache fonctionne généralement sous l’utilisateur www-data. Il doit pouvoir accéder au socket du pool.
Vérifiez ses permissions :
sudo stat "/run/php/php${PHP_VERSION}-fpm.sock"Langage du code : JavaScript (javascript)
Dans le pool, les directives suivantes conviennent généralement :
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
Rechargez ensuite PHP-FPM pour recréer le socket avec les bonnes permissions :
sudo systemctl reload "php${PHP_VERSION}-fpm.service"Langage du code : JavaScript (javascript)
Erreur Primary script unknown
Le message suivant indique généralement qu’Apache transmet à PHP-FPM un chemin de script incorrect :
AH01071: Got error 'Primary script unknown'Langage du code : JavaScript (javascript)
Vérifiez :
- le
DocumentRootde l’hôte virtuel ; - le chemin réel des fichiers ;
- la syntaxe de
SetHandler; - les permissions de traversée des répertoires ;
- les liens symboliques ;
- une éventuelle directive
ProxyPassMatchhéritée d’une ancienne configuration.
Affichez les permissions de chaque composant du chemin :
namei -l /var/www/example.com/public_html/index.phpLangage du code : JavaScript (javascript)
Apache affiche le code PHP au lieu de l’exécuter
Si le navigateur reçoit le code source PHP, le gestionnaire PHP-FPM n’est pas actif pour cet hôte.
Vérifiez la configuration FPM activée :
ls -l /etc/apache2/conf-enabled/*fpm*
Vérifiez également les directives SetHandler :
grep -RHE 'SetHandler.*fcgi' \
/etc/apache2/conf-enabled/ \
/etc/apache2/sites-enabled/Langage du code : JavaScript (javascript)
Traitez ce problème immédiatement. Servir un fichier PHP sans l’interpréter peut exposer des identifiants, des clés secrètes et la configuration de l’application.
PHP-FPM atteint pm.max_children
Le journal peut afficher un message similaire :
server reached pm.max_children settingLangage du code : CSS (css)
Avant d’augmenter la limite, examinez :
- la mémoire disponible avec
free -h; - la mémoire de chaque processus PHP ;
- le journal lent PHP-FPM ;
- les requêtes SQL lentes ;
- le taux de cache de page ;
- la fréquence des tâches cron ;
- les robots et les requêtes abusives.
Consultez les messages récents :
sudo journalctl \
-u "php${PHP_VERSION}-fpm.service" \
--since '1 hour ago' \
--no-pagerLangage du code : JavaScript (javascript)
Apache refuse d’activer MPM Event
Une erreur indiquant un conflit entre MPM signale généralement que Prefork ou Worker reste actif.
ls -l /etc/apache2/mods-enabled/mpm_*
Désactivez les MPM concurrents :
sudo a2dismod mpm_prefork mpm_worker
sudo a2enmod mpm_event
Si mod_php reste actif, désactivez-le également avant de relancer la commande.
Procédure de retour arrière
Si un site critique ne fonctionne plus et que le diagnostic doit attendre, revenez temporairement à mod_php.
Désactivez la configuration FPM et MPM Event :
sudo a2disconf "php${PHP_VERSION}-fpm"
sudo a2dismod mpm_event proxy_fcgiLangage du code : JavaScript (javascript)
Réactivez Prefork et le module PHP :
sudo a2enmod mpm_prefork "php${PHP_VERSION}"Langage du code : JavaScript (javascript)
Validez avant de redémarrer :
sudo apache2ctl configtest
sudo systemctl restart apache2
Cette procédure suppose que le paquet libapache2-mod-php n’a pas encore été supprimé. C’est l’une des raisons pour lesquelles il vaut mieux le conserver quelques jours après la migration.
Script de migration avec vérifications
Le script suivant automatise la bascule de base. Il ne remplace pas la vérification des sites ni le dimensionnement des pools.
#!/usr/bin/env bash
set -Eeuo pipefail
if [ "${EUID}" -ne 0 ]; then
echo "Exécutez ce script avec sudo." >&2
exit 1
fi
PHP_VERSION="$(
php -r 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;'
)"
FPM_SERVICE="php${PHP_VERSION}-fpm.service"
FPM_CONF="php${PHP_VERSION}-fpm"
PHP_MODULE="php${PHP_VERSION}"
BACKUP_DIR="/root/apache-php-backup-$(date +%F-%H%M%S)"
echo "Version PHP détectée : ${PHP_VERSION}"
echo "Vérification initiale d’Apache..."
apache2ctl configtest
echo "Sauvegarde de la configuration..."
mkdir -p "${BACKUP_DIR}"
cp -a /etc/apache2 "${BACKUP_DIR}/"
cp -a /etc/php "${BACKUP_DIR}/"
echo "Installation de PHP-FPM..."
apt update
apt install -y "php${PHP_VERSION}-fpm"
echo "Activation de PHP-FPM..."
systemctl enable --now "${FPM_SERVICE}"
if ! systemctl is-active --quiet "${FPM_SERVICE}"; then
echo "PHP-FPM n’est pas actif." >&2
exit 1
fi
echo "Activation de la configuration FPM dans Apache..."
a2enconf "${FPM_CONF}"
echo "Désactivation de mod_php et MPM Prefork..."
a2dismod "${PHP_MODULE}" 2>/dev/null || true
a2dismod mpm_prefork
echo "Activation de MPM Event et mod_proxy_fcgi..."
a2enmod mpm_event proxy proxy_fcgi setenvif
echo "Validation de PHP-FPM..."
"php-fpm${PHP_VERSION}" -t
echo "Validation d’Apache..."
apache2ctl configtest
echo "Redémarrage d’Apache..."
systemctl restart apache2
if ! systemctl is-active --quiet apache2; then
echo "Apache n’a pas redémarré correctement." >&2
journalctl -u apache2 -n 100 --no-pager
exit 1
fi
echo
echo "Migration terminée."
echo "Sauvegarde : ${BACKUP_DIR}"
echo
apache2ctl -V | grep -i 'Server MPM'
apache2ctl -M | grep -E 'mpm_|proxy|fcgi|php' || trueLangage du code : PHP (php)
Avant de l’exécuter, vérifiez que la version PHP détectée correspond bien au module Apache actif. Sur un serveur multiversion, adaptez explicitement PHP_VERSION.
Checklist après la migration
- Apache utilise bien MPM Event ;
php_modulen’est plus chargé ;proxy_moduleetproxy_fcgi_modulesont actifs ;- PHP-FPM fonctionne et son socket existe ;
- la ligne
Server APIindiqueFPM/FastCGI; - chaque hôte virtuel sert la bonne version PHP ;
- les tâches cron et WP-CLI utilisent la version PHP attendue ;
- les formulaires, téléversements et traitements d’images fonctionnent ;
- WordPress et WooCommerce ne produisent aucune erreur fatale ;
- les journaux Apache et PHP-FPM restent propres ;
- le cache de page fonctionne ;
- les processus PHP ne saturent pas la mémoire ;
- la procédure de retour arrière a été conservée.
Besoin d’optimiser ou de fiabiliser votre serveur WordPress ?
Une migration vers PHP-FPM ne se limite pas à activer quelques modules. Il faut dimensionner les pools, surveiller les erreurs, vérifier MySQL, configurer les caches et anticiper les pics de charge.
- configuration Apache, Nginx et PHP-FPM ;
- optimisation des pools PHP et d’OPcache ;
- hébergement de sites WordPress et WooCommerce ;
- migration vers un nouveau serveur ;
- analyse des erreurs 502, 503 et des processus saturés ;
- sécurisation, supervision et sauvegardes.
Présentez-moi votre infrastructure et vos objectifs pour obtenir une configuration adaptée à sa charge réelle.
Questions fréquentes
MPM Event est-il meilleur que MPM Worker ?
MPM Event dérive de Worker, mais gère plus efficacement les connexions persistantes inactives. Pour une configuration Apache moderne avec PHP-FPM, Event constitue généralement le meilleur choix.
PHP-FPM est-il plus rapide que mod_php ?
Pas systématiquement pour une requête isolée. Son principal avantage réside dans la séparation des processus, le contrôle de la concurrence, l’utilisation de MPM Event et la possibilité de créer plusieurs pools. Les performances globales deviennent surtout plus prévisibles et plus faciles à régler.
Faut-il installer mod_fastcgi ou mod_fcgid ?
Non pour cette architecture. Apache 2.4 communique directement avec PHP-FPM grâce à mod_proxy et mod_proxy_fcgi. Les anciennes procédures fondées sur mod_fastcgi ne sont plus nécessaires.
Peut-on utiliser plusieurs versions de PHP avec Apache ?
Oui. Installez plusieurs services PHP-FPM, puis associez chaque hôte virtuel au socket de la version souhaitée. Évitez alors la configuration FPM globale, qui appliquerait le même gestionnaire à tous les sites.
Un socket Unix est-il plus sûr qu’un port TCP ?
Sur un même serveur, le socket Unix simplifie le contrôle des accès grâce aux propriétaires, groupes et permissions. Un port TCP reste pertinent pour des conteneurs ou des serveurs distincts, mais il ne doit jamais être exposé publiquement.
Quelle valeur utiliser pour pm.max_children ?
Il n’existe pas de valeur universelle. Mesurez la mémoire moyenne des processus PHP sous une charge réelle, déterminez la mémoire que vous pouvez réserver au pool, puis conservez une marge pour Apache, la base de données, le système et les autres services.
PHP-FPM permet-il d’utiliser HTTP/2 avec Apache ?
Oui. En retirant la dépendance à mod_php et MPM Prefork, PHP-FPM permet d’utiliser MPM Event avec le module HTTP/2 d’Apache.
Sources
- Documentation Apache : MPM Event
- Documentation Apache : mod_proxy_fcgi
- Manuel PHP : FastCGI Process Manager
- Manuel PHP : configuration de PHP-FPM
- Documentation Apache : directives communes aux MPM
- Documentation Apache : module HTTP/2
Un projet WordPress en tête ?
Vous avez une idée claire de ce que vous voulez, mais pas les ressources en interne pour le faire bien. Je développe des sites et extensions WordPress sur-mesure — sans délais à rallonge ni mauvaises surprises.
Décrivez-moi votre projet →



Article mis à jour :
– ajout des paramètres
-appConnTimeoutet-idle-timeoutdans la configuration FastCgi (étape 3).– ajout du fichier
error_logdans le fichier php.ini de PHP-FPM (étape 4).Tu as pu voir des différences de performances entre MySQL et MariaDB de 4% en faveur de MariaDB, du coup avec PHP-FPM tu vois une vrai différence ?
Difficile à dire : cela me semble un tout petit plus rapide qu’avant mais cela pourrait aussi bien être un effet placebo…
Je me dis que c’est aussi une manière de se tourner vers système de gestion de base de données plus réactif et disposant de davantage de fonctions que MySQL. Il est d’ailleurs de plus en plus proposé sur les distributions.
Le principal boost viendra très probablement de PHP7, qui promet d’excellentes performances à tous niveaux.
mais adebian 7 utilise apache 2.2 , pas 2.4 …???
Bonjour fds,
C’est exact, je viens de modifier l’article pour la dernière version stable de Debian.
Debian 7 possède effectivement Apache 2.2, Debian 8 Apache 2.4
Un super Tutoriel et ça marche avec ubuntu 15.04. Merci beaucoup.
Juste, une petite question: Comment mettre en place plusieurs sites web avec des utilisateurs différents ? (pour sécuriser).
Merci encore
Bonjour,
Il suffit de créer un VirtualHost pour chaque site. Ensuite, je pense qu’il faut utiliser le module Apache 2 ITK MPM.
Article mis à jour:
– ajout des instructions pour PHP7.
– ajout de la configuration pour MPM Worker.
Bonjour, est-ce sans risque de faire cette manip lorsque un ou plusieurs serveurs tournent déjà sur la config existante ? étant relativement noob en la matière, j’ai eu quelques déboires en suivant le tuto sur la maj ver PHP 5.6 et j’ai perdu tout mes serveurs (cela avait littéralement vidé mon dossier /var/www ).Avec cette manip pour php-fpm Cela va t’il les désinstaller aussi ou non ? autre question, aurais-je à réecrire tout mes virtualhost ?
merci d’avance
Bonjour zboob,
Il est recommandé de faire une sauvegarde des fichiers et des fichiers de configuration VirtualHosts avant toute intervention sur un serveur de production qui héberge des sites actifs. Il faut penser à sauvegarder le dossier
/etc/également.Une fois les sauvegardes faites, il est assez aisé de faire la mise à jour. Au pire, il sera toujours possible de remettre la configuration initiale.
Ps : les VirtualHosts n’auront pas besoin d’être réécrits.