PHP FPM beállítása Apache HTTPD 2.2 és 2.4 alatt

Írtam már a mod_cgi/mod_cgid és a mod_fcgid modulokról, amikkel a PHP több verzióját futtathatjuk egyszerre. A PHP FPM viszont egy ezeknél is jobb megoldás. Azért mégsem tejesen új, mivel a mod_fastcgi vagy mod_fcgid Apache modulok egyike kell hozzá. Bár előbbiről nem esett még külön szó az említés szintjén felül, most ezt is telepítjük, mivel az Apache HTTPD 2.2 nem támogatja a szükséges mod_proxy_fcgi modult a mod_fcgid használatához.

A fejezet végén tehát már ismerni fogjuk mindkét lehetőséget és mindkét webszerver képes lesz bármely PHP verziót FPM-en keresztül futtatni tetszőleges felhasználó nevében.

Előbb azonban mindenképp javaslom a PHP telepítéséről szóló fejezet elolvasását, ahol az FPM telepítéséhez szükséges konfigurálásról írtam. Valamint az előző CGI megoldásokról szólót is.

Előkészületek, előismeret

Már az eddigiek után talán mondanom sem kell, de root jogra szükség lesz a sudo su vagy su - root parancsok egyikével. Amelyik működik.

Miért?

Mielőtt bármit állítgatnánk, értsük meg, hogy miért is tesszük és hogy ellenőrizzük a sikerességét! Azt a tényt, hogy ezzel több PHP verziót is lehet egyidejűleg használni, már kellően sokat emlegettem. És ez már FPM nélkül is működött. Ahhoz viszont, hogy a PHP egy tetszőleges felhasználó nevében futhasson, további intézkedések kellenek. Ez szintén megoldható lenne FPM nélkül, az FPM viszont ennél többről szól.

Egy helyen menedzselhetők a processek kezelésének tulajdonságai, a felhasználó és különböző környezeti változók. De akár egy chroot-olt környezet is használható vele. Illetve jó sebességet is el lehet érni. Profikat megszégyenítő beállításokat nem fogunk itt végezni, de nem is ez a cél.

Az, hogy a PHP-t egy adott felhasználó nevében lehet futtatni, azért lényeges, mert olykor a PHP-nek is tudnia kell fájlokat kezelni. Ehhez viszont kell, hogy legyen rá joga. Amihez pedig legalább a könyvtárak csoportját kell megfelelőre állítani, vagy mindenkinek kell rá jogot adni. Vagy egyszerűen a php-t kell tulajdonosnak kijelölni. Ekkor viszont a saját felhasználóval nem lehet könnyen szerkeszteni.

Ráadásul két teljesen független PHP alkalmazás, akár ( de nem feltétlenül) különböző valós személyek kezében ( chroot nélkül ) képes belelesni vagy akár belemódosítani a másik fennhatósága alatt álló fájlokba. Ha ezt körülményesen is fogalmaztam, annyi érezhető, hogy bonyodalmakat okoz az egyfelhasználós megoldás.

Tesztelés

Hogy ne csak "beszéljünk" erről, mutatok egy példát. Indítsuk el a 2.4-es szervert:

/opt/apache/2.4/bin/apachectl start

Elsőként ellenőrizzük le, hogy jelenleg mi is a felhasználója a PHP-nek! Ezt a következő módon: Készítünk egy whoami.php -t a p5414-es aldomain dokumentum gyökérebe.

nano /var/www/vhosts/vm1/a24/p5414/www/whoami.php

Tartalomként pedig írunk egy sort, ami a shell-t használva kiírja az aktuális felhasználót:

<?php
echo exec('whoami');

Az eredménye nálam "daemon". Ez az Apache felhasználója. Ha lefuttatjuk parancssorban a

ls -la /var/www/vhosts/vm1/a24/p5414/www/

parancsot, hasonló kimenetet ad:

drwxr-xr-x 2 root root 4096 May  1 19:52 .
drwxr-xr-x 4 root root 4096 Apr 20 20:55 ..
-rw-r--r-- 1 root root   14 Apr 21 10:44 index.html
-rw-r--r-- 1 root root   17 Apr 27 16:46 index.php
-rw-r--r-- 1 root root  144 May  5 19:03 whoami.php

Látható, hogy minden fájl és könyvtár tulajdonosa a "root" felhasználó. Ezzel hoztam létre a könyvtárakat és a fájlokat. Készítsünk egy touch.php fájlt, ami csak megpróbál létrehozni egy teszt.txt fájlt:

nano /var/www/vhosts/vm1/a24/p5414/www/touch php

A tartalma

<?php
touch('teszt.txt');

Az eredménye pedig:

Warning: touch(): Unable to create file teszt.txt because Permission denied in /var/www/vhosts/vm1/a24/p5414/www/touch.php on line 3

A PHP-nek nincs hozzá joga. Jó, akkor adjuk át a tulajdoni jogot a mappára a daemon felhasználónak!

chown daemon:daemon /var/www/vhosts/vm1/a24/p5414/www/

Az "ls" parancsot használva most ez látszik az aktuális könyvtárnál:

drwxr-xr-x 2 daemon daemon 4096 May  5 19:12 .

A touch.php pedig hiba nélkül lefut és létrehozza a teszt.txt fájlt.

-rw-r--r-- 1 daemon daemon    0 May  5 19:20 teszt.txt

Viszont innentől minden virtuális hosztnak van hozzá joga. A fájlt csak daemon vagy root userként lehet módosítani, de daemon-ként is csak root-ból lehet belépni. Ha pedig az olvasási jogot is elvenném az idegen felhasználóktól, akkor olvasni is csak így tudnám. Ez akár lehet cél is. Amikor helyi gépen, SSH-n keresztül vagy FTP-n dolgozunk, könnyen kopaszodáshoz vezethet manuális beavatkozással.

Apache 2.4

Most, hogy már remélhetőleg világosabb, miért és hová tartunk, jöhet az első szerver felkészítése mindhárom PHP verzióra. Az 5.3 és 5.4 -es PHP-val még könnyű dolgunk lesz. Az 5.2-nél trükközni kell.

Két modulra mindenképpen szükség lesz, amiket engedélyezni kell a httpd.conf-ban. Ezek a mod_proxy és a mod_proxy_fcgi. Ez teszi lehetővé, hogy megszólítsuk az FPM-et.

nano /opt/apache/2.4/conf/httpd.conf

A

#LoadModule proxy_module modules/mod_proxy.so

és a

#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

sorok elejéről kell kivenni a kettőskeresztet

PHP 5.4.14

Ha megnézzük a phpinfo kimenetét, még "CGI/FastCGI" látható a "ServerAPI" mellett. Ez az FPM beállítása után meg fog változni "FPM/FastCGI" -ra. Lássuk!

Virtuális hoszt konfiguráció

Az előző megoldásoknál is mindig volt pár sor a virtuális hoszt definíciójában, ami valahogyan hivatkozott a használandó PHP-re. Itt most TCP-n keresztül IP és port segítségével történik a kommunikáció. A PHP-hez tartozik egy "php-fpm" program, ami a háttérben figyel adott IP-port párokon. Ezeket hívjuk pool-oknak. Amikhez egyedi beállításokat szabhatunk.

Ahhoz, hogy socket-en keresztül működjön a kommunikáció, meg kéne hackelni az Apache-ot. Erre egy patch-re lenne szükség, amit jómagam nem próbáltam ki, de a következő oldalon írnak róla:
https://issues.apache.org/bugzilla/show_bug.cgi?id=54101

Haladók saját felelősségre ügyeskedhetnek.

Nyissuk meg a p5414 aldomainhez tartozó virtuális hoszt definíció fájlját:

nano /opt/apache/2.4/conf/extra/vhosts/002-p5414.a24.vm1.conf

A <Directory> blokk elé kerüljön a következő sor:

ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.2:9000/var/www/vhosts/vm1/a24/p5414/www/$1

A korábbi, cgi wrapper-t használó megoldáshoz tartozó sorokat törölni lehet. Vagy csak megjegyzésbe tenni. A fenti sor a "ProxyPassMatch" után írt reguláris kifejezésre illeszkedő fájlokat fogja elküldeni az FPM-nek feldolgozásra a jobb oldalon megadott IP-n és porton.

Az IP-port párosoknak minden pool-ban egyedinek kell lennie és nyilván más alkalmazás sem foglalhatja őket együtt. A virtuális hosztok fájljaihoz hasonlóan adtam meg az IP-t. Azaz a fix 127-es után 0.0.2 következik, ahogy a vhost fájl neve is 002-vel kezdődik. A port pedig az alapértelmezett 9000. Ezt persze ugyanígy lehetne a port változtatásával is megoldani.

A port után a futtatandó fájl útvonalát kell írni a szerver gyökeréhez viszonyítva. Ennek a végén egy $1 található, ami a reguláris kifejezésben levő zárójeles rész behelyettesítését jelenti. Abban pedig a / jelet szándékosan tettem a zárójelen kívülre, mivel az útvonal tartalmazni fogja. A $1 előtti útvonal a virtuális hoszt gyökere, így ahhoz képest keres minden fájlt.

Gyanakodva, hogy mi van, ha "../"-rel könyvtárt váltok az url-ben, kipróbáltam, ki lehet-e szökni a gyökérből. De nem lehet.

A világosság kedvéért megmutatom, nekem hogy néz ki a teljes virtuális hoszt definícióm:

<VirtualHost *:80>
    ServerName p5414.a24.vm1
    ServerAlias www.p5414.a24.vm1
     
    DocumentRoot "/var/www/vhosts/vm1/a24/p5414/www"

    ErrorLog "/var/www/vhosts/vm1/a24/p5414/_logs/error.log"
    CustomLog "/var/www/vhosts/vm1/a24/p5414/_logs/access.log" common

    php_flag engine off

#    mod_cgid -vel
#    Action application/x-httpd-php /php/php-5414
   
#   mod_fcgid -vel
#    <FilesMatch "\.php$">
#        SetHandler fcgid-script
#        Options +ExecCGI
#        FcgidWrapper /var/www/cgi-bin/php-5414 .php
#    </FilesMatch>

    ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.2:9000/var/www/vhosts/vm1/a24/p5414/www/$1

    <Directory "/var/www/vhosts/vm1/a24/p5414/www">
        Require all granted
    </Directory>
</VirtualHost>

Ha most újraindítjuk a szervert,

/opt/apache/2.4/bin/apachectl restart

A következő hibaüzenet fogad bármely PHP futtatásakor a p5414.a24.vm1 domainen

Service Unavailable

The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.

Jelzi, hogy a túloldalon az FPM még nem figyel. Így nem tudja lefuttatni a PHP szkripet.

FPM konfiguráció

A telepített PHP könyvtárában van egy "etc" mappa, abban pedig egy "php-fpm.conf.default" nevű fájl. Ez egy alap konfigurációt ad az FPM-hez "ini" szintaktikával. Ahhoz viszont, hogy figyelembe vegye az FPM, át kell másolni php-fpm.conf nevűként egy új fájlba.

cp /opt/php/5.4.14/etc/php-fpm.conf.default /opt/php/5.4.14/etc/php-fpm.conf

Fontos, hogy megmaradjon az eredeti is érintetlenül, ha később vissza kell nyúlni valamiért, amit az élesből már töröltünk. Így NE LECSERÉLJÜK a fájlt, csak másoljuk!

Nem idézem az egész fájlt, mert nagyon hosszú. Viszont a lényeg a következő:

CTRL+W -vel ( nano szövegszerkesztőben ) keressünk rá a [www] sorra! Ez a pool neve. A hozzá tartozó beállítások ez alatt lesznek. A lényeg számunkra az elején van:

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = nobody
group = nobody

; The address on which to accept FastCGI requests.

; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = 127.0.0.1:9000

A "user" és "group" az, ahol a php felhasználóját és csoportját megadhatjuk. A "listen" meghatározza az IP-t és a portot, amin figyel. Ez az, amire a szerver beállításban hivatkoztunk. Megjegyzések nélkül a helyes beállítások a következők:

user = web
group = web

listen = 127.0.0.2:9000

Most viszont el kell indítani az FPM-et is. A PHP könyvtárában az "sbin" könyvtárban levő "php-fpm" programot kellene lefuttatni. FIGYELEM! Csak KELLENE.

/opt/php/5.4.14/sbin/php-fpm

Igen, csak ennyi. Nincs "start" argumentum. Ez okozna is majd gondot, ugyanis a leállításhoz tudni kellene az FPM process azonosítóját. Viszont pid fájl használata nélkül ezt valahogy így lehetne megoldani:

ps aux | grep fpm | grep 5.4.14 | grep master

Majd itt a "root" utáni számot, ami a process id-je, felhasználni a következő módon:

kill -9 1845

Ahol az 1845 nálam az azonosító volt. A PHP fordítása után viszont létrejött egy daemon szkript is, amivel ez leegyszerűsödik. Csak át kell másolnunk a php sbin könyvtárába és futattási jogot kell adni a root usernek hozzá:

cp /opt/php/php-5.4.14/sapi/fpm/init.d.php-fpm /opt/php/5.4.14/sbin/php-fpmd
chmod 0700 /opt/php/5.4.14/sbin/php-fpmd

Ezek után az indítás így néz ki:

/opt/php/5.4.14/sbin/php-fpmd start

A leállítás pedig:

/opt/php/5.4.14/sbin/php-fpmd stop

Vagy újraindítás:

/opt/php/5.4.14/sbin/php-fpmd restart

Tehát indítsuk el most az FPM-et és nézzük meg a whoami.php kimenetét! Nálam már "web" -et ír ki. A phpinfo kimenete pedig a ServerAPI mellett már az "FPM/FastCGI"-t mutatja. Remélem, mindenki hasonló sikerrel járt.

Viszont ezt a hatalmas fájlt végigpásztázni minden alkalommal, amikor bele kell nyúlni bármelyik pool-ba, nem egyszerű mulatság. Mivel a default beállítások le vannak mentve, megtehetjük a következőket:

A php-fpm.conf fájl eleje felé van egy ilyen sor:

;include=etc/fpm.d/*.conf

A pontosvessző a megjegyzés jele. Tehát vegyük ki az elejéről! Ez annyit tesz, hogy az fpm.d könyvtárban beolvassa a pool definíciókat, ahogyan azt a virtuális hosztok leírásánál is hasonlóképpen mutattam. A default "www" pool-ra nem lesz szükség. Így azt teljesen töröljük ki! A törlést "nano" fájlszerkesztővel a [www] sorára állva lehet megoldani a CTRL+K billentyűkombinációt nyomva tartva, amíg el nem fogynak a sorok.

A php-fpm.conf mellett hozzuk létre az fpm.d mappát:

mkdir /opt/php/5.4.14/etc/fpm.d

Majd a pool nevével megegyező névű fájlba mentsük el az első pool leírását! A pool neve legyen a virtuális hoszt neve!

A www lehetett volna a fődomain-, azaz az alap virtuális hoszt pool-ja, de azt megtartjuk arra az esetre, amikor szándékosan a mod_php modullal akarjuk a PHP-t működtetni.

nano /opt/php/5.4.14/etc/fpm.d/p5414.a24.vm1.conf

A tartalma pedig:

[p5414.a24.vm1]

listen = 127.0.0.2:9000
listen.allowed_clients = 127.0.0.2

user = web
group = web

pm = ondemand
pm.max_children = 5

Rendesen lecsupaszítottam a pool tartalmát. A figyelt IP-port párost tartalmazza, a felhasználót és a csoportot, valamint a "pm" és "pm.max_children" opciókat, amik kötelezőek még.

A "pm" a processzek létrehozásának és megszüntetésének módja. A "pm.max_children" pedig azt mondja meg, hány gyerekfolyamatot indíthat egyszerre maximum.

Az "ondemand" lehetőség a PHP 5.3 óta létezik. A processzeket nem hozza létre előre az induláskor, csak szükség esetén. És ha már nem kellenek, megszünteti őket

Extraként még a "listen.allowed_clients" opcióval megadtam, hogy kizárólag a 127.0.0.2 -es IP-ről fogadjon el az FPM kéréseket. Ez nem feltétlenül egyezik meg a listen után írt IP-vel, de ha 127.x.x.x IP-t választunk, akkor a remote IP is az lesz.

Ha a php.ini beállításait kellene módosítani, azt így lehet:

php_value[nev] = érték

Végül adjuk át a dokumentum gyökeret és az összes tartalmát a web felhasználónak és csoportjának:

chown -R web:web /var/www/vhosts/vm1/a24/p5414/www

PHP 5.3.24

A beállítások nagyon hasonlók. Virtuális hoszt kiegészítése és új pool létrehozása kell. Valamint az init script másolása.

Virtuális hoszt konfiguráció

A p5324-es aldomainhez tartozó virtuális hoszt definíciót

nano /opt/apache/2.4/conf/extra/vhosts/003-p5324.a24.vm1.conf

kiegészítjük a <Directory> blokk előtt a következő sorral:

ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.3:9000/var/www/vhosts/vm1/a24/p5324/www/$1

Újraindítjuk a szervert.

/opt/apache/2.4/bin/apachectl restart
FPM konfiguráció

Másoljuk a default fájlt:

cp /opt/php/5.3.24/etc/php-fpm.conf.default /opt/php/5.3.24/etc/php-fpm.conf

Kitöröljük a php-fpm.conf következő sora elől a pontosvesszőt.

;include=etc/fpm.d/*.conf

Töröljük a [www] sorától a pool teljes tartalmát a CTRL+K billentyűkombináció segítségével.

Létrehozzuk az fpm.d mappát és a pool definíciót:

mkdir /opt/php/5.3.24/etc/fpm.d
nano /opt/php/5.3.24/etc/fpm.d/p5324.a24.vm1.conf

A tartalma

[p5324.a24.vm1]

listen = 127.0.0.3:9000
listen.allowed_clients = 127.0.0.3

user = web
group = web

pm = ondemand
pm.max_children = 5

Majd másoljuk az init szkriptet:

cp /opt/php/php-5.3.24/sapi/fpm/init.d.php-fpm /opt/php/5.3.24/sbin/php-fpmd
chmod 0700 /opt/php/5.3.24/sbin/php-fpmd

Majd adjuk át a dokumentum gyökeret és az összes tartalmát a web felhasználónak és csoportjának:

chown -R web:web /var/www/vhosts/vm1/a24/p5324/www

PHP 5.2.17

Virtuális hoszt konfiguráció

Ez még ugyanaz, mint eddig.

nano /opt/apache/2.4/conf/extra/vhosts/004-p5217.a24.vm1.conf

A <Directory> blokk elé beszúrandó sor:

ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.4:9000/var/www/vhosts/vm1/a24/p5217/www/$1
FPM konfiguráció

És most jön a neheze. Ugyanis PHP 5.2-nél még nem létezett beépített FPM. De az FPM készítői gyártottak hozzá egy patch fájlt, ami a PHP forráskódjában változtatandó sorokat tartalmazza. Ennek alkalmazására létezik a "patch" program, tehát kézzel semmit nem kell majd módosítani. A patch fájlt viszont be kell szerezni a http://php-fpm.org/downloads/ oldalról és sajnos újra kell fordítani az 5.2.17-es verziójú PHP-t. Nagy gond nincs, mert például a bemásolt php.ini nem fog eltűnni, tehát csendben újrafordul a PHP és folytatjuk a munkát.

Feltételezve, hogy a php forráskódja már ( vagy még ) ott van a "/opt/php/php-5.2.17" könyvtárban, a következőket kell tenni:

cd /opt/php/php-5.2.17
wget http://php-fpm.org/downloads/php-5.2.17-fpm-0.5.14.diff.gz
gunzip php-5.2.17-fpm-0.5.14.diff.gz

patch -p1 < php-5.2.17-fpm-0.5.14.diff

Az utolsó sor a patch alkalmazása. A balra mutató relációs jeltől jobbra a használandó fájl neve. A "-p1" pedig leveszi az első per jelet a fájlok útvonala elől a patch fájlban. Ha belenéznénk, ilyesmiket látnánk, hogy:

---a/configure
+++b/configiure

Az "a" jelöli az eredeti forrást. A "b" pedig a változtatottat. A többi az útvonal. Az "a" és "b" nem zavar semmit. De nekünk csak a "configure" kell "/" nélkül, mert épp a forráskód könyvtárában állunk.

A PHP telepítésénél létrehozott configure szkriptet másoljuk át "conf-php52-fpm" néven.

cp conf-php52 conf-php52-fpm

Írjuk hozzá a lista végére akár, vagy az --enable-fastcgi után, hogy "--enable-fpm"!

Ha a lista végére kerül, akkor az előző sor végére kell egy backslash. Ha korábban szúrjuk be, akkor pedig rögtön utána kell a backslash.

Most pedig újrafordítjuk:

./conf-php52-fpm
make clean
make
make install

Szembetűnő különbség, hogy nem egy ".default" végű fpm konfigurációs fájl jön létre, hanem rögtön "php-fpm.conf". Ezt rögtön mentsük el default-nak!

cp /opt/php/5.2.17/etc/php-fpm.conf /opt/php/5.2.17/etc/php-fpm.conf.default

A másik szembetűnő, és egyben bosszantó is, hogy itt még nem "ini" szintaktika volt, hanem "xml". Másik konfigurációs fájl include-jára pedig nincs lehetőség. Talán ez kevésbé probléma, mivel ez a PHP verzió már elavult. És csak át nem írható, régi programok futtatására érdemes használni.

A pool definiciója a <section name="pool"> blokkban található. Minden pool ezzel kezdődik és tartalmazza blokkon belül a nevét és annak beállításait is. Ha úgy tetszik, ez a section blokk felel meg egy egyedi fájlnak az előző két PHP verziónál.

Egyetlen ilyen blokk van. Keressük meg és töröljük ki, majd a következőt írjuk a helyére:

<section name="pool">
   <value name="name">p5217.a24.vm1</value>
   <value name="listen_address">127.0.0.4:9000</value>
   <value name="allowed_clients">127.0.0.4</value>
   <value name="user">web</value>
   <value name="group">web</value>
   <value name="pm">
       <value name="style">static</value>
       <value name="max_children">5</value>
   </value>
   <value name="php_defines">
        <value name="doc_root">/var/www/vhosts/vm1/a24/p5217/www</value>
        <value name="cgi.fix_pathinfo">0</value>
        <value name="auto_prepend_file">/var/www/fix_pathinfo.php</value>
   </value>
</section>

A fenti sorokhoz egy kis magyarázat. Minden "value" blokkokból áll, amiknek van egy nevük a "name" attribútumban és egy értékük.

  • name: A pool neve
  • listen_address: Az IP-port páros
  • allowed_clients: Azok az IP-k vesszővel elválasztva, ahonnét hajlandó kéréseket fogadni az FPM.
  • user és group: A felhasználó és csoport.
  • pm: A processzek tulajdonságai.
    • style: Mint az előző verzióknál a szimpla "pm" opció. De itt csak "static" és "apache-like" lehet.
    • max_children: A max gyermekfolyamatok száma
  • php_defines: A PHP beállításai.
    • doc_root: Bár a ProxyPassMatch után itt is megadtuk az útvonalát a fájlnak, ezt figyelmen kívül hagyja az 5.2.17-es PHP-hez tartozó FPM. Meg kell adni a doc_root-ot, hogy ahhoz képest az url-ben kért fájlt tudja feldolgozni.
    • cgi.fix_pathinfo: Ez az opció a php.ini-ben 1-esre van állítva. Azaz helyreállítja a SCRIPT_FILENAME környezeti változóban az útvonalat. Tehát például nem kerül bele a CGI wrapper útvonala, sem pedig a proxy-ra utaló hivatkozás. Mint jelen esetben megtörténik. Ha viszont ezt bekapcsolva hagyjuk, akkor egyáltalán nem fog működni az FPM.
    • auto_prepend_file: Ez egy kis trükk lesz, ugyanis ezzel minden php program előtt lefuttathatunk egy másik PHP szkriptet, ami beállítja a $_SERVER és $_ENV változókban a SCRIPT_FILENAME értékét. Felhasználva azt az útvonalat, amit maga az FPM figyelmen kívül hagy.

Létrehozzuk a fix_pathinfo.php-t

nano /var/www/fix_pathinfo.php
<?php
$_SERVER['SCRIPT_FILENAME'] = $_ENV['SCRIPT_FILENAME'] = preg_replace('/^proxy:fcgi:\/\/\d+\.\d+\.\d+\.\d+:\d+(\/.*)/', '$1',$_SERVER['SCRIPT_FILENAME']);

FONTOS, hogy a végére ne tegyünk php záró címkét és a nyitó címke előtt se legyen szóköz, sortörés. Így elkerülhetjük a HTTP fejlécek akadályozását.

Jó hír, hogy ennek a verziónak a php-fpm programja már eleve ismeri a start, stop, restart argumentumokat. Valójában ez a fajta FPM egy kicsit más. Belenézve a szkriptbe, látható, hogy a php-cgi binárissal dolgozik közvetlenül. Ha elindítjuk az FPM-et:

/opt/php/5.2.17/sbin/php-fpm start

És megnézzük a hozzá tartozó index.php-t, benne a phpinfo kimenetével, a "ServerAPI" továbbra is "CGI/FastCGI" maradt. Viszont a beállítás sikeressége leellenőrizhető azzal, ha rákeresünk az "Environment" -re és, látjuk a "web" user-t és a home könyvtárát.

Végül adjuk át a dokumentum gyökeret és az összes tartalmát a web felhasználónak és csoportjának:

chown -R web:web /var/www/vhosts/vm1/a24/p5217/www

Apache 2.2

Ha az 5.2-es PHP FPM-esítése nehéz volt, akkor ez hasonló lesz. Ugyanis le kell fordítani külön a mod_fastcgi modult is. Amit a www.fastcgi.com oldalról kell letölteni. Utána pedig egy ProxyPassMatch helyett FastCGIExternalServer -t fogunk használni. Ráadásként pedig egy halom nem létező dologra kell hivatkozni a virtuális hoszt beállításánál.

Modulokat viszont mást nem kell engedélyezni.

mod_fastcgi beállítása

cd /opt/apache
wget http://www.fastcgi.com/dist/mod_fastcgi-SNAP-0910052141.tar.gz
tar xf mod_fastcgi-SNAP-0910052141.tar.gz
cd mod_fastcgi-SNAP-0910052141
/opt/apache/2.2/bin/apxs -n fastcgi -o mod_fastcgi.so -i -a -c *.c

Ezzel létre is jön a modul a modules könyvtárban és a httpd.conf -ban is engedélyezve lesz.

A "-o" és az utána levő név elhagyásával az utolsó sorban "fcgi_buf.so" néven jönne létre a modul.

Verziófüggetlen beállítások

És itt jött el a nem létezők ideje. De nézzük sorban. Elvileg a virtuális hosztokban ilyesmit is elég volna írni:

FastCGIExternalServer /dokumentumgyokér -socket /tmp/socketfájl

Igen, itt nem IP-t és portot, hanem socketet használunk. Útvonalként pedig a hoszt dokumentum gyökerét adjuk meg, bár más is lehetne, csak hosztonként egyedi legyen.

Az IP-s megoldás is használható volna a "-socket" helyett a "-host" paraméter megadásával. De a 2.4-es szerverben megadott porttal való ütközést el kell kerülni.
FastCGIExternalServer /dokumentumgyökér -host 127.0.0.2:9001

Igen ám, de így az összes fájlra érvényes lesz, hogy az FPM kezelje. Beleértve a html fájlokat is. Az eredménye így a html fájlok esetén egy "Access denied" üzenet lenne a tartalom helyett. Ahogy az fcgid-nél is korlátozni kellett PHP fájlokra az FPM-et, itt is ezt kellene tenni. Viszont A FastCGIExternalServer direktíva nem írható be a FilesMatch blokkba. Ami megnehezíti a megoldást és itt jön valami eszement trükközés.

A httpd.conf végére a következőt kell írni:

# fpm-hez
<Location "/$">
    Order Deny,Allow
    Deny from all
    Allow from env=REDIRECT_STATUS
</Location>

Action application/x-httpd-php /$

Itt a Location utáni "/$" egy útvonalat jelent, ami nem létezik. Nincs ilyen mappa se fájl. Mégis megmondjuk rá, hogy mindenki számára legyen tiltott a megnyitása webről. Viszont megengedjük, hogy amennyiben létezik egy REDIRECT_STATUS nevű környezeti változó, akkor hozzáférhető legyen. Ez kell a webszervernek.

Ez után egy Action sor következik, ahol egy handler és egy útvonal lenne a paraméter. A handler gyakorlatilag akármi lehetne. "kismacska" is. Csak legyen hozzárendelve a .php kiterjesztésű fájlokhoz. Egy korábbi fejezetben ezt már megtettem. De emlékeztetőül: A fenti "Location" blokk elé még kerüljön be a következő, akinél nincs ott:

<FilesMatch "\.php$">
   SetHandler application/x-httpd-php
</FilesMatch>

Na most az Action utáni útvonal ugyanaz a nem létező útvonal, amit a Location-ben meg kellett adni. Ez is lehetne bármi hamis elérési út. De a dollár jel épp elég valószínűtlen, hogy valós url-ben szerepelne. Márpedig ezt el lehetne érni böngészőből is, ha azt le nem tiltottuk volna épp a Location blokkban.

Valójában az történik, hogy előre hivatkozunk egy nem létező útvonalra, ami valamikor létrejön a virtuális hosztokon. Persze ott is csak virtuálisan. Az Action egy bizonyos handler hatására ( amit itt kiterjesztés alapján állítottunk be ) átadja a kért fájl kezelését egy programnak. Na ez a program lesz az, amit a virtuális hoszton beállítunk. Vagyis elérjük, hogy a rendszer azt lássa, hogy az útvonalon egy program van. Aki még emlékszik a CGI wrapperekre, ott is hasonló történt. De ott a fájlok tényleg léteztek.

PHP 5.4.14

Virtuális hoszt konfiguráció
nano /opt/apache/2.2/conf/extra/vhosts/002-p5414.a22.vm1.conf

A <Directory> blokk elé most elég ennyit írni:

#   fpm-hez
Alias /$ /var/www/vhosts/vm1/a22/p5414/$
FastCGIExternalServer /var/www/vhosts/vm1/a22/p5414/$ -socket /tmp/php-fpm-p5414.a22.vm1.sock

Itt az Alias -szal egy url-t lehet átirányítani egy, a fájlrendszeren levő útvonalra, aminek nem kell a dokumentum gyökérben lennie. Átirányítjuk egy szintén nem létező fájlra. Azért, mert a FastCGIExternalServer virtuálisan elkészíti ezt a fájlt úgy, hogy ezt írjuk első paraméterének. Majd pedig a socket útvonalát. Teljes a káosz. Tudom. De sajnos így működik.

Ez a virtuális program lehetne bármilyen útvonalon, viszont egyedinek kell lennie. Erre pedig pont alkalmas, ha a virtuális egyedi útvonalaihoz kötjük.

Szerver újraindítása

/opt/apache/2.2/bin/apachectl restart
FPM konfiguráció

Az 5.4.14 -es PHP -hez kell még egy pool:

nano /opt/php/5.4.14/etc/fpm.d/p5414.a22.vm1.conf

A tartalma

[p5414.a22.vm1]

listen = /tmp/php-fpm-$pool.sock

user = web
group = web

pm = ondemand
pm.max_children = 5

Érdekesség, hogy a pool nevét a $pool változóval helyettesítem be a socket fájl nevébe.

Idítsuk újra az 5.4.14-es PHP-hez tartozó FPM-et:

/opt/php/5.4.14/sbin/php-fpmd restart

Fájlrendszer felhasználó és csoport beállítása

chown -R web:web /var/www/vhosts/vm1/a22/p5414/www

PHP 5.3.24

Virtuális hoszt konfiguráció
nano /opt/apache/2.2/conf/extra/vhosts/003-p5324.a22.vm1.conf

A <Directory> blokk elé a következő sorok kerülnek:

#   fpm-hez
Alias /$ /var/www/vhosts/vm1/a22/p5324/$
FastCGIExternalServer /var/www/vhosts/vm1/a22/p5324/$ -socket /tmp/php-fpm-p5324.a22.vm1.sock

Szerver újraindítása

/opt/apache/2.2/bin/apachectl restart
FPM konfiguráció

Az 5.3.24 -es PHP -hez kell még egy pool:

nano /opt/php/5.3.24/etc/fpm.d/p5324.a22.vm1.conf

A tartalma

[p5324.a22.vm1]

listen = /tmp/php-fpm-$pool.sock

user = web
group = web

pm = ondemand
pm.max_children = 5

Az előzőhöz képest tehát csak a pool neve változott.

Indítsuk újra az 5.3.24-es PHP-hez tartozó FPM-et:

/opt/php/5.3.24/sbin/php-fpmd restart

Fájlrendszer felhasználó és csoport beállítása:

chown -R web:web /var/www/vhosts/vm1/a22/p5324/www

PHP 5.2.17

Itt most újra az XML-lel kell dolgozni, de a nehezén már túl vagyunk.

Virtuális hoszt konfiguráció
nano /opt/apache/2.2/conf/extra/vhosts/004-p5217.a22.vm1.conf

A <Directory> blokk elé a következő sor kerül:

#   fpm-hez
Alias /$ /var/www/vhosts/vm1/a22/p5324/$
FastCGIExternalServer /var/www/vhosts/vm1/a22/p5324/$ -socket /tmp/php-fpm-p5324.a22.vm1.sock

Szerver újraindítása

/opt/apache/2.2/bin/apachectl restart
FPM konfiguráció

Az 5.2.17 -es PHP -hez kell még egy pool:

nano /opt/php/5.3.24/etc/php-fpm.conf

Egy új section-t vegyünk fel. Aminek a tartalma:

 <section name="pool">
   <value name="name">p5217.a22.vm1</value>
   <value name="listen_address">/tmp/php-fpm-p5217.a22.vm1.sock</value>
   <value name="user">web</value>
   <value name="group">web</value>
   <value name="pm">
         <value name="style">static</value>
         <value name="max_children">5</value>
   </value>
 </section>

Nem használható a $pool változó, de cserébe nem is kell a php_defines részt megadni. Az FPM működik és a SCRIPT_FILENAME értéke is jó.

Indítsuk újra az 5.2.17-es PHP-hez tartozó FPM-et:

/opt/php/5.2.17/sbin/php-fpm restart

Fájlrendszer felhasználó és csoport beállítása:

chown -R web:web /var/www/vhosts/vm1/a22/p5217/www

Összegzés

Ezzel készen is vagyunk. Van tehát 3 PHP verziónk FPM-mel meghajtva, 2 Apache HTTPD webszerverrel mögöttük. A webszervereket eddig is könnyen indítottuk és állítottuk le, a PHP 5.3 és PHP 5.4 -es FPM-hez viszont a forráskönyvtárból átmásolhattuk az indító szkriptet. PHP 5.2-höz erre nem volt szükség, de az IP-port-os megoldásnál a Proxy modullal külön kellett gondoskodni a SCRIPT_FILENAME változó helyességéről.

Nyilván még ez is lehetne szebb és könnyebben kezelhető, hiszen most minden programot ( PHP, Apache, MySQL ) külön kell elindítani. Ezek kezelése viszont nem ennek a fejezetnek a témája. Később azonban szó lesz róla.

Bár a felhasználót és csoportot beállítottuk, a fájlok jogosultságait nem módosítottuk. Így az olvasási jog megmaradt a PHP fájlokra más felhasználók számára is. Tesztkörnyezetben ez nem különösebben probléma, de éles helyzetben már az. Viszont a lehetőség már megvan az olvasási jog megvonására. Illetve chroot alkalmazásával fájljogok nélkül kivédhető ez a probléma.

Bár most mindegyik virtuális hoszt a web felhasználó tulajdonában van, ez igény szerint különböző is lehetne. A pool definícióban kell megváltoztatni a felhasználót és csoportot, valamint a fájlrendszeri tulajdonosi viszonyról kell gondoskodni.

Végül mentsük el a virtuális gépet "wtk-vm1-v8-fpm" néven. v8, mert már több, mint a sima cgi megoldások, de az fpm-et még mögé írhatjuk, hogy mégis beszédesebb legyen a fájlnév. Hiszen ez egy nagyobb állomása a tesztkörnyezet elkészítésének.

Források

Kategóriák: 
Megosztás/Mentés

Hozzászólások

Anonymous képe

Ez egy nagyon hasznos és átfogó leírás, nekem nagyon sokat segített! Köszönöm a munkádat vele!

Rimelek képe

Köszönöm a visszajelzést! Örülök, hogy segítettem.

Anonymous képe

próbáltam a leírások alapján a php 5.6.15 és a legújabb php 7.0.0RC8 verziót telepíteni
5.6 ppa-ból, 7.0 tar.gz forrásból, az 5.6 működik, de a 7.0.0 -val nem tudom működésre bírni, ebben kellene segítség,
köszönöm!
a teljes kívánt konfig: /apache 2.4.17 +php 5.6.15 (FPM, PDO_mysql) + php 7.0.0 (FPM, PDO_mysql) + MySQL5.6]/ (a mysql-le és phpmyadminnal való összehangolás se tiszta :/ )

Rimelek képe

Üdv. Ha adsz több infót arról, hogy meddig jutottál, mit jelent, hogy nem tudtad működésre bírni, hibaüzenet volt-e, stb, akkor talán tudok segíteni.

Anonymous képe

Anonymous képe

a php7.0.0-t ez alapján telepítettem:
https://www.howtoforge.com/tutorial/install-php-7-on-debian-8-jessie/

a libjpeg62-turbo-dbg nem lett telepítve, mert nem találta
a
pid = run/php-fpm.pid
helyett
pid = run/php7-fpm.pid
-t állítottam be, hogy egyértelműbb legyen

listen = 127.0.0.1:8999 helyett:
listen = 127.0.0.2:8999

insserv php-7.0.0-fpm ( insserv: parancs nem található)

systemctl daemon-reload ( systemctl: parancs nem található)

$ sudo service apache2 restart && sudo service php5-fpm stop && sudo service php-7.0.0-fpm start
[sudo] password for adam:
* Restarting web server apache2 [ OK ]
php5-fpm stop/waiting
Starting php-fpm ................................... failed

Rimelek képe

Ránézek majd később. Most nincs időm, de addig esetleg próbáld meg megtalálni, hova logol az fpm ilyenkor, ha nem tud elindulni. Vagy hogy indítható úgy, hogy kiírja az okát. Mintha lenne valami kapcsoló. De nem vagyok benne biztos.

Anonymous képe

ez a vonal már tárgytalan, elkezdtem nulláról az egészet a leírások alapján:
http://rimelek.hu/webtesztkornyezet/apache-telepitese
http://rimelek.hu/webtesztkornyezet/mysql-telepitese
http://rimelek.hu/webtesztkornyezet/php-telepitese

apache gond nélkül indul mindkettő (párhuzamosan is)
php5.6 és php7 is indul külön-külön modulként (apache 2.4-ben)
mysql is megy

az FPM beállítással viszont gondok vannak:
mindent beállítottam ahogy kell (szerintem), de mikor indítanám a php-fpm-et akkor hibával leáll:
# /opt/apache/2.4/bin/apache24 -k start
# /opt/php/5.6.16/sbin/php-fpmd start
Starting php-fpm [01-Dec-2015 22:24:28] ERROR: [pool www] unable to set listen address as it's already used in another pool 'p5616_test.a24.home'
[01-Dec-2015 22:24:28] ERROR: failed to post process the configuration
[01-Dec-2015 22:24:28] ERROR: FPM initialization failed
failed

ugyanennyit ír be az error.log-ba is + mindenhol a php Apache modulként

a beállítások:
http://pastebin.com/q9ZvcQ6w
http://pastebin.com/38RgLFsL
http://pastebin.com/wi4k3C5W

Rimelek képe

Minden FPM pool-nak különböző IP-port kombinációt kell beállítani. Nem figyelhet a www és a p5616_test.a24.home is ugyanazon az ip-n, ugyanazon a porton.

Nálad a php-fpm.conf-ban is be van állítva egy pool. Én a példában kiszedtem abból a fájlból az alapbeállítást és csak a külön fájlokban voltak beállítva fpm pool-ok az etc/fpm.d mappában.

Anonymous képe

már közel a cél, de még mindig nem tökéletes:
apache 2.4.17 + php 5.6.16 FPM gond nélkül megy
apache 2.2.31 + php 5.6.16 FPM (mod_fastcgi befordítva) -> Error 500

apache 2.2 mod_fcgid php-vel működött, FPM-el már nem
konfig:
mod_fcgid(ezzel megy): http://pastebin.com/k48bhsCp
fpm (error 500): http://pastebin.com/w0KUkLsh

+ még egy cikk hiba (http://rimelek.hu/webtesztkornyezet/apache-php-cgi/fpm):
A PHP-nek nincs hozzá joga. Jó, akkor adjuk át a tulajdoni jogot a mappára a daemon felhasználónak!

chmod daemon:daemon /var/www/vhosts/vm1/a24/p5414/www/

> "chown -R" kell a "chmod" helyett!

Rimelek képe

Köszönöm a hibajelentéseket! Hm... Lehet, te vagy az első, aki végigolvassa. Javítottam.

Az 500-as hiba megfejtéséhez viszont kellene a hiba oka. A szerver logban valószínűleg jobban részletezi, hogy mi okozta az 500-as hibát. Sajnos annyira nem megy fejből a dolog, hogy config alapján kiszúrjam mindig a problémát.

Anonymous képe

virtualhost (apache 2.2) error_log: http://pastebin.com/DWwv00qN

apache 2.2 error_log vége (a teljes több, mint 24ezer sor - lehet nem ártana próbálkozás közben néha ránézni :) )
http://pastebin.com/XsahsFx3

php-fpm log-ban semmi hiba nincs

Rimelek képe

Nem biztos, csak gyanú, de én a példáimban nem a document root-ban definiáltam a virtuális útvonalat, hanem azon kívül, a www mappa mellett. Neked a public a documentroot-od és a public-ban van a dollár útvonal is definiálva. Mikor bejön egy kérés, amit a szerver a php-nek ad át, akkor a (domain)/$ -ra irányítja át, ami viszont a docroot-on belül van és oda lett definiálva a virtuális fájl is a dollárral.

Így próbáld:

    Alias /$ /opt/www/vhost/teszt/$
    FastCGIExternalServer /opt/www/vhost/teszt/$ -socket /tmp/php-fpm-teszt.localhost22.home.sock
Anonymous képe

külön van:
a22 docroot: /opt/www/a22/public
a24 docroot: /opt/www/a24/public
vhost: /opt/www/vhost/...

de kis keresés után meg van a megoldás:
a virtualhost pool konfigba hozzá kell adni a következő 3 sort és működik :)
listen.owner = www-data
listen.group = www-data
listen.mode = 0666

Anonymous képe

most már csak a phpMyAdmin-t kellene beilleszteni a rendszerbe, hogy mindegyikkel működjön (ja még a php 7 nincs telepítve, de szerintem túlságos különbség nem lesz a konfigban az 5.6-hoz képest :) )