Willkommen im ersten “echten” Teil meines Workshops!
In diesem Teil werden wir den nginx-Webserver als Basis für unser Projekt installieren und konfigurieren. Vorausgesetzt wird ein Linux-Server mit Debian Squeeze. Im Idealfall handelt es sich um eine “frische” Installation, sodass man sich nicht um Altlasten vorheriger Konfigurationsversuche kümmern muss. Alle Arbeiten werden als Root-Nutzer durchgeführt. Wir werden den nginx-Webserver darauf vorbereiten, Websites auszuliefern und den PHP-Interpreter über den PHP-FPM-Prozessmanager anzusprechen.
Da die Debian-Pakete für nginx schon recht veraltet sind und PHP-FPM in Debian Squeeze noch nicht verfügbar ist, werden wir zuerst die Paketquellen des dotdeb.org-Repositories einbinden, was auch den netten Nebeneffekt hat, dass wir eine aktueller MySQL-Version bekommen. Dotdeb ist übrigens sehr stabil, da braucht man sich keine Sorgen zu machen.
Zuerst fügen wir also die Paketquellen des Dotdeb.org-Repositories in die Datei /etc/apt/sources.list ein:
deb http://packages.dotdeb.org stable all deb-src http://packages.dotdeb.org stable all
Anschließend laden wir den GPG-Key des Repositories herunter und importieren diesen in den Keyring, um die Paketquelle auch nutzen zu können:
wget http://www.dotdeb.org/dotdeb.gpg cat dotdeb.gpg | apt-key add -
Ein abschließends apt-get update && apt-get upgrade sorgt nun dafür, dass die Paketlisten um das neue Repository aktualisiert wird und auch alle bisher installierten Pakete auf den neusten Stand gebracht werden. Nun stellen wir sicher, dass kein anderer Webserver läuft, der auf Port 80 lauscht und installieren den nginx-Webserver sowie den PHP-FPM-Prozessmanager mit allen Abhängigkeiten und starten abschließend den nginx-Webserver.
apt-get install nginx php5 php5-fpm service nginx start
Die globale Konfigurationsdatei von nginx ist die Datei /etc/nginx/nginx.conf. Für jede gehostete Website muss wie bei dem Apache-Webserver ein eigener virtueller Host angelegt werden. Die Dateien für die virtuellen Hosts werden im Verzeichnis /etc/nginx/sites-available/ gespeichert; soll eine Website aktiviert werden, muss deren Konfigurationsdatei in das Verzeichnis /etc/nginx/sites-enabled/ kopiert werden. Nach einem Neustart von nginx steht die Website dann zur Verfügung.
Standardmäßig muss in der nginx.conf nicht viel angepasst werden. Interessant für uns ist lediglich der Wert worker_processes. Dieser Wert gibt an, wie viele Unterprozesse von dem nginx-Masterprozess gestartet werden. Je mehr Arbeitsspeicher ein Server zur Verfügung hat, umso mehr Unterprozesse sollten gestartet werden. Auf diesem Server mit 512MB RAM werden 4 Prozesse gestartet, auf einem anderen Server mit 2GB sind es schon 8. Genaue Richtwerte kann man dafür aber nicht angeben, da die Auslastung nicht nur von der Zahl der Unterprozesse, sondern auch vom Inhalt der gehosteten Seiten abhängt. Hier muss man also ein wenig ausprobieren, um den für sein System besten Wert zu finden.
Dann begeben wir uns ins Verzeichnis /etc/nginx/sites-available/ und legen mit einem Editor unsere Wahl die Datei domain.tld.conf an. Natürlich muss domain.tld sowohl im Dateinamen als auch in der Datei selbst immer durch die echte Domain ersetzt werden. Ich empfehle folgende Konfigurationsdatei als Vorlage:
server { server_name domain.tld www.domain.tld; root /var/www/www.domain.tld/htdocs/; #Nur IPv4: listen 80; #Nur IPv6/Dual Stack: listen [::]:80; listen 80; index index.php index.html; access_log /var/log/nginx/www.domain.tld.access.log; error_log /var/log/nginx/www.domain.tld.error.log; if (-f $request_filename) { break; } location / { try_files $uri $uri/ @domain; } location @domain { fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include /etc/nginx/fastcgi_params; fastcgi_param SCRIPT_NAME /index.php; } location ~ \.php$ { try_files $uri @domain; fastcgi_index index.php; fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include /etc/nginx/fastcgi_params; } location ~ /\.ht { deny all; } #Rewrite-Regel für http://www. statt http:// #if ($host !~* ^(www|subdomain)) { #rewrite ^/(.*)$ $scheme://www.$host/$1 permanent; #} #Rewrite-Regel für WordPress 3.x #if (!-e $request_filename) { #rewrite ^(.+)$ /index.php?q=$1 last; #break; #} }
Natürlich muss der root-Ordner noch den eigenen Bedürfnissen angepasst werden. Bei der Wahl des root-Ordners der Websites empfehle ich /var/www/domain.tld/htdocs für die Hauptseiten und /var/www/domain.tld/subdomains/subdomain1 für Subdomains, wobei subdomains1 exemplarisch für eine beliebige Subdomain steht. Der Ordner /var/www/domain.tld/ muss dabei dem PHP-Benutzer der Website entsprechen, sonst kommt es zu unangenehmen Rechteproblemen. Natürlich muss für jede Subdomain ein eigener vHost angelegt werden. Die Konfigurationsdatei enthält auch schon Rewrite-Regeln für WordPress und eine Regel, um vor die URL automatisch ein “www” zu setzen. Eine Besonderheit ist noch bei der Wahl der listen-Direktive zu beachten. Wenn nur IPv4 auf dem Server verfügbar ist, muss hier listen 80; gesetzt werden. Sobald aber eine IPv6-Adresse zu dem Server geroutet wird – egal ob “IPv6-Only” oder im Dualstack-Betrieb – muss an dieser Stelle listen [::]:80; gesetzt werden, sonst kann nginx sich nicht an den Port binden.
Abschließend speichern wir die Datei und kopieren sie nach /etc/nginx/sites-enabled/. Nach einem Neustart des Webservers mit service nginx restart kann die Website dann aufgerufen werden. Zeit, nginx fit für die Zusammenarbeit mit PHP zu machen!
Prinzipiell ist es mit einem einfachen service php5-fpm start schon getan. Prinzipiell. Allerdings mit einem unschönen Nebeneffekt: PHP wird immer als Nutzer www-data ausgeführt, was genau dann zu Problemen führt, wenn wir etwa über unseren FTP-Nutzer Inhalte in unser Webverzeichnis hochladen und PHP-Nutzer und FTP-Nutzer nicht zusammenpassen. In diesem Fall kann PHP nämlich mit den Dateien, die über den FTP-Account hochgeladen wurden, nicht wirklich viel anfangen. Auch mit der Rechtetrennung bei mehreren vHosts sieht es momentan noch nicht so toll aus, dank PHP-FPM kann man nämlich für jede Website einen eigenen PHP-Nutzer definieren.
Dazu legen wir eine zuerst neue Datei namens /etc/php5/fpm/common.conf mit folgendem Inhalt an:
listen.backlog = -1 listen.allowed_clients = 127.0.0.1 pm = dynamic pm.status_path = /status ping.path = /ping ping.response = pong request_terminate_timeout = 120s rlimit_files = 131072 rlimit_core = unlimited catch_workers_output = yes env[HOSTNAME] = $HOSTNAME env[PATH] = /bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/sbin:/usr/sbin
Die common.conf gilt für alle Websites und deren PHP-Konfigurationen, welche wir gleich anlegen werden. Dann begeben wir uns in das Verzeichnis /etc/php5/fpm/pool.d/ und legen dort eine neue Datei namens domain.tld.conf (natürlich wieder mit dem echten Domainnamen) an. In dieser Datei definieren wir dann u.A. den Benutzer, unter dem diese PHP-Anwendung laufen soll.
[domain.tld] ; one Port for one Website listen = 127.0.0.1:11000 ; uid/gid user = domain_user group = domain_user ; logging request_slowlog_timeout = 5s slowlog = /var/log/slowlog-domain.log ; Choose how the process manager will control the number of child processes. pm.max_children = 10 pm.start_servers = 2 pm.min_spare_servers = 2 pm.max_spare_servers = 4 pm.max_requests = 500 ; inculde defaults include = /etc/php5/fpm/common.conf ; host-specific php ini settings here ;php_admin_value[open_basedir] =
Diese Konfigurationsdatei besagt nun, dass alle PHP-Skripte, die über den Port 9000 an den PHP-Interpreter übergeben werden, unter dem Benutzer domain_user laufen. Dieser User sollte im Idealfall natürlich existieren und z.B. dem FTP-Nutzernamen entsprechen. Wenn man eine weitere Website eines anderen Benutzers hosten will, dann nutzt man wieder diese Konfigurationsdatei als Vorlage, trägt aber als Portnummer z.B. 9001 ein. Auch der Benutzername muss natürlich wieder angepasst werden. In der vHosts-Datei der neuen Website muss bei dem Wert fastcgi_pass natürlich auch die erhöhte Portnummer eingetragen werden, sonst können PHP und nginx nicht miteinander kommunizieren. Nach einem Neustart von php5-fpm und nginx ist die Konfiguration abgeschlossen – nginx und PHP sind einsatzbereit.