Résumé : activation de HTTP/2 sur ce serveur, donc migration vers mpm_event (car HTTP/2 = requêtes en parallèle dans une même connexion ce que ne peut pas gérer mpm_prefork), donc migration du module PHP pour Apache httpd (on rappellera que la fondation Apache publie d'autres logiciels que httpd : Tomcat, Storm, Ant, Kafka, Hadoop, etc.) vers PHP-FPM (car le module n'est pas multithreadé), donc suppression du chroot Apache httpd devenu inutile, donc suppression du chroot BIND9 par homogénéité entre tous les logiciels que j'utilise. Je termine par un joli bug Apache httpd quand on utilise h2c (HTTP/2 sur une connexion non chiffrée). Je rappelle que les navigateurs web prennent en charge uniquement HTTP/2 over TLS (HTTPS/2, quoi).
Il y a quelques mois, j'ai testé l'activation de la nouvelle version du protocole qui soutient le web, HTTP/2.
J'en avais déduis que son fonctionnement « plusieurs requêtes dans une même connexion TCP / HTTP » nécessite plutôt un module de traitement Apache httpd qui gère réellement les requêtes parallèles. Exit mpm_prefork, bonjour mpm_event (recommandé par la doc' officielle d'Apache httpd). Sauf que, le module PHP pour Apache n'est pas utilisable avec mpm_event, justement car il n'est pas multi-tâches. Il faut donc passer à PHP-FPM.
Par défaut, PHP-FPM n'est pas chrooté. Il peut l'être. Vu les emmerdes que ça m'a apporté au fil des ans (voir ici et là), ça en m'intéresse pas. Puisque PHP n'est plus un module d'Apache httpd, est-il encore utile de chrooter ce dernier ? Apache httpd va uniquement manipuler des fichiers statiques, pas de code dynamique avec des saisies utilisateur… Un chroot aura environ aucun intérêt.
J'ai déjà dé-chrooté MySQL car c'était la galère. Si je dé-chroote Apache httpd, il restera BIND9. Chrooter BIND9 m'a posé aucun souci pendant 10 ans. Mais, d'une part, il n'est pas chrooté par défaut, et, d'autre part, je ne l'ai pas totalement chrooté dans les règles de l'art (un chroot doit être hermétique et auto-suffisant, sans lien vers l'extérieur). Virer le chroot de BIND9, c'est assurer l'homogénéité de fonctionnement entre les logiciels que j'utilise, ce qui simplifie la mémorisation de l'architecture technique. Le seul logiciel encore chrooté sera Postfix, mais il est livré ainsi et le chroot m'a jamais posé problème.
Mon chroot MySQL aura tenu 7 ans, mes chroots Apache httpd et BIND9 auront tenu 10 ans. Le module PHP pour Apache httpd aura tenu plus de 10 ans. Pas si mal.
Au final, j'ai :
Aucune difficulté : il suffit de copier (cp -a
) les fichiers de zone, les clés, les journaux de transferts de zones, etc. du chroot vers l'emplacement hors chroot (/etc/bind
par défaut, mais j'ai l'habitude de séparer la configuration du contenu en mettant la conf' dans /etc
et le contenu dans /var/named
comme l'on sépare le contenu d'un site web dans /var/www
de la configuration d'un serveur web dans /etc∕
) puis de retirer l'option « -t » dans /etc/default/bind9 puis de redémarrer BIND9. Si aucune erreur est consignée dans le journal, on peut supprimer le chroot avec un rm -r
.
Il faut copier (cp -a
) le contenu des sites web (les DocumentRoot
) depuis l'emplacement du chroot vers /var/www
puis retirer les directives de configuration ChrootDir
et LoadFile
du fichier /etc/apache2/apache2.conf
. Dans chaque hôte virtuel (aka virtualhost), il faut s'assurer que les directives DocumentRoot
et Directory
sont toujours valables (si le chroot était bien fait, elles devraient l'être).
Côté module PHP pour Apache httpd, il faut annuler la bidouille du script de nettoyage régulier des sessions PHP et virer le paramétrage d'un magasin de certificats x509 interne au chroot plutôt que le magasin par défaut du système.
Enfin, on redémarre Apache httpd. Si aucune erreur est consignée dans le journal, on peut supprimer le chroot avec un rm -r
.
J'ai déjà tout écrit dans mon shaarli sur mon test de HTTP/2 donc je vais faire court.
Il faut…
Installer PHP-FPM avec apt-get install php-fpm
.
Dans la configuration des hôtes virtuels (aka virtualhosts) d'Apache httpd, il faut retirer les directives php_admin_value
. Si l'on veut les conserver et que leur valeur est commune à tous les hôtes virtuels, on les déplace dans le php.ini (/etc/php/7.3/fpm/php.ini
). Si non, il faut créer autant de pools que de virtualhosts et mettre les directives php_admin_value
dans la définition d'un pool (/etc/php/7.3/fpm/pool.d/www.conf
, par exemple).
Remplacer prefork par event : a2dismod mpm_prefork && a2enmod mpm_event
.
Désactiver le module PHP et activer l'utilisation de PHP-FPM : a2dismod php7.3 && a2enconf php7.3-fpm
. Si t'as plusieurs pools, il ne faut pas activer cette conf' généraliste, mais ajouter une directive de proxy fcgi spécifique (socket différente) à l'intérieur de chaque hôte virtuel.
Redémarrer Apache httpd. Si aucune erreur est consignée dans le journal, on peut désinstaller le module PHP pour Apache httpd : apt-get autoremove --purge libapache2-mod-php libapache2-mod-php7.3 && rm -r /etc/php/7.3/apache2
.
Les erreurs / avertissements / notifications liées au code PHP (oubli d'un point virgule, mauvais échappement d'une chaîne de caractères, etc.) sont toujours consignées dans le fichier error.log d'un hôte virtuel. Les erreurs liées à PHP-FPM toutes pools confondus (nombre maximum de processus atteint, etc.) **sont consignées dans le journal d'erreur de PHP, /var/log/php7.3-fpm.log
). Il est possible d'avoir un journal par pool en surchargeant error_log
dans la définition du pool.
Par défaut, le pool www
est éxecuté sous le compte utilisateur www-data
, c'est-à-dire… celui du serveur web. Comme avec le module PHP pour Apache httpd. On peut changer ça (ainsi que les droits sur les fichiers des sites web) mais, boarf, la motivation me manque.
J'ai déjà tout écrit dans mon shaarli sur mon test de HTTP/2 donc je vais faire court : a2enmod http2 && systemctl restart apache2
.
Je rappelle viteuf qu'il y a trois manières d'initier une connexion HTTP/2 : extension TLS ALPN, entête HTTP/1.1 « Upgrade: h2c » sur connexion non chiffrée ou entête HTTP/1.1 « HTTP Alternative Services ». **Les navigateurs web, notamment Mozilla Firefox, prennent en charge exclusivement la première méthode (HTTP/2 over TLS, HTTPS).
On notera un truc rigolo dans le journal Apache httpd access.log de l'hôte virtuel lors d'un accès h2c (HTTP/2 sur une connexion en clair, non TLS, non chiffrée) :
2001:db8::1 - - [01/Jan/1970:01:00:00 +0100] "GET / HTTP/2.0" 200 132608 "-" "curl/7.64.0"
2001:db8::1 - - [15/Feb/2020:17:56:05 +0100] "GET / HTTP/1.1" 101 132733 "-" "curl/7.64.0"
La connexion HTTP/2 qui a forcément eu lieu après la connexion HTTP/1.1 est consignée avant… et avec un horodatage inexact.
Cette erreur se retrouve dans les entêtes transmis au client web :
HTTP/1.1 101 Switching Protocols
Upgrade: h2c
Connection: Upgrade
HTTP/2 200
date: Thu, 01 Jan 1970 00:00:00 GMT
server: Apache
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
pragma: no-cache
last-modified: Sat, 15 Feb 2020 17:08:49 GMT
vary: Accept-Encoding,User-Agent
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
content-type: text/html; charset=utf-8
Évidemment, cela a un impact sur la durée du cache côté client web et sur tout ce qui utilise la date… ÉDIT DU 23/11/2020 À 22 H 40 : Cela impacte le calcul de la date dans l'entête « Expire » sur une image, par exemple, mais, dans cet exemple précis, la date qui apparaît dans l'entête « Expires » n'est pas une erreur de calcul liée à la date faussée par le bug h2c, mais une date symbolique passée choisie par les développeurs de PHP pour désactiver la mise en cache lors de l'ouverture d'une session sur un site web. FIN DE L'ÉDIT.