Installer et configurer PHP pour Apache2

Apache et PHP ont déjà quelques années de vie conjugale. Et comme tout couple qui dure, ils sont très complémentaires et savent se réinventer. Nous allons voir comment configurer php de deux manières différentes : en tant que module Apache, mod_php, et et en tant que serveur FastCGI via php-fpm.

Nous allons partir sur la dernière version majeure de PHP : PHP 7. Si vous êtes sous Debian 8 ou Ubuntu 16.04 (ou plus), c’est la version par défaut dans les dépôts. En revanche, si vous avez une version de Linux antérieure, il va falloir utiliser des dépôts alternatifs.

Toutes les commandes exécutées ci-après sont exécutées en root. Pensez donc à passer en root avec sudo su ou à faire précéder vos commandes de sudo.

# ajout des dépôts alternatifs pour PHP7 au besoin
add-apt-repository ppa:ondrej/php
apt-get update

Voilà, quel que soit votre version, vous disposez des dépôts qui vont bien. Commençons l’installation.

Installation avec mod_php

On attaque avec le plus simple, la manière legacy d’utiliser php avec Apache. Je dis legacy car le moteur de php intégré à Apache en tant que module était à l’origine la seule manière de faire jusqu’à Apache 2.4.

Cette méthode est tout à fait fonctionnelle et est plus simple à paramétrer. Elle possède néanmoins deux défauts. Le premier est inhérent au fait que php est intégré en tant que module Apache : les processus ont tendances à gonfler l’usage de la mémoire. Rien d’insurmontable cependant, il suffit de les forcer à se renouvelle de temps à autre. J’explique la marche à suivre dans la partie sur l’optimisation des performances de l’article dédié à la configuration d’Apache.

Le second défaut est que le MPM prefork requis pour utiliser php en tant que module Apache n’est pas compatible avec HTTP/2. Si ces deux petits défauts ne vous contrarient pas, alors le mod_php est une solution parfaitement viable.

apt install libapache2-mod-php

Si php n’est pas déjà installé, il le sera automatiquement, ainsi que toutes les autres dépendances.

Installation avec php-fpm

php-fpm consiste en un serveur php autonome avec lequel Apache communique via fastCGI. On utilisera un socket unix pour la communication.

Nous allons installer php-fpm et configurer Apache afin qu’il transmette les requêtes à php lorsqu’elles nécessitent d’être interprétées.

# installation de php-fpm et ses dépendances
apt install php-fpm

# apache a besoin du module proxy_fcgi pour transmettre les requêtes
a2enmod proxy_fcgi

# on précise de manière globale à apache (pour tous les vhost)
# de transmettre toutes requête destinée à php
a2enconf php7.0-fpm

Voilà, ce n’est pas plus compliqué que cela. Lors de l’installation de php-fpm, php s’installe évidemment avec ses dépendances.

Ubuntu nous a déjà bien mâché le travail en fournissant des fichiers de configuration tout prêts. La configuration de la connexion se trouve dans /etc/php/7.0/fpm/pool.d/www.conf. La partie qui nous intéresse ici est celle qui définit la création du socket d’écoute :

listen = /run/php/php7.0-fpm.sock

C’est cette information qui est reprise dans le fichier de configuration pre-rempli qui nous est automatiquement fournit et que l’on active via a2enconf php7.0-fpm. On peut inspecter son contenu (et le créer s’il n’existe pas). Il se trouve à /etc/apache2/conf-available/php7.0-fpm.conf :

<IfModule !mod_php7.c>
    # Enable http authorization headers
    SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1

    <FilesMatch ".+\.ph(p[3457]?|t|tml)$">
        SetHandler "proxy:unix:/run/php/php7.0-fpm.sock|fcgi://localhost"
    </FilesMatch>
    <FilesMatch ".+\.phps$">
        # Deny access to raw php sources by default
        # To re-enable it's recommended to enable access to the files
        # only in specific virtual host or directory
        Require all denied
    </FilesMatch>
    # Deny access to files without filename (e.g. '.php')
    <FilesMatch "^\.ph(p[3457]?|t|tml|ps)$">
        Require all denied
    </FilesMatch>
</IfModule>

On voit bien que la directive SetHandler reprend (en ajoutant une option pour écouter via une connexion TCP au besoin) notre socket UNIX. Il est également possible de ne pas activer la configuration et d’ajouter ceci directement dans les ou les vhost concernés (cela permet de ne pas l’activer pour tous…).

Il y a un autre paramètre très important dans ce fichier de configuration, il s’agit de pm.max_children. Cette valeur défini combien de processus PHP peuvent s’exécuter en paralèlle. Si vous atteingnez le maximum, vous verrez un warning dans les logs de php et la requête sera placée en file d’attente.

La valeur est à 5 par défaut. Si vous avez du trafic, il peut être judicieux d’augmenter cette valeur. Évidemment, c’est à mettre en relation avec la charge CPU et la RAM disponible car des processus supplémentaires ont un coût.

L’impact CPU ainsi que mémoire dépend fortement des traitements effectués avec php. Cependant, la plupart du temps, la RAM constitue le goulot d’étranglement. On regarde donc quel est la taille en mémoire d’un processus :

ps aux | grep php-fpm
root     29968  0.0  1.6 357700 32088 ?        Ss   08:48   0:00 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf)
www-data 29973  0.1  4.2 442596 84560 ?        S    08:48   0:02 php-fpm: pool www
www-data 29974  0.1  4.1 440552 82268 ?        S    08:48   0:02 php-fpm: pool www
www-data 30270  0.0  2.8 361248 57264 ?        S    08:58   0:00 php-fpm: pool www

On constate que plusieurs processus enfants sont en cours d’exécution avec plus ou moins de mémoire utilisé. Le plus important consomme 84560 KB de mémoire, soit ≈85MB. Sachant que ce serveur dispose de 2GB de ram et qu’il doit aussi exécuter MySQL, je peux allouer dans les 800MB maximum. J’augmente donc cette valeur à 10 (ou 9 pour être prudent).

Si vous voyez des WARNING: [pool www] server reached pm.max_children setting (10), consider raising it, c’est que vous gagneriez à augmenter pm.max_children. Cependant, si vous n’avez plus beaucoup de ram disponible, soit vous déchargez votre serveur de la base de données par exemple, soit il faudra envisager un serveur avec plus de ram.

Réglages du php.ini

Quelle que soit la méthode choisie, php est désormais fonctionnel ! Il reste néanmoins quelques paramètres à modifier dans le fichier de configuration de php, le php.ini. Vous trouverez ce fichier dans /etc/php/7.0/apache ou /etc/php/7.0/fpm.

Je vous mets ci-dessous, une liste des paramètres intéressants que l’on doit ou que l’on a souvent à changer.

;;;;;;;;;;;;;;;;;;;;
; Language Options ;
;;;;;;;;;;;;;;;;;;;;
# Mettre à Off si possible
# les shorts open tags sont les balises d'ouvertures courtes de php <?
# elles posent des problèmes de compatibilité avec XML
# puisque c'est justement la syntaxe des balises XML. 
short_open_tag = Off

# le safe_mode est déprécié dans PHP 5.3 et a été supprimé de 5.4
# par conséquent, laissez cette option à Off
safe_mode = Off

# l'open basedir permet de limiter les dossiers dans lequel php va pouvoir interpréter des données
# cela est plus sur car un attaquant ne pourra pas utiliser php pour lire des données en dehors de dossier spécifié
; http://php.net/open-basedir
open_basedir = /var/www

# désactiver des fonctions de php
# il y en a certaines de désactivées par défaut, toutefois, certaines fonctions sont souvent utilisées pour 
# exploiter une faille dans l'application et mettre en place des backdors, ainsi, si votre application ne 
# les utilise pas, il est judicieux de les désactiver.
# à celle par défaut listées ci-dessous, on peut ajouter :
# exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signasignal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,

;;;;;;;;;;;;;;;;;
; Miscellaneous ;
;;;;;;;;;;;;;;;;;
# ajoute ou non la signature de php dans les en-tête http
# ce n'est pas primordial, mais personne n'a à savoir
# que nous utilisons php, ni la version utilisée
expose_php = Off

;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;
# ces options concernent les performances de php
# les réglages par défaut doivent normalement suffire pour la plupart des cas

# temps maximum d'exécution après lequel un script sera arrêté
# sauf cas particulier, vos script ne devraient jamais mettre 
# plus de quelques secondes à s'exécuter
max_execution_time = 30

# temps maximum qu'un script peut mettre pour recevoir des données input
# au delà de ce laps de temps, le traitement est stoppé
# il peut-être ici judicieux d'augmenter ce temps si vous proposer l'upload de fichier
max_input_time = 60

# taille de mémoire qu'un script peut consommer
# de même, si vous avez un formulaire d'upload de gros fichiers
# il se peut que vos scripts aient besoin de plus de mémoire
memory_limit = 512M

# affiche les erreurs php
# mettre à On pendant le dev, Off en production
display_errors = On

# affiche les erreurs qui ont cours durant la séquence de démarrage de php
# mettre à Off en production. Il peut être intéressant de les mettre 
# à On en développement pour le débogage. 
display_startup_errors = Off

# consigne les erreurs dans les fichiers de log
# je conseille de toujours laisser à On
log_errors = On

;;;;;;;;;;;;;;;;;
; Data Handling ;
;;;;;;;;;;;;;;;;;
# taille maximale que php accepte pour les données en POST
# dans le cas d'un upload de fichier par post, 
# cette valeur sera aussi à modifier si vous voulez uploader des fichiers de plus de 8M
post_max_size = 8M

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

# peut-être désactivé si vous ne comptez pas autoriser l'upload de fichiers
file_uploads = On

# définit la taille maximale de fichiers que l'on peut uploader
# cette taille ne peut toutefois pas dépasser celle de post_max_size
upload_max_filesize = 2M

;;;;;;;;;;;;;;;;;;;
; Module Settings ;
;;;;;;;;;;;;;;;;;;;

# règle le fuseau horaire
date.timezone = Europe/Paris

Il faut maintenant redémarrer le serveur apache pour que ces modifications soient prisent en compte. Je vous redonne la commande :

service apache2 restart

Il n’y a rien de plus à configurer pour php. You’re good to go!.

Il n'y a pas encore de commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *