PHP a beaucoup accéléré son cycle de développement et a raccourci la durée de prise en charge de chaque version. Forcément, nos devs ne suivent pas et se retrouvent à bosser sur X sites web avec Y versions de PHP, de la 5.6 à la 8.2 en passant par la 7.2.
Côté adminsys, on se retrouve à devoir gérer trouzemilles versions de PHP sur nos serveurs. Évidemment, toutes les versions désirées par nos devs ne sont pas empaquétées dans la version stable de Debian GNU/Linux. On répond au besoin avec du PHP compilé, du PHP-FPM, du reverse proxy, des scripts maison, et du Puppet. Merci Seb'.
Nos devs tiennent à développer en local, sur leur station de travail, pas sur une plateforme de dev ou de test… T'as beau leur expliquer que leur IDE peut pousser leur code, qu'il existe des hooks gitlab, que ça garantit qu'un code qui fonctionne en dev passe la test et donc la prod (notamment quand il utilise des extensions), que ça fait gagner du temps aux adminsys pour les assister (on n'a pas à connaître leur installation perso, leur système d'exploitation perso, leur façon de faire, leurs boulettes, etc.)… rien y fait… Nos devs ont leur tambouille locale (et un peu perso) pour installer et maintenir plusieurs versions de PHP sur leur poste de travail.
Dans ce contexte, le nouveau dev' souhaite pousser l'utilisation de phpenv dans son équipe. Je me suis penché dessus afin de l'assister sur l'interfaçage de phpenv avec PHP-FPM / Apache httpd.
sudo apt install git ;git clone https://github.com/phpenv/phpenv ~/.phpenv ;echo 'export PATH="$HOME/.phpenv/bin:$PATH"' >> ~/.bashrc ;echo 'eval "$(phpenv init -)"' >> ~/.bashrc ;. .bashrc.La compilation est effectuée par php-build. C'est donc de son côté qu'il faudra changer les options de compilation d'une version de PHP afin d'ajouter une extension PECL, par exemple.
Première fois :
git clone https://github.com/php-build/php-build $(phpenv root)/plugins/php-build.
Ensuite et les fois suivantes (les fois suivantes, penser à git pull php-build pour le mettre à jour ;) ) :
phpenv install 8.2.0 ;phpenv rehash ;phpenv versions permet de vérifier.
Évidemment, phpenv ne fait pas de magie : compiler une vieille version de PHP sur un système récent va être compliqué voire impossible (pas la bonne version d'une dépendance empaquetée dans les dépôts officiels, il faudra adapter les chemins vers les fichiers d'entêtes des lib, etc.).
phpenv shell 8.2.0 (sinon erreur « phpenv: php: command not found / The `php' command exists in these PHP versions ») ;php </chemin/vers/le/fichier.php>.Pour tester un même fichier avec plusieurs versions de PHP, il suffit donc de changer la version de PHP, puis d'exécuter, puis de changer puis…
~/.phpenv/versions/<VERSION>/etc/php-fpm.d/www.conf, remplacer « group = nobody » par « group = nogroup », car le group nobody n'existe pas sur Debian GNU/Linux. Sans ça, systemctl status php-fpm crachera l'erreur « [pool www] cannot get gid for group 'nobody' ». Perso, j'ai mis « user » et « group » à « www-data », car c'est ainsi qu'est configuré php-fpm empaqueté dans Debian et qu'affiner les droits a du sens uniquement dans un contexte multi-instances (une instance de PHP pour un site web donné, nécessaire dans le cadre d'un hébergement web mutualisé) ;sudo cp ~/.phpenv/versions/<VERSION>/etc/systemd/system/php-fpm.service /etc/systemd/system/php-fpm.service ;sudo systemctl start php-fpm (on peut aussi enable pour que php-fpm soit lancé au démarrage de la machine) ;Créer un virtualhost Apache httpd basique et ajouter :
<FilesMatch \.php$>
SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>
sudo a2ensite <NOM_VIRTUALHOST> ;sudo a2enmod proxy_fcgi ;sudo systemctl restart apache2 ;/etc/hosts (exemple : « ::1 test-8.2.0.local »).L'ennui, c'est qu'une seule et même version de PHP va servir tous les sites web (tous les virtualhosts). Pour changer de version, il faut refaire le cp ci-dessus (en changeant la version) et restart php-fpm.
Je trouve dommage que phpenv n'ai pas poussé plus loin l'intégration alors que c'est facile (et que c'est un peu son objectif…)…
Instructions :
~/.phpenv/versions/<VERSION>/etc/php-fpm.d/www.conf, remplacer « listen = 127.0.0.1:9000 » par « listen = 127.0.0.1:90XY » avec X = version majeure PHP, Y = version mineure. Exemples : « listen = 127.0.0.1:9074 » = PHP 7.4 ; « listen = 127.0.0.1:9082 » = PHP 8.2 ;/etc/systemd/system/php<X.Y>-fpm.service. C'est évidemment cette unit qu'il faut démarrer et plus la fade « php-fpm » ;SetHandler "proxy:fcgi://127.0.0.1:9074" ; pour un 8.2 : SetHandler "proxy:fcgi://127.0.0.1:9082". Il faut reload Apache httpd après ce changement.
Avec cette méthode, j'ai bien plusieurs versions de PHP utilisables avec PHP-FPM et un serveur web configuré en reverse proxy :
$ grep SetHandler /etc/apache2/sites-available/test-8.2.0.local.conf
SetHandler "proxy:fcgi://127.0.0.1:9082"
$ grep SetHandler /etc/apache2/sites-available/test-7.4.33.local.conf
SetHandler "proxy:fcgi://127.0.0.1:9074"
$ cat /var/www/test-8.2.0.local/index.php
<?php phpinfo(); ?>
$ cat /var/www/test-7.4.33.local/index.php
<?php phpinfo(); ?>
$ grep test /etc/hosts
::1 test-8.2.0.local
::1 test-7.4.33.local
$ curl -s http://test-7.4.33.local/ | grep -Po '(?<=PHP Version )[0-9\.]+'
7.4.33
$ curl -s http://test-8.2.0.local/ | grep -Po '(?<=PHP Version )[0-9\.]+'
8.2.0
Merci Raph' pour la découverte. :)