Schlank, schnell, vielseitig und einfach zu konfigurieren: Nginx bringt alles mit, was man sich von einem modernen Webserver wünscht. Kein Wunder, dass das Multitalent immer weiter zu Apache aufholt.
Zwar dominiert Apache mit Marktanteilen von über 60 Prozent noch immer den Webserver-Markt, doch seit knapp vier Jahren schickt sich mit Nginx [1] eine feine, schnelle Alternative an, dem Marktführer Anteile abzuluchsen. Im Juni 2012 wurden laut der Netcraft Web Server Survey [2] weltweit bereits über 10 Prozent der Webseiten von Nginx ausgeliefert – ein grandioser Aufstieg, wenn man bedenkt, dass der aus Russland stammende Webserver bis vor kurzem noch ziemlich unbekannt war.
Nginx wurde bereits 2002 von dem Russen Igor Sysoev entwickelt. Ursprünglich war er dafür gedacht, die Webseiten von Rambler.ru auszuliefern. Das tat der unter einer BSD-Lizenz stehende Server dann auch mit beeindruckender Leistung. Neben der Performance punktet Nginx auch, indem er sich modular einsetzen sowie leicht konfigurieren lässt und durch geringen Ressourcenverbrauch glänzt. Der Webserver kann Anfragen nicht nur direkt beantworten, sondern auch als Reverse-Proxy für seine Kollegen dienen, etwa für Apache.
Schnell installiert
Nginx liegt in den Repositories aller gängigen Distributionen. Die Installation solcher fertig geschnürter Pakete ist zwar zweifelsohne bequem, bietet aber nicht immer das Bestmögliche: Anders als bei Apache gilt es die zu verwendenden Module und Funktionen bei Nginx schon beim Übersetzen des Quellcodes anzugeben, denn sie werden direkt beim Kompilieren integriert. Verwenden Sie Binärpakete einer Distribution, entlocken Sie Nginx mit nginx -V die beim Übersetzen berücksichtigten Module.
Spätestens, wenn ein Modul fehlt, das Paket zu viele unnötige Komponenten als Ballast mitschleppt oder Nginx topaktuell sein soll, lohnt es sich, den Webserver aus den Quellen zu übersetzen. Nachdem Sie die Quellen [3] der derzeit neuesten Version 1.2.1 heruntergeladen haben, entpacken Sie diese mit tar -xzf nginx-1.2.1.tar.gz und wechseln in das neu entstandene Verzeichnis. Die Installation erfolgt mittels ./configure, make und (als root) make install.
Mit ./configure --help erhalten Sie eine Übersicht aller möglichen Optionen für Configure. So prüfen Sie beispielsweise, ob die Konfiguration alle gewünschten Module integriert respektive die unerwünschten außen vorlässt: Standardmäßig sind beispielsweise das SSL-Modul oder IPv6-Unterstützung deaktiviert. Außerdem können Sie mithilfe bestimmter Optionen von der Standardkonfiguration abweichende Pfade setzen. Neben den Core-Modulen existieren noch viele Module von Drittanbietern [4], die Nginx zwar nicht offiziell unterstützt, die aber die Funktionalität des schnellen Webservers erhöhen.
Standardmäßig landet Nginx im Verzeichnis /usr/local/nginx/. Dort lagern dann sowohl die ausführbaren Binaries als auch die Konfigurations- und Protokolldateien. In vielen Fällen residiert jedoch /usr/local/ auf der Root-Partition. Wenn diese aufgrund vieler temporärer Dateien zuläuft und sich das System instabil verhält, liegt es nicht unbedingt auf der Hand, auf /usr/local/nginx/ als mögliche Quelle des Übels zu kommen.
Daher sind Konfigurationsdateien in der Regel in /etc/ beziehungsweise Protokolle in /var/log/ besser aufgehoben. Das regeln Sie entweder gleich über die Schalter --conf-path=Pfad, --error-log-path=Pfad und --http-log-path=Pfad oder später über symbolische Links. Das sinngemäß gleiche gilt für temporäre Dateien (--http-client-body-temp-path und --http-fastcgi-temp-path), die Sie auf /tmp/ zeigen lassen sollten.
Um zu prüfen, ob die Installation geklappt hat, hilft ein /usr/local/nginx/sbin/nginx -v -t. Spuckt Nginx daraufhin die Versionsnummer und einen positiven Bescheid über einen erfolgreichen Selbsttest aus, steht dem Start des Webservers nichts mehr im Wege.
Indem Sie Nginx aus den Quellen installieren, erhalten Sie zwar einen taufrischen Webbrowser, aber es fehlt das Startskript, mit dem sich der Server bequem beim Rechnerstart in Stellung bringen, neu starten, neu laden oder beenden lässt. Auf der Heft-DVD sowie als Download finden Sie ein entsprechendes Skript für Debian und Ubuntu [5], das sie unter /etc/init.d als nginx ablegen.
Rasant einrichten
Nginx ist fast ebenso schnell eingerichtet, wie Sie es installiert haben. In der Konfigurationsdatei (beziehungsweise den Dateien, wenn die Konfiguration einzelner Server separat erfolgen soll) gilt es in der Regel nur noch wenige Änderungen vorzunehmen. Die wichtigste Konfigurationsdatei, nginx.conf, liegt – sofern Sie bei der Installation keinen anderen Pfad gesetzt haben – unter /usr/local/nginx/conf/. Stammt Nginx aus dem Distributionsfundus, findet sie sich möglicherweise auch unter /etc/nginx/.
Sie konfigurieren den Webserver in drei oder vier (mit Mailproxy) Modulen: main, events, http und mail. Bis auf das Main-Modul stehen alle Modul-Konfigurationen als sogenannte Blöcke innerhalb geschweifter Klammern, Strichpunkte schließen die einzelnen Anweisungen ab. Es gibt auch noch ein Ein Konfigurationsmodul, das aber nichts weiter tut, als sich um das Einbinden externer Dateien zu kümmern, wodurch sich die die Konfiguration aufteilen und damit übersichtlicher gestalten lässt.
Nginx besteht aus einer einzigen Binärdatei. Der Server startet, sofern nicht anders gewünscht, einen Masterprozess mit Root-Rechten als Daemon. Dieser schickt anschließend eine Reihe Worker-Prozesse unter anderen Nutzer- und Gruppenrechten (gewöhnlich www oder www-data) ins Rennen, welche die anfragenden HTTP-Clients bedienen. Hier bietet es sich an, pro CPU-Kern einen Worker-Prozess zu starten. Die zugehörigen Parameter daemon, user und worker_processes gehören zu den wichtigsten Anweisungen im Main-Modul.
In den Anweisungen für das Events-Modul legen Sie fest, wie viele gleichzeitige Verbindungen ein Worker bearbeitet, welches Ereignis-Modell er dazu nutzt oder ob Nginx alle eingehenden Verbindungen auf einmal akzeptiert. Mit der Anzahl der gleichzeitigen Verbindungen sollten Sie experimentieren: Liegt der angegebene Wert zu niedrig, lehnt der Server eventuell Anfragen ab, ist er zu hoch, kann das System Abstürzen. Listing 1 zeigt eine kommentierte Beispielkonfiguration für die Module Main und Events.
Listing 1
# /etc/nginx/nginx.conf
# als Daemon laufen
daemon on;
# User, der Worker-Prozess ausfuehrt
user www-data www-data;
# Anzahl Worker-Prozesse, einer pro CPU-Core
worker_processes 4;
events {
# Anzahl simultaner Verbindungen
worker_connections 1024;
use epoll;
}
Als letztes wichtiges und umfangreichstes Modul vor einem ersten Test gilt es das HTTP-Modul einzurichten. Es gliedert sich in die Blöcke http, server und location (Abbildung 1). Angaben im Block http bestimmen die HTTP-Eigenschaften. Sie wirken sich auf auf alle server-Blöcke aus, die jeweils einen virtuellen Host des Webservers definieren. Die innerhalb der der server-Direktiven stehenden location-Blöcke beeinflussen nur einzelne Verzeichnisse. Auch wenn Nginx mehrere http-Blöcke erlaubt, sollten Sie sich auf einen beschränken: Dadurch halten Sie einerseits die Konfigurationsdatei lesbarer, andererseits verhindert es, dass sie Anweisungen versehentlich überschreiben und so die Fehlersuche erschweren.
Viele HTTP-Direktiven sind bereits mit sinnvollen Werten vorbelegt. Zu den Anpassungen, die für alle virtuellen Hosts (V-Hosts) gelten sollen, zählen wahrscheinlich die Werte für Timeouts, das Caching und die Gzip-Komprimierung auszuliefernder Webseiten. Kürzere Timeouts als die gängigen 60 bis 75 Sekunden bieten sich beispielsweise bei hochfrequentierten Webseiten an, die wenig Nutzer-Interaktionen erfordern. Clientseitiges Caching eignet sich ideal für Seiten, die sich selten ändern. Die Gzip-Komprimierung lässt sich auf bestimmte Dateitypen beschränken. Bei bereits komprimierten Dateien (typischerweise etwa Grafiken oder MP3s) würde eine wiederholte Kompression nur Rechenzeit kosten, ohne nennenswerte Vorteile zu bringen.
Ein Beispiel für globale http-Direktiven zeigt Listing 2. Es integriert die Datei mime.types, nach deren Vorgaben Nginx verschiedene Dateitypen unterschiedlich behandelt. Erkennt der Server ein Typ nicht, liefert er die Datei als application/octet-stream aus. Mit sendfile on halst Nginx die Verwaltung der Datei-Übertragungen dem Kernel auf. Der Server setzt Keep-Alive-Verbindungen schon nach 30 anstelle der standardmäßigen 60 Sekunden zurück.
Bei der Gzip-Komprimierung wurde zwischen schneller, aber schlechter Kompression (1) und bester, aber zeitaufwändiger Kompression (9) die goldene Mitte gewählt. Die Kompression greift auch Dann, wenn die HTTP-Anfrage über einen Proxy abgesetzt wurde. Zudem komprimiert der Server neben text/html auch weitere textlastige Dateitypen, während Grafiken und Audio-Dateien außen vor bleiben. log_not_found off; verhindert, dass Nginx jede Anfrage nach einer nicht vorhandenen Datei zeit- und platzraubend protokolliert. Diese Anweisung gilt nicht nur für fehlende Webseiten, sondern auch für die gern und oft vergessenen Dateien robots.txt und favicon.ico.
Listing 2
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 30;
gzip on;
gzip_comp_level 5;
gzip_proxied any;
gzip_types text/css text/javascript text/xml text/plain application/xml application/xhtml+xml application/x-httpd-php application/x-httpd-fastphp application/rss+xml application/javascript application/x-javascript ;
log_not_found off;
include sites-enabled/*;
}
Jetzt kann es an die virtuellen Hosts gehen. Listing 3 zeigt eine sehr einfache server-Direktive: Nginx lauscht auf Port 80 und schaut, sobald eine Anfrage eingeht, im Verzeichnis /var/www/ nach, ob er sie bedienen kann. Im Zweifelsfall liefert er die index.htm(l) aus, sofern es eine solche gibt. Es bietet sich an, für jede gehostete Domain eine eigene Konfigurationsdatei anzulegen und diese dann einzubinden (siehe vorletzte Zeile in Listing 2). Die beim Apache gern geübte Praxis, V-Hosts im Verzeichnis sites-available/ einzurichten und dann über einen Softlink ins Verzeichnis sites-enabled/ zu verlinken, funktioniert auch mit Nginx sehr gut.
Listing 3
server {
listen 80;
server_name localhost;
root /var/www;
index index.html index.htm;
}
Mit der bis hierhin erstellten, einfachen Konfiguration können Sie Nginx über den Befehl usr/local/nginx/sbin/nginx -t prüfen lassen, ob er die getätigten Einstellungen klaglos akzeptiert. Treten keine Fehler auf starten Sie den Server anschließend mit /etc/init.d/nginx start. Sobald Sie im Browser http://localhost/ aufrufen, sollte Nginx die index.html auf den Schirm holen.
PHP, Caching und Denies
Etwas komplizierter, aber auch realitätsnäher gibt sich Listing 4. Hier kommen auch Caching für statische Dateien, PHP sowie Rewrite-Regeln ins Spiel.
Um in Scriptsprachen wie PHP, Python oder Perl implementierte dynamische Seiten auszuliefern, greift Nginx auf FastCGI zurück. Im Zusammenspiel mit PHP hat sich dazu in der Vergangenheit PHP-FPM [6] etabliert. In Listing 4 übergibt Nginx die Verarbeitung von PHP an den FastCGI-Process-Manager, der auf einem Unix-Socket lauscht. Bei derartigen Lösungen gilt es darauf zu achten, dass entsprechende PHP-Instanzen beim Serverstart geladen werden. Falls Sie PHP-FPM aus dem Repository der Linux-Distribution installiert haben, sollten die zugehörigen Startskripte bereits eingerichtet sein; anderenfalls fällt ein wenig Nacharbeit an.
Listing 4
server {
listen 80;
server_name meine_domain.de;
root /var/www/meine_domain.de/;
index index.php;
location / {
if !-e $request_filename) {
rewrite ^ /index.php last;
}
}
location ~* \.php$ {
fastcgi_pass unix:/tmp/php.socket;
fastcgi_param SCRIPT_FILENAME /var/www/meine_domain$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
include fastcgi_params;
}
# Caching
location ~* (css|js|png|jpe?g|gif|ico)$ {
expires max;
}
location ~ /include/* {
deny all;
return 404;
}
}
Die location-Blöcke ermöglichen es Nginx, ausgewählte Dateien und Verzeichnisse speziell zu behandeln. Anstelle einfacher Verzeichnisangaben lassen sich auch komplexe Muster verwenden, die Nginx dann nur auf wenige Dateien anwendet. Über einen Location-Modifikator (siehe Tabelle “Location-Modifikatoren”) teilen Sie dem Webserver mit, wie er das folgende Muster zu behandeln hat. So gilt beispielsweise location ~* \.php$ für alle Dateien, die auf .php, .PHP, .pHp, … enden.
Location-Modifikatoren
| Modifikator | Beschreibung |
|---|---|
| kein Modifikator | Die URI (einfacher String) muss mit dem vorgegebenen Muster beginnen. |
| = | Die URI (einfacher String) muss dem Muster genau entsprechen. |
| ~ | Nginx behandelt den folgende regulären Ausdruck schreibweisenabhängig (case-sensitive). |
| ~* | Nginx behandelt den folgenden regulären Ausdruck schreibweisenunabhängig (case-insensitive). |
| ^ | Die URI muss mit dem folgenden Muster beginnen. Sobald ein Treffer gelandet wurde, hört Nginx auf, nach weiteren Mustern zu suchen. |
| @ | Ein benannter Location-Block, der intern von Nginx aufgerufen wird, aber für Clients nicht erreichbar ist. |
Im Beispiel aus Listing 4 animiert Nginx die Browser, statische Inhalte wie Bilder, CSS- und Javascript-Dateien solange wie möglich im Browser-Cache zu halten. Dadurch verringern sich bei wiederholten Seitenbesuchen des Clients Datenvolumen und Ladezeiten. Ein weiteres, für die Praxis wichtiges Beispiel ist der Block location ~ /include/*: Er legt fest, dass Clients keine im Verzeichnis /include/ abgelegten Dateien laden dürfen. Versuchen Sie es trotzdem, speist der Server sie mit einem Fehler 404 (Not Found) ab.
Rewrites
Viele dynamische Webseiten verwenden kryptische URIs wie etwa http://www.site.de/?dir=foo&file=bar&comment=baz. Sie sehen nicht nur gruselig aus und sind schlecht zu merken, sondern wirken sich auch ungünstig auf die Suchmaschinenoptimierung aus. Hier helfen Rewrite-Regeln, die hässlichen URIs zu verschönern. Um die obige URI in die lesefreundlichere Form http://www.Site.de/foo/bar/baz zu bringen, verwenden Sie die Anweisung
rewrite ^/(.*)/(.*)/(.*)$ /?dir=$1&file=$2&comment=$3;
Hier verkörpern die regulären Ausdrücke (.*) jeweils einen Parameter und werden mit $1, $2, $3 verarbeitet. Ähnliche Regeln helfen auch dabei, Besucher restrukturierter Webseiten an die richtige Stelle weiterzuleiten, statt sie mit einer Fehlermeldung zu vergraulen. Nehmen wir an, Sie haben die Seite /robinhood.php in das Verzeichnis /sherwood/ verschoben: Dann sorgt die Rewrite-Regel
rewrite ^/robinhood.php$ /sherwood/robinhood.php permanent;
dafür, dass Besucher die Seite über Lesezeichen und Suchmaschinen weiterhin erreichen und beim nächsten Besuch via HTTP-Statuscode 301 (Moved Permanently) erfahren, dass Sie die Seite dauerhaft verschoben haben. Lassen Sie dagegen das permanent weg, liefert Nginx den Statuscode 302 (Found) aus, was signalisiert, dass Sie die Seite nur temporär verschoben haben und daher Lesezeichen sowie indizierte URIs weiter gelten.
Neben den Parametern in der URI kann Nginx für die Rewrites auch verschiedene Variablen [7] auswerten, beispielsweise Werte in GET-Anfragen ($arg_PARAMETER), den HTTP-User-Agent ($http_user_agent) oder den Referer ($http_referer). Durch Auswerten des HTTP-User-Agents biegen Sie unter anderem Anfragen von Smartphones auf mobile Seiten um (Listing 5).
Listing 5
location / {
if ($http_user_agent ~* '(Android|iPhone|BlackBerry)') {
set $mob_request '1';
}
if ($mob_request = '1') {
rewrite ^.+ http://mobil.meine_domain.de/$uri;
}
}
Pimp my Nginx
Nginx ist von Natur aus schon sehr leistungsstark. Möchten Sie dem Server zu noch mehr Geschwindigkeit verhelfen, erledigen Sie das mit zusätzlichen Werkzeugen wie Memcached [8]. Dabei handelt es sich um ein skalierbares, verteiltes Memory-Object-Caching-System für dynamische Webseiten, das nach dem Key-Value-Prinzip arbeitet. Der Vorteil von Memcached: Es hält dynamisch erzeugte Webseiten im Hauptspeicher vor. Statt bei einer Anfrage erneut eine Seite zu generieren, greift Nginx auf die gepufferte Page zurück und liefert die Seite so um ein Vielfaches schneller aus.
TIPP
Um zu prüfen, ob Memcached Nginx tatsächlich Feuer unter dem Hintern macht, nehmen Sie am besten ein Lasttest-Werkzeug zuhilfe. Zu den geeigneten Kandidaten zählen etwa Apache JMeter, OpenWebLoad, Http_load oder Httperf. Letzteres ist ein kleines, einfach zu bedienendes Kommandozeilenwerkzeug aus den HP Research Labs, das für einen schnellen Test vollkommen ausreicht [12]. Möchten Sie ihre Installation mit aufwändigeren Testszenarien konfrontieren, greifen Sie stattdessen zu Apache JMeter [13].
Auf den meisten Systemen müssen Sie Memcached erst noch aus dem Repository der Distribution installieren oder aus den Quellen übersetzen. Anschließend ergänzen Sie den Block location ~* \.php$ des zu puffernden V-Hosts um die Zeilen aus Listing 6. Sie legen fest, dass die angefragte URI als Memcached-Key dient. Generiert der Server die Seiten auf Basis von GET-Parametern, ersetzen Sie $uri durch $request_uri. Die Direktice memcached_pass gibt an, wo der Memcached-Server zu finden ist. Wie schon bei PHP-FPM kommt auch hier wieder ein Unix-Socket zum Einsatz. Das hat den Vorteil, dass kein TCP-Overhead anfällt und kein Server-Port geöffnet wird. Der Nachteil: Memcached muss dazu auf dem selben Rechner laufen.
Da Memcached Key-Value-basiert arbeitet und nicht weiß, welche Art Value es ausliefert, dient hier text/html als Default-Typ. Behalten Sie stattdessen den von Nginx als Standard voreingestellten Wert application/octet-stream bei, werden die von Memcached gelieferten Daten wie ein Download behandelt – was meist nicht im Sinne des Webmasters sein dürfte. Hat Memcached einen Eintrag mit passenden Schlüssel gespeichert und den zugehörigen Wert ausgeliefert, gibt es einen Statuscode 200 (OK) an Nginx weiter. Existiert kein Key-Value-Paar, resultiert daraus der Statuscode 404 (Not Found). In dem Fall soll Nginx in den Block location @not_cached springen, der die im ursprünglichen Block ~* \.php$ vorhandenen Anweisungen für den FastCGI-PHP-Handler enthält.
Listing 6
set $memcached_key $uri; memcached_pass unix:/tmp/memcached.socket; default_type text/html; error_page 404 = @not_cached #127.0.0.1:11211;
Für einen ein separaten Memcached-Server müssen Sie den Unix-Socket durch die entsprechende Server:Port-Kombination ersetzen. Sind gar mehrere Server verfügbar, leistet das Upstream-Modul [9] wertvolle Dienste wie etwa ein Load-Balancing (Listing 7). Falls Sie von dieser Option Gebrauch machen möchten, tragen Sie als der Wert hinter memcached_pass den Namen der Upstream-Konfiguration anstatt eines einzelnen Servers oder Sockets ein.
Listing 7
upstream memcached_cluster {
server ip_memcached_1:11211;
server ip_memcached_2:11211;
server ip_memcached_3:11211;
}
Das standardmäßig in Nginx enthaltene Memcached-Modul hat den Nachteil, dass es keine Key-Value-Paare an Memcached übergeben kann und so darauf angewiesen ist, dass die Anwendungen oder ein Skript den Cache füllen. Steht weder das einen noch das andere zur Verfügung,, lohnt sich ein Blick auf das NginxHttpMemcModule [10] oder das Enhanced Nginx Memcached Module [11].
Fazit
Nginx und lässt sich dank seines modularen Aufbaus für viele Einsatzszenarien optimieren. Die Konfiguration gestaltet sich einfach und übersichtlich. Eine gute Dokumentation und ein umfangreiches Wiki kompensieren den Mangel an Fachbüchern zu dem russischen Webserver. Um das Maximale aus Nginx herauszuholen, sollten Sie mit den Optionen experimentieren. Sollen dynamische Skriptsprachen zum Einsatz kommen, müssen sie diese in die Experimente mit einbeziehen.
Mit Nginx macht dem Apache ein leistungsfähiger Webserver Konkurrenz, der sich zurecht immer größerer Beliebtheit erfreut. Als eventbasierter Server kommt er mit wenigen Prozessen aus und verbraucht kaum System-Ressourcen, was ihn auch zu einem Kandidaten für betagte oder weniger gut ausgebaute Rechner macht. Er lässt sich einerseits dazu nutzten, um auf dem Server liegende Seiten direkt auszuliefern, andererseits kann er auch als Reverse-Proxy für bereits existierende Webserver wie Apache Httpd, Tomcat oder Tornado fungieren.
Infos
[1] Nginx: http://www.nginx.org
[2] Netcraft Web Server Survey: http://news.netcraft.com/archives/2012/06/06/june-2012-web-server-survey.html
[3] Nginx-Download: http://www.nginx.org/en/download.html
[4] Module von Drittanbietern: http://wiki.nginx.org/3rdPartyModules
[5] Nginx-Init-Skript: http://www.linux-user.de/Downloads/2012/08/
[6] PHP-FPM: http://php-fpm.org
[7] Nginx-Variablen: http://wiki.nginx.org/HttpCoreModule#Variables
[8] Memcached: http://memcached.org
[9] HttpUpstreamModule: http://wiki.nginx.org/HttpUpstreamModule
[10] NginxHttpMemcModule: http://wiki.nginx.org/NginxHttpMemcModule
[11] Enhanced Nginx Memached Module: https://github.com/bpaquet/ngx_http_enhanced_memcached_module
[12] Httperf: http://www.hpl.hp.com/research/linux/httperf/
[13] Apache JMeter: http://jmeter.apache.org/






