Apache2 mit PHP FastCGI
Aus Gentoo Linux Wiki
| Installationsmethoden • LiveCDs • Kernel & Hardware • Laptops & Notebooks • Portage • System • Netzwerke & Services • X • Software • Anderes • alphabetischer HOWTO Index |
Inhaltsverzeichnis |
[Bearbeiten] Vorbereitung
Zuerst müssen wir mal Root sein, damit wir auch installieren und konfigurieren können.
[Bearbeiten] Use-Flags
PHP muss mit dem USE-Flags cgi gebaut werden, zusätzlich sollte man noch discard-path und force-cgi-redirect übersetzt werden; beides sind lokale USE-Flags und Sicherheitsfeatures. Welche weiteren Module man in PHP benötigt, sollte jeder selbst herausfinden und entscheiden. Das MySQL Flag ist wohl häufig benötigt.
| Datei: /etc/portage/package.use |
dev-lang/php -apache2 cgi cli discard-path force-cgi-redirect |
Das USE-Flag apache2 wird für PHP an sich nicht benötigt, da wir PHP ja als CGI betreiben wollen. Für mod_fastcgi (und z.B. subversion, wenn man das installieren will) benötigt man es aber. Global bleibt es also aktiviert, für PHP jedoch deaktiviert.
| Datei: /etc/make.conf |
USE="apache2 ... fastcgi ... mysql ... php ... unicode ..." |
[Bearbeiten] Installation
Nachdem jetzt die richtigen USE-Flags gesetzt sind, können wir das ganze installieren.
| Code: Installation von Apache, PHP und mod_fastcgi |
# emerge -va apache php mod_fastcgi |
Das war dann eigentlich auch schon alles. PHP ist ein recht großes Paket, und je nachdem welche Funktionen man noch aktiviert hat, kann das Kompilieren schon mal ein Weilchen dauern.
[Bearbeiten] Konfiguration
Am Ende dieses Abschnitts möchten wir einen Webserver haben, der PHP per FastCGI aufruft und bei Bedarf pro VHost eigene PHP-Konfigurationen nutzen kann.
[Bearbeiten] Verzeichnisstruktur
Webpräsenzen legt Gentoo standardmäßig unterhalb /var/www ab. Das DocumentRoot jedes VHost liegt dann unter /var/www/VHOST/htdocs. Will man webapp-config nutzen (z.B. für phpmyadmin, gallery, wordpress o.ä.), sollte man sich daran auch halten.
Wir benötigen in jedem Vhost ein Verzeichnis für die Konfiguration, z.B. conf. Dort kann dann für jeden Vhost eine php.ini abgelegt werden. Falls die dort nicht zu finden ist, wird automatisch die php.ini im Verzeichnis /etc/php/cgi-php5/ verwendet.
Zusätzlich wird noch für jeden VHost eine Start-Datei benötigt. Dazu erzeugen wir ein Unterverzeichnis.
| Code: Verzeichnis-Struktur |
cd /var/www mkdir -p php-fcgi-scripts/localhost mkdir localhost/conf |
[Bearbeiten] PHP-Start-Skript
In dem eben angelegten Verzeichnis für Skripte müssen wir für jeden VHost ein Start-Skript erstellen, welches PHP-CGI-Instanzen startet.
| Datei: /var/www/php-fcgi-scripts/localhost/php-fcgi-starter |
#!/bin/sh PHPRC="/var/www/localhost/conf" export PHPRC PHP_FCGI_CHILDREN=4 export PHP_FCGI_CHILDREN exec /usr/bin/php-cgi |
Wir geben mit der Variable PHPRC den Pfad zur Konfigurationsdatei an. Wichtig dabei ist, dass nur der Pfad angeben wird, der Dateiname am Ende wird nicht mit angegeben. PHP_FCGI_CHILDREN gibt an, wieviele Kinder gestartet werden sollen. So viele PHP-Prozesse wird man nach dem Start des Apachen im System sehen können. Schlussendlich wird noch das PHP-Binary aufgerufen. Bei Bedarf werden von FastCGI neue Prozesse gestartet. Man kann die Angabe der Kindprozesse auch weglassen, dann werden alle benötigten Kinder bei Bedarf gestartet, was eine erhöhte Last (und Verzögerung) beim ersten Aufruf zur Folge haben kann.
Nun müssen wir uns eine Sache überlegen: Wie benötigen einen normalen User, dem die Daten im Default Vhost (localhost) gehören sollen. Diesen Nutzer müssen wir gleich angeben.
[Bearbeiten] Globale Konfiguration
Bei der Installation legt mod_fastcgi eine Datei in /etc/apache2/modules.d ab. Diese Datei müssen wir nun editieren.
| Datei: /etc/apache2/modules.d/20_mod_fastcgi.conf |
<IfDefine FASTCGI>
<IfModule !mod_fastcgi.c>
LoadModule fastcgi_module modules/mod_fastcgi.so
</IfModule>
<IfModule mod_fastcgi.c>
AddHandler fastcgi-script .fcg .fcgi
FastCgiWrapper /usr/sbin/suexec2
FastCgiServer /var/www/php-fcgi-scripts/localhost/php-fcgi-starter -user DEFAULT_VHOST_USER -group DEFAULT_VHOST_GROUP
AddHandler php-fastcgi .php
Action php-fastcgi /cgi-bin/php-fcgi-starter
AddType application/x-httpd-php .php
<Location /cgi-bin/php-fcgi-starter>
SetHandler fastcgi-script
Options +ExecCGI
</Location>
AddDirectoryIndex index.php
</IfModule>
</IfDefine>
|
Was haben wir hier definiert? Wir haben den Wrapper definiert, damit PHP dann als User läuft. Das übernimmt suexec2. Hier gab es auf meinem System noch ein Problem: Der Webserver durfte suexec2 nicht aufrufen. Der Aufruf schien nicht als Root aber auch nicht mit der Gruppe apache zu erfolgen. Genauer konnte ich das nicht eingrenzen, jedoch scheint auf einem Debian-System suexec2 generell mit den Rechten 4755 installiert zu werden.
| Code: Anpassen der Rechte für /usr/sbin/suexec2 |
ls -l /usr/sbin/suexec2 -rws--x--- 1 root apache 13248 Nov 24 00:04 /usr/sbin/suexec2 chmod o+x /usr/sbin/suexec2 ls -l /usr/sbin/suexec2 -rws--x--x 1 root apache 13248 Nov 24 00:04 /usr/sbin/suexec2 |
Nun kann suexec2 auch gestartet werden.
Des Weiteren haben wir ein Start-Skript definiert. Zu den Berechtigungen komme ich später noch. Wir haben außerdem noch festgelegt, wie .php Dateien behandelt werden sollen, dass in dem cgi-bin Verzeichnis CGIs ausgeführt werden dürfen und dass index.php auch als Index-Datei zählt.
Jetzt müssen wir noch fastcgi aktivieren. Dies geschieht so:
| Datei: /etc/conf.d/apache2 |
... APACHE2_OPTS="-D DEFAULT_VHOST -D FASTCGI -D SUEXEC" ... |
[Bearbeiten] VHost-spezifische Konfiguration
Pro Vhost wird eine Konfigurationsdatei benötigt. Wir bearbeiten zuerst die Datei für den Default VHost.
| Datei: /etc/apache2/vhosts.d/00_default_vhost.conf |
NameVirtualHost *:80
<IfDefine DEFAULT_VHOST>
<VirtualHost *:80>
DocumentRoot "/var/www/localhost/htdocs"
<Directory "/var/www/localhost/htdocs">
Options Indexes FollowSymLinks +ExecCGI
AllowOverride None
Order allow,deny
Allow from all
</Directory>
ScriptAlias /cgi-bin/ /var/www/php-fcgi-scripts/localhost/
SuexecUserGroup "DEFAULT_VHOST_USER" "DEFAULT_VHOST_GROUP"
</VirtualHost>
</IfDefine>
|
Wir haben hier also den Pfad zu unserem Startskript angegeben und User/Gruppe, unter dem die Skripte ausgeführt werden sollen, angegeben.
[Bearbeiten] korrekte Rechte
Korrekte Rechte der Dateien sind extrem wichtig. Wenn die Dateien falsche Rechte haben, verweigert suexec2 seinen Dienst.
| Code: Rechteanpassung |
# cd /var/www/php-fcgi-scripts # chown -R DEFAULT_VHOST_USER:DEFAULT_VHOST_GROUP localhost # chmod 755 localhost/php-fcgi-starter # chattr -V +i localhost/php-fcgi-starter # lsattr localhost/php-fcgi-starter # ----i-------- localhost/php-fcgi-starter |
Durch chattr +i erreicht man, dass das Start-Skript nicht geändert werden kann. Nicht einmal von root, dafür muss das immutable Bit erst wieder entfernt werden. Wenn man das nicht macht, könnten Benutzer die Dateien überschreiben und somit durch "böse" Skripte ersetzen und somit die Systemstabilität gefährden.
Wichtig ist auch, dass auch das Verzeichnis des Startskripts dem User gehören muss, sonst gibt es Fehlermeldungen im suexec_log.
Je nach Anwendungsfall kann es gewünscht sein, dass ein Nutzer seine php.ini Datei selbst bearbeiten kann. Dann sollte die globale php.ini ins oben erstellte conf-Verzeichnis des VHosts kopiert werden und die Besitzrechte an den User angepasst werden.
Das htdocs-Verzeichnis des VHost sollte natürlich nun auch dem Nutzer gehören, damit uns das Ganze überhaupt etwas bringt - nämlich Schreibrechte von PHP im DocumentRoot ohne globale Schreibrechte.
[Bearbeiten] Fertigstellen/Fazit
Nun können wir unser Glück versuchen und den Apachen starten. Wenn alles erfolgreich war, sollte das dann so aussehen:
| Code: Apache Start |
# /etc/init.d/apache2 start * Starting apache2 ... [ ok ] |
Mögliche Fehlermeldungen und die mögliche Bedeutung habe sind unten aufgeführt.
Was haben wir also erhalten? Einen Apache Webserver mit FastCGI und PHP. Dies gibt uns die Möglichkeit, PHP als User laufen zu lassen. Die Vorteile:
- Schreibrechte auf die Webpräsenz ohne globale Schreibrechte
- angepasste php.ini Dateien
- Möglichkeit des Einsatzes verschiedener PHP-Versionen pro VHost bzw. sogar innerhalb eines VHosts
[Bearbeiten] Credits, Kommentare, etc ...
[Bearbeiten] Credits
Das HowTo lehnt sich an vor allem an http://www.debianhowto.de/doku.php/de:howtos:sarge:apache2_php-fcgi an. Ich danke den Autoren für dieses Howto.
[Bearbeiten] Fehlermeldungen
Hier sollen einige Fehlermeldungen aufgelistet werden und der mögliche Grund dafür.
| Datei: STDERR |
FastCgiWrapper: "/usr/sbin/suexec2" execute access for server (uid 4294967295, gid 4294967295)
failed: execute not allowed
|
- Grund: Keine Rechte für "other" auf /usr/sbin/suexec2. Die Angaben von uid und gid sind extrem daneben, daran kann man nicht sehen, als welcher Nutzer versucht wird, die Datei aufzurufen.
- Lösung: chmod o+x /usr/sbin/suexec2
| Datei: /var/log/apache2/error_log |
[Sun Nov 26 17:26:03 2006] [warn] FastCGI: server "/var/www/php-fcgi-scripts/localhost/php-fcgi-starter"
(uid 1000, gid 1000) started (pid 24432)
[Sun Nov 26 17:26:03 2006] [warn] FastCGI: server "/var/www/php-fcgi-scripts/localhost/php-fcgi-starter"
(pid 24432) terminated by calling exit with status '120'
|
| Datei: /var/log/apache2/suexec_log |
[2006-11-26 17:26:18]: target uid/gid (1000/1000) mismatch with directory (1000/1000) or program (81/1000) |
- Grund: Die PHP-Start-Datei oder das Verzeichnis gehört nicht dem User, der in der FastCGI- oder VHost-Konfiguration angegeben wurde.
- Lösung: chown -R DEFAULT_VHOST_USER:DEFAULT_VHOST_GROUP /var/www/php-fcgi-scripts/localhost
| Datei: /var/log/apache2/error_log |
[Sat Nov 25 17:23:35 2006] [warn] FastCGI: server "/var/www/php-fcgi-scripts/localhostphp-fcgi-starter"
(pid 8135) terminated by calling exit with status '108'
|
| Datei: /var/log/apache2/suexec_log |
[2006-11-25 17:23:40]: uid: (user/user) gid: (apache/apache) cmd: php [2006-11-25 17:23:40]: cannot run as forbidden gid (81/php) [2006-11-25 17:27:09]: uid: (apache/apache) gid: (apache/apache) cmd: php [2006-11-25 17:27:09]: cannot run as forbidden uid (81/php) |
- Grund: Es wurde ein FastCGI-User mit UID und GID <1000 angegeben. Dies ist nicht erlaubt.
- Lösung: User und Gruppe mit UID/GID >=1000 angeben. Ändern des Besitzers des Skripts nicht vergessen.
| Datei: /var/log/apache2/error_log |
[Sun Nov 26 16:05:02 2006] [error] FastCGI: access for server (uid 4294967295, gid 4294967295) failed:
read not allowed
[Sun Nov 26 16:05:02 2006] [error] FastCGI: can't create dynamic directory "/var/run/fastcgi/dynamic":
access for server (uid 4294967295, gid 4294967295) failed:
read not allowed
|
- Grund: Scheinbar kann kein Socket in dem angegebenen Verzeichnis beim Starten erzeugt werden.
- Lösung: Keine. Ein chmod 777 für das Verzeichnis lässt zwar die Fehlermeldung verschwinden, jedoch wird kein Socket dort abgelegt. Muss man wahrscheinlich ignorieren. Interessanterweise können später beim Aufruf einer Seite und dem damit verbundenen Erzeugen eines FastCGI-Prozesses Sockets in dem bemängelten Verzeichnis angelegt werden. Das scheint also ein Bug während des Startvorgangs zu sein - wohl der gleiche, der auch den Zugriff auf suexec verhindert. Kurzzeitig muss da wohl was unter einem völlig anderem User laufen.
