Schnell, ressourcenschonend und leicht zu konfigurieren – dank dieser Attribute eignet sich der Webserver Nginx nicht nur für High-Traffic-Websites.
Das Apache-Projekt hat mittlerweile etliche Jahre auf dem Buckel und schleppt entsprechenden Ballast mit. Performance-Probleme und eine nicht immer ganz einfache Konfiguration der etablierten Software leisteten Geburtshilfe für neue Webserver-Projekte wie Lighttpd und Nginx, die nun beginnen, dem Platzhirsch das Wasser abzugraben. Vor allem Nginx [1] macht in der letzten Zeit immer häufiger von sich reden. Stark frequentierte Webseiten, wie beispielsweise WordPress.com, Sourceforge.net oder Youporn.com setzen auf die Software.
So jung ist der unter einer BSD-Lizenz stehende Nginx jedoch nicht: Bereits 2002 entwickelte der Russe Igor Sysoev die Software und setzte sie zum Betrieb der bereits damals gut besuchten Webseite Rambler.ru ein. Inzwischen ist die “Engine X” gereift und erfreut sich zunehmender Beliebtheit. Im Januar 2011 kam sie laut der Netcraft Web Server Survey auf einen Marktanteil von 7,5 Prozent [2].
Neben guter Performance zeichnet sich Nginx durch hohe Modularität, einfache Konfiguration und geringen Ressourcenverbrauch aus, so dass er sich als Alternative für den Betrieb auf betagter Webserver-Hardware qualifiziert. Nginx beantwortet nicht nur Anfragen nach Webseiten, sondern arbeitet bei Bedarf als Reverse-Proxy für den Apache oder als Mail-Proxy.
Installation
Der Webserver gehört zum Bestand der meisten Distributionen und findet so mithilfe der Standardtools ohne großen Aufwand seinen Weg ins System. Wer jedoch die aktuelle Version oder spezielle Module benötigt, kommt nicht darum herum, zu den Quellen [3] zu greifen und selbst Hand anzulegen. Hier gilt es zu beachten, dass Sie Module nicht wie beim Apache separat hinzufügen können, sondern gleich beim Kompilieren integrieren müssen.
Sie richten den Server mittels des klassischen Dreischritts ./configure, make, make install. Obwohl Nginx standardmäßig eine Reihe sinnvoller Module und Voreinstellungen enthält, lohnt sich ein vorhergehendes ./configure --help. Zum einen finden sich dort in der Vorgabe deaktivierte Module, wie die für Mehrkernsysteme interessanten Google Performance Tools [4], andererseits legen Sie bereits in den an configure übergebenen Parametern fest, wo das Programm später Log- und PID-Dateien ablegt.
Listing 1 zeigt eine Parameterübergabe, bei der die Konfigurationsdateien im Verzeichnis /etc und Logdateien in /var/log landen. Darüber hinaus teilen Sie dem Programm auf diese Weise mit, dass es mit den Rechten des Nutzers www-data läuft, HTTPS (http_ssl_module) unterstützen sowie die Module RealIP (falls Nginx Anfragen von Proxys empfängt) und Image-Filter (um JPG-, GIF- und PNG-Bilder transformieren zu können) einbinden soll. Zudem stehen die Funktionen der Google Performance Tools bereit.
Eventuell müssen noch einige Pakete wie SSL-Entwicklerdateien, die Libpcre3 oder Zlib1g nachinstallieren. Anschließend übersetzen und installieren Sie Nginx, was selbst auf alten Rechnern oder auf Netbooks innerhalb weniger Sekunden gelingt. Wenn nicht anders angegeben, sollte der Webserver bei Erfolg im Verzeichnis /usr/local/nginx/ zu finden sein.
Listing 1
$ ./configure --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --pid-path=/var/run/nginx/nginx.pid \ --lock-path=/var/run/nginx.lock \ --user=www-data \ --group=www-data \ --http-log-path=/var/log/nginx/access.log \ --http-client-body-temp-path=/tmp/nginx/ \ --http-fastcgi-temp-path=/tmp/nginx/fastcgi/ \ --http-uwsgi-temp-path=/tmp/nginx/uwsgi/ \ --http-scgi-temp-path=/tmp/nginx/scgi/ \ --with-http_ssl_module \ --with-http_realip_module \ --with-http_image_filter_module \ --with-google_perftools_module
Konfiguration
Nginx bringt die kleine, übersichtliche Konfigurationsdatei /etc/nginx/nginx.conf mit, an der Sie in der Regel nur noch wenig ändern müssen. Listing 2 zeigt eine Konfiguration, die sich auf verschiedenen Rechnern im Alltag bewährt hat. Einer davon ist ein alter Pentium III mit 768 MByte RAM, der verschiedene Subdomains einer Universitätseinrichtung verwaltet, der andere ein Sheevaplug mit 1,2 GHz Taktrate und 512 MByte RAM, der als Entwicklermaschine seinen Dienst verrichtet.
Listing 2
# /etc/nginx/nginx.conf
# User, der Worker-Prozess ausfuehrt
user www-data www-data;
# Anzahl Worker-Prozesse
worker_processes 1;
# Als Daemon laufen
daemon on;
events {
worker_connections 256;
use epoll;
}
Die Konfigurationsdatei gliedert sich in mehrere Modulkategorien, in denen Sie Anpassungen vornehmen können:
- das Haupt-Modul enthält Angaben zum Verwalten der Prozesse, dem Logging und den Sicherheitseinstellungen;
- das Ereignis-Modul steuert die Netzwerkfunktionen, wie etwa Queues;
- das HTTP-Modul umfasst Einstellungen für Gzip-Komprimierung, Caching und HTTP Authentication, und
- das Mail-Modul enthält alle Angaben, um Nginx als Mail-Proxy einzusetzen.
Geschweifte Klammern fassen alle Angaben eines Moduls zu einem Block zusammen, eine Ausnahme macht lediglich das Main-Modul. Einzelne Zeilen schließen Sie jeweils mit einem Semikolon ab. Um Nginx sinnvoll konfigurieren zu können, sollten Sie wissen, wie der Webserver Anfragen entgegennimmt: Wenn Sie Nginx starten, läuft zunächst lediglich der sogenannte Master-Prozess. Er nimmt keine Anfragen von Clients entgegen, sondern startet gegebenenfalls Worker-Prozesse, die sich um die eingehenden Anfragen kümmern.
Über worker_processes stellen Sie ein, wie viele Requests zu einem jeweils neuen Prozess führen. Hier bietet es sich an, auf Mehrkernsystemen pro Prozessorkern einen Prozess zu starten. Wie viele Verbindungen jeder der Prozesse verwaltet, steuern Sie mittels des Parameters worker_connections im Abschnitt events. Die Anzahl der Worker-Prozesse und -Verbindungen richtet sich nach der Leistungsfähigkeit des Servers. Anhaltspunkte als Basis für eigene Versuche liefert die Tabelle “Varianten”.
Varianten
| Prozessorkerne | 1 bis 2 | 4 | >= 8 |
| Arbeitsspeicher | < 2 GByte | 4 bis 8 GByte | > 8 GByte |
| Anfragen pro Sekunde | 1 | 30 bis 50 | 500 bis 1000 |
worker_processes |
1 bis 2 | 4 | 8 |
worker_connections |
128 bis 256 | 1024 | 8192 |
multi_accept |
on |
off |
off |
Der Parameter multi_accept gibt an, ob Nginx alle in der Queue des Worker-Prozesses ankommenden Anfragen auf einmal annimmt. Ihr besonders Augenmerk verdienen darüber hinaus die Parameter worker_priority und worker_cpu_affinity. Die worker_priority steuert die Priorität der Worker-Prozesse. Die möglichen Werte entsprechen jenen des Nice-Befehls, also von -20 bis 19, wobei ein kleinerer Wert einer höheren Priorität entspricht.
Mittels worker_cpu_affinity legen Sie fest, welcher Worker-Prozess auf welchem CPU-Kern arbeitet. Angenommen, Nginx läuft auf einem Quadcore-System und startet vier Prozesse: Dann würde worker_cpu_affinity 0100 0100 0010 0001 die Prozesse 1 und 2 dem zweiten Kern aufhalsen, der dritte Prozess liefe auf dem dritten Kern und Prozess vier auf dem vierten. Allgemein ausgedrückt gibt es für jeden Worker-Prozess einen Ziffernblock, dessen Länge der Anzahl der CPU-Kerne entspricht. In diesem setzen Sie eine Eins für die CPU, der Sie einen Prozess zuteilen wollen. Alle anderen stehen auf Null.
Haben Sie alle Einstellungen vorgenommen, bringen Sie den Server auf den Weg. Dazu reicht es, die nginx.conf um einige Zeilen zu erweitern beziehungsweise die Standard-Datei anzupassen. Listing 3 zeigt eine Beispielkonfiguration, bei der Nginx auf Port 80 lauscht, angefragte Dateien im Verzeichnis /var/www/ sucht und eine index.html oder index.htm ausliefert.
Listing 3
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65 20;
server {
listen 80;
server_name localhost;
location / {
root /var/www;
index index.html index.htm;
}
}
}
Jetzt gilt es nur noch, eine index.html im Verzeichnis /var/www/ abzulegen und zu testen, ob Nginx funktioniert. Bevor Sie den Server starten, untersuchen Sie am besten noch die Konfiguration via /usr/local/nginx/sbin/nginx -t auf Fehler. Tauchen hier keine Probleme auf, steht dem Start mit /usr/local/nginx/sbin/nginx nichts mehr im Weg, und die Testseite sollte im Browser erscheinen (Abbildung 1).

Abbildung 1: Um einen Server mit Nginx zum Leben zu erwecken, genügen wenige Zeilen in der Konfigurationsdatei.
Wenn Sie den Server mit dem Schalter -s reload aufrufen, dann liest er die Konfiguration neu ein. Der Parameter -s quit beendet den Webserver mittels Quit-Signal, über -s stop beenden Sie ihn mit einem SIGTERM. Haben Sie in die Konfigurationsdatei zwischen zwei Befehlen versehentlich fehlerhafte Änderungen eingefügt, gehen alle Befehle ins Leere. In diesem Fall bringt ein Test Licht ins Dunkel.
Läuft alles wie erwartet, ergänzen Sie den HTTP-Block in der Konfiguration um einige Zeilen, die im Dauerbetrieb das Ausliefern von Webseiten deutlich beschleunigen und den Traffic reduzieren. So empfiehlt es sich, für alle Webseiten Caching und das Komprimieren via Gzip einzuschalten. Das Beispiel in Listing 4 sorgt dafür, dass Webseiten bis zu 30 Tage im Browser-Cache verbleiben und aktiviert die Gzip-Kompression.
Listing 4
# Caching aktivieren expires 30d; add_header Cache-Control public; add_header Last-Modified: $date_gmt; # Gzip-komprimierung aktivieren 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 ; # Vermisste Seiten, z.B. favicon.ico oder robots.txt sollen nicht geloggt werden log_not_found off;
Die Option gzip_comp_level gibt an, wie stark Nginx Seiten vor dem Ausliefern staucht. Die Spanne reicht hier von 1 bis 9, wobei ein höherer Wert kleinere Dateien liefert, aber mehr Rechenkraft benötigt. Die Option gzip_proxied any erlaubt das Komprimieren für jegliche Anfragen. Hier lässt sich die Kompression vom gesendeten Header abhängig machen. In gzip_types finden sich schließlich die Dateitypen, die der Server – neben HTML-Seiten – komprimiert ausliefert. Der Schalter log_not_found off; weist Nginx an, Fehler bei Anforderungen nicht vorhandener robots.txt und favicon.ico nicht zu loggen.
FastCGI und PHP
Viele Webserver unterstützen dynamische Scriptsprachen wie PHP oder Python. Nginx bedient sich dazu der Hilfe des FastCGI-Interfaces. Ruft ein Besucher eine dynamische Seite auf, reicht Nginx die Anfrage an FastCGI weiter. Das aktiviert den passenden Interpreter wie PHP oder Python und liefert die Ergebnisse an Nginx zurück, der sie an den anfragenden Client durchreicht.
Anders als beim Apache oder Lighttpd starten die FastCGI-Prozesse jedoch nicht automatisch aus Nginx – Sie müssen Sie separat auf den Weg bringen. Listing 5 zeigt ein Skript, das 15 Prozesse startet, die mit dem PHP-Interpreter verbandelt sind. Speichern Sie das Skript unter /etc/init.d/fastcgi ab und passen Sie mittels chmod 755 fastcgi die Rechte an. Entweder starten Sie das Skript nun manuell mithilfe des Befehls /etc/init.d/fastcgi start oder binden es in den Boot-Prozess ein. Unter Debian oder Ubuntu geschieht das mittels update-rc.d fastcgi defaults auf der Kommandozeile.
Listing 5
#!/bin/bash
BIND=127.0.0.1:9000
PHP_CGI=/usr/bin/php-cgi
PHP_CGI_NAME=$(basename $PHP_CGI)
PHP_CGI_ARGS="- USER=www-data PATH=/usr/bin PHP_FCGI_CHILDREN=15 PHP_FCGI_MAX_REQUESTS=1000 $PHP_CGI -b $BIND"
RETVAL=0
start() {
echo -n "Starting PHP FastCGI: "
start-stop-daemon --quiet --start --background --chuid "$USER" --exec /usr/bin/env -- $PHP_CGI_ARGS
RETVAL=$?
echo "$PHP_CGI_NAME."
}
stop() {
echo -n "Stopping PHP FastCGI: "
killall -q -w -u $USER $PHP_CGI
RETVAL=$?
echo "$PHP_CGI_NAME."
}
case "$1" in
start)
start ;;
stop)
stop ;;
restart)
stop
start ;;
*)
echo "Usage: php-fastcgi {start|stop|restart}"
exit 1
esac
exit $RETVAL
In Listing 5 ist sind die FastCGI-Prozesse an einen TCP-Socket gebunden. Um die leistungsfähigeren Unix-Sockets zu verwenden, ersetzen Sie den Eintrag 127.0.0.1:9000 durch /tmp/php.socket in der Bind-Anweisung. Anschließend weisen Sie Nginx in der Server-Sektion an, alle Anfragen nach PHP-Seiten an FastCGI weiterleiten (Listing 6). Die eingebundene Datei fastcgi_params gelangt bei der Installation von Nginx ins System. Sie enthält viele Standardwerte und bedarf in der Regel keiner weiteren Modifikation.
Listing 6
location ~* \.php$ {
fastcgi_pass 127.0.0.1:9000;
# Unix-Socket
//fastcgi_pass unix:/tmp/php.socket;
include fastcgi_params;
}
Erweist sich die Konfiguration anschließend als fehlerlos, liefert eine PHP-Datei mit dem Inhalt phpinfo(); die Information, ob alles wie gewünscht funktioniert (Abbildung 2).
Die Anfragen nach PHP-Dateien erkennt der Server mithilfe des regulären Ausdrucks \.php$ in der ersten Zeile. Die Tilde und der Stern weisen ihn an, nach allen Treffern zu suchen, also Groß- und Kleinschreibung zu ignorieren. Verwenden Sie im Location-Block nur die Tilde, berücksichtigt die Regel nur exakte Treffer (schreibweisenabhängig); ein = bedeutet, dass die URI dem regulären Ausdruck genau entsprechen muss.
Setzen Sie keine Location-Modifier ein, greift die Regel nur dann, wenn die URI mit dem angegebenen Pattern beginnt. Ein location \web würde also die URIs http://Site/web, http://Site/webseite, http://Site/web/foo, aber nicht http://Site/intern betreffen.
Virtuelle Hosts
In vielen Fällen bedient ein Server nur eine einzige Webseite. Planen Sie, mehrere virtuelle Hosts einzusetzen, sollten Sie im Konfigurationsverzeichnis die bereits vom Apache bekannten Ordner sites-available und sites-enabled anlegen. So haben Sie später die Möglichkeit, Site einfach an- oder abzuschalten oder deren Konfiguration zu ändern. Die Parameter für einen virtuellen Servers finden sich beispielhaft in Listing 7.
Listing 7
server {
listen 80;
server_name blog.sprachenzentrum.hu-berlin.de;
root /var/www/blog/;
index index.php; # index.html index.htm;
location / {
if (!-e $request_filename) {
rewrite ^ /index.php last;
}
}
location ~* \.php$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
}
}
Im Beispiel handelt es sich um einen domainbasierten virtuellen Host, der PHP-Seiten ausliefert und dessen Seiten im Verzeichnis /var/www/blog liegen. Hier sehen Sie eine Rewrite-Rule, die besagt, dass der Server bei allen angefragten Dateien, die nicht existieren, auf die index.php umleitet. Das Flag last teilt Nginx mit, dass keine weiteren Rewrite-Direktiven folgen.
SSL-Verschlüsselung
In Zeiten, in denen immer mehr Ganoven ihr Unwesen im Web treiben, bietet es sich für manche Seiten an, abhörsicher mit dem Client zu kommunizieren. Hier greift das HTTPS-Protokoll, das die Datenübertragung per SSL verschlüsselt. Dergleichen richten Sie mit Nginx fast ebenso schnell und einfach ein wie alles andere, allerdings fallen einige Vorarbeiten an: Zuerst erstellen Sie die nötigen Schlüssel und Zertifikate. Listing 8 zeigt die erforderlichen Schritte, um ein selbst signiertes Zertifikat zu erstellen, das drei Jahre lang gilt. Alternativ verwenden Sie die Daten, die Ihnen bei Bedarf eine Zertifikatstelle liefert – meist nur gegen Bezahlung.
Listing 8
# openssl genrsa -out website.key 1024 # openssl req -new -key website.key -out website.csr # openssl x509 -days 1095 -signkey website.key -in website.csr -req -out website.crt
Um nun HTTPS für eine entsprechende Seite zu aktivieren, erweitern Sie deren Server-Abschnitt um mindestens drei Zeilen, die Nginx den Pfad zu den Schlüsseln weisen. Standardmäßig verwendet der Server den Port 443, um die Kommunikation über HTTPS abzuwickeln, so dass es den Parameter listen anzupassen gilt. Listing 9 zeigt, wie Sie einen virtuellen Server mit HTTPS-Unterstützung aufsetzen. Neben dem zu verwendenden Schlüssel und Zertifikat sind auch die unterstützten Protokolle und Chiffren angegeben.
Listing 9
# HTTPS
server {
listen 443;
server_name haus3.no-ip.org;
ssl on;
ssl_certificate /home/falko/website.crt;
ssl_certificate_key /home/falko/website.key ;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
location / {
root /var/www/haus3/;
index index.php; #index.html index.htm;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~* \.php$ {
fastcgi_pass unix:/tmp/php.socket;
fastcgi_index index.php;
include fastcgi_params;
}
}
Startskript und Tests
Haben Sie Nginx nicht aus dem Paketrepository gezogen, kommt schnell der Wunsch nach einem Startskript auf, das den täglichen Einsatz deutlich vereinfacht. Eine entsprechende Datei [5] haben Sie leicht erstellt, via chmod 755 /etc/init.d/nginx und rcupdate-rc.d nginx defaults angepasst und den zu startenden Diensten der Runlevels hinzugefügt.
Um die Leistungsfähigkeit der neuen Site zu testen, bieten sich Werkzeuge wie Httperf [6] an, die den Server mit Anfragen traktieren und messen, was er leistet. Das Werkzeug ist zwar alt, genügt aber völlig, um die Auswirkungen von Parameteränderungen zu verfolgen. Listing 10 zeigt eine Kommandozeile, bei der Httperf 150 Verbindungen pro Sekunde zum Server 192.168.10.111 aufbaut, die index.php abruft und aufhört, sobald 20?000 Verbindungen voll sind (Abbildung 4).

Abbildung 4: Nginx auf einem Sheevaplug ist in der Lage, knapp 100 Verbindungen pro Sekunde mit FastCGI zu handhaben.
Listing 10
httperf --hog --server 192.168.10.111 --uri=/index.php --num-conn 20000 --rate 150 --timeout 5
Fazit
Bei Nginx handelt es sich um einen Webserver, der Apache durchaus das Wasser reichen kann. Leichte Konfiguration und hohe Performance sind nur zwei Gründe, die für das Programm als Apache-Ersatz sprechen. Wer den Indianer unbedingt braucht, etwa weil er ein laufendes System nicht ändern will, dem bietet sich Nginx als Reverse Proxy an. Neben den hier erwähnten Einstellungen lohnt es sich, einige zusätzliche Module wie RealIP, GeoIP oder Memchached genauer zu betrachten, um alle Möglichkeiten des Webservers aus Russland auszuschöpfen.
Glossar
-
SIGTERM
-
Auf Posix-kompatiblen Plattformen ein Signal zum beenden von Prozessen, das der jeweilige Prozess allerdings interpretieren oder ignorieren darf im Gegensatz zu SIGKILL, was ein sofortiges Beenden nach sich zieht.
Infos
[1] Nginx: http://nginx.net
[2] Netcraft Webserver Survey 01/2011: http://news.netcraft.com/archives/2011/01/12/january-2011-web-server-survey-4.html
[3] Nginx-Quellcode: http://nginx.org/en/download.html
[4] Google Perftools: http://code.google.com/p/google-perftools/
[5] Nginx-Startskript: http://doku.sprachenzentrum.hu-berlin.de/wikka.php?wakka=ServerNginx
[6] Httperf: http://www.hpl.hp.com/research/linux/httperf/







