Apache 2.x z PHP jako FastCGI i xcache

Opis konfiguracji Apache 2.x z PHP uruchomionym jako FastCGI i XCache jako op-code cache.

Cele jakie chcę osiągnąć

  • Używać serwera Apache 2.2 dla jego wielkich możliwości konfiguracyjnych, w przeciwieństwie do serwerów jednowątkowych jak lighttpd czy nginx.
  • PHP działające jako FastCGI dla separacji uprawnień procesów PHP bez narzutu na wydajność.
  • XCache jako op-code cache z cache współdzielonym między procesami PHP tego samego użytkownika.
  • Serwer obsługuje wiele serwerów wirtualnych, każdy innego użytkownika. Ich konfiguracja powinna być od siebie odseparowana.

Rozwiązanie

W internecie można znaleźć mnóstwo informacji na wyżej wymienione tematy osobno, jednak uruchomienie tego jako całość sprawia problemy. Chodzi głównie o XCache w konfiguracji Apache + PHP jako FastCGI. XCache potrafi współdzielić zawartość cache pomiędzy procesami jednak warunkiem jest uruchamianie procesów roboczych przez program php-cgi. W Apache 2.2 standardowy moduł mod_fcgi sam jednak uruchamia programy FastCGI, z których każdy obsługuje jedno żądanie równocześnie i działa na osobnym sockecie nie wiedząc nic o innych. Rozwiązaniem jest użycie innego modułu - mod_fastcgi, który jest dodatkowym modułem, ale dostępnym w wielu dystrybucjach Linuksa jako pakiet. posiada on opcję FastCgiExternalServer, która umożliwia przekazanie żądania do już działającego procesu FastCGI przez UNIXowy socket lub TCP/IP.

Konfiguracja ta jest dość specyficzna i wymaga objaśnień. Proponuję następujące rozwiązanie:

Konfiguracja Apache (VirtualHost)

Oto przykład minimalnej konfiguracji sekcji VirtualHost z objaśnieniami "dziwnych" wpisów.

<VirtualHost *:80>
        ServerName mieszkania-24.pl

        DocumentRoot /home/user/public_html

        # Ta opcja mówi, ze za obsługę (wirtualnego) skryptu /var/www/empty/php-user odpowiedzialny jest program
        # FastCGI, z którym należy się połączyć przez socket unixowy (-socket). Dodatkowo nagłówki autentykacji HTTP
        # mają zostać przesłane.
        FastCgiExternalServer /var/www/empty/php-user -socket /var/lib/php-sock/user -pass-header HTTP_AUTHORIZATION

        # Tworzymy alias aby ułatwić dalszą konfigurację. Robimy to tylko po to aby "wirtualny" plik /var/www/empty/php-user
        # nie musiał być umieszczony w DocumentRoot. (wymagany moduł mod_alias)
        ScriptAlias /fcgi-bin/ /var/www/empty/

        <Directory /home/user/public_html>

                # Pliki .php będą obsługiwane za pomocą handlera php5-script (wymagany moduł mod_mime)
                AddHandler php5-script .php

                # Handler php5-scrip (pliki .php) obsługiwany przez wirtualny skrypt /fcgi-bin/php-user (wymagany moduł mod_action)
                Action php5-script /fcgi-bin/php-user
        </Directory>
</VirtualHost>

A teraz obiecane wyjaśnienia "dziwności" tej konfiguracji:

  • /var/www/empty/php-user to plik, który musi istnieć, ale nie będzie do niczego użyty. Wynika to z budowy Apache/mod_fastcgi i jest niestety uciążliwością, którą w tym przypadku trzeba znieść.
  • /var/www/empty to pusty katalog, który "robi" za nasze /fcgi-bin/. Opcja ScriptAlias powoduje, że nie musimy faktycznie trzymać tego katalogu w DocumentRoot. Używam ScriptAlias zamiast Alias Aby dodatkowo odciąć prawa czytania tego katalogu przed ciekawskimi.

Aby to zadziałało dla większej liczby hostow należy w każdej sekcji VirtualHost użyć innej nazwy skryptu. Apache obsługę plików .php zleci w tej konfiguracji serwerowi FastCGI nasłuchującemu na sockecie /var/lib/php-sock/user. Jak go uruchomić? Tu posługuję się zalecanym w przypadku lighttpd programem spawn-fcgi. Skrypt ułatwiający jego uruchamianie można znaleźć na Setup FastCGI and PHP with individual user permissions (Create a FastCGI start-up script for each user).

Podsumowanie

Nie jest to kompletny opis dla początkujących jak uruchomić PHP jako FastCGI, ale jeżeli masz już podobną konfigurację i chesz ją ulepszyć, to na pewno się przyda.