nginx
Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:
Du möchtest den Artikel für eine weitere Ubuntu-Version testen? Mitarbeit im Wiki ist immer willkommen! Dazu sind die Hinweise zum Testen von Artikeln zu beachten.
Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:
nginx 🇬🇧 (gesprochen „engine x”) ist ein Webserver, welcher gegenüber Apache sehr schnell und schmal ist. Er ist dafür ausgelegt, selbst unter hoher Last nur wenig Ressourcen zu verbrauchen. nginx wurde von Igor Sysoev entwickelt und wird laut netcraft 🇬🇧 von 7.53% (Stand: Januar 2010) aller Websites genutzt.
Installation¶
Aus den Paketquellen¶
nginx kann ab Ubuntu Hardy 8.04 als fertiges Paket installiert werden[1]:
nginx (universe)
Befehl zum Installieren der Pakete:
sudo apt-get install nginx
Oder mit apturl installieren, Link: apt://nginx
Mithilfe des Quellcodes¶
Hinweis!
Zusätzliche Fremdquellen können das System gefährden.
Zuerst muss der Quellcode von nginx hier ⮷ heruntergeladen werden. Bevor nginx kompiliert werden kann, benötigt es folgende Pakete:
gcc
libevent
build-essential
Befehl zum Installieren der Pakete:
sudo apt-get install gcc libevent build-essential
Oder mit apturl installieren, Link: apt://gcc,libevent,build-essential
Nun entpackt[3] man das Paket und kompiliert[4] nginx.
Achtung!
Der Ort der Konfigurationsdatei ist bei der Installation aus dem Quellcodes abweichend. Sie befindet sich unter /usr/local/nginx/nginx.conf.
Konfiguration¶
nginx liest die Konfiguration aus der Datei /etc/nginx/nginx.conf. Die Datei besteht im Wesentlichen aus zwei Teilen: Dem kleinen "events"-Teil und dem wichtigen "http"-Teil.
Kommentiert wird mit einer Raute (#); kommentierte Zeilen werden von nginx nicht beachtet.
Ändern der Umgebung¶
Ändern des Nutzers¶
nginx kann - wie viele andere Webserver - auch einen anderen Nutzer als „root” benutzen. Um dies auszulösen ändert man folgende Zeile:
#user nobody;
ab zu folgender Zeile (in diesem Beispiel wird der Nutzer „www-data” verwendet):
user www-data;
Dies ändert - unabhängig davon, mit welchem Nutzer nginx gestartet wurde - das Konto, mit dem der Daemon arbeitet.
Aktivierung einer Logdatei¶
Um eine komplette Logdatei nach /etc/nginx/logs/error.log zu schreiben, ändert man die Zeile:
#error_log logs/error.log;
ab zu:
error_log /etc/nginx/logs/error.log;
Hinweis:
Falls der Nutzer geändert wurde (s.o.), muss dieser Schreibzugriff auf den Ordner bzw. die Datei besitzen.
Durch das Hinzufügen von info
oder notice
nach dem Dateinamen kann das Protokoll gefiltert werden. Dies meint, dass z.B. nur Informationen gesichert werden.
Konfigurieren des Webservers¶
Grundkonfiguration¶
Damit nginx an eine Domain oder IP gebunden wird, muss folgender Grundblock in den http-Teil eingefügt werden:
server { }
Hinweis:
Die Datei ist nach der Installation schon vorkonfiguriert. Es ist empfehlenswert, jegliche server { [...] }
-Bereiche zu entfernen, um Komplikationen zu vermeiden.
Nun wird angegeben, an welchen Port sich nginx binden soll (80
) und an welche Domain bzw. IP (localhost
):
server { listen 80; server_name localhost; }
Nun würde nginx zwar am Port 80 horchen, allerdings könnte er keine Daten anzeigen bzw. versenden, da er kein Verzeichnis mit Dateien zur Verarbeitung bekommen hat. Dies ändert man mit root
(im Beispiel liegen die Dateien in /srv/localhost):
root /srv/localhost;
Hinweis:
root
steht für document root
und nicht, wie man denken könnte, für den Benutzer root
.
Zuletzt wird noch festgelegt, welche Datei aufgerufen werden soll, wenn der Nutzer nur localhost
eintippt:
location / { index index.html index.htm; }
Domains einbinden¶
Domains lassen sich folgendermaßen einbinden:
server_name www.example.com example.com;
Damit hört nginx sowohl an www.example.com
als auch example.com
.
Sub- und Wildcarddomains einbinden¶
Sub- und Wildcarddomains bindet man mit
server_name *.example.com subdomain.example.com;
ein.
Achtung!
Jeder server { [...] }
-Block löst aus, dass alle Domains, die hinter server_name
stehen, mit dem Inhalt des Verzeichnisses root
versorgt werden.
Beispiel¶
server { listen 80; server_name localhost example.com www.example.com; root /srv/daten; location / { index index.html index.htm; } } server { listen 80; server_name subdomain.example.com; root /srv/subdomain/daten; location / { index index.html index.htm; } }
PHP mit nginx¶
nginx verlangt für PHP eine FastCGI-Schnittstelle. Da PHP nicht im Passiv-Modus agiert, müssen - wie für FastCGI üblich - PHP-Instanzen gestartet werden, die im Arbeitsspeicher auf ihren Einsatz warten.
Zuerst installiert man PHP im CGI-Modus, falls noch nicht geschehen, mit folgendem Paket:
php5-cgi
Befehl zum Installieren der Pakete:
sudo apt-get install php5-cgi
Oder mit apturl installieren, Link: apt://php5-cgi
Ab Ubuntu Hardy 8.04¶
Bis Ubuntu 9.10 existiert das Paket spawn-fcgi nicht, mit welchem man sonst die Instanzen hätte einfacher starten können, weswegen man start-stop-daemon verwenden muss.
Dazu erstellt man die Datei /usr/bin/php-fastcgi und füllt sie mit folgendem Bash-Skript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #!/bin/bash BIND=127.0.0.1:9000 USER=www PHP_FCGI_CHILDREN=8 PHP_FCGI_MAX_REQUESTS=1000 PHP_CGI=/usr/bin/php-cgi PHP_CGI_NAME=`basename $PHP_CGI` PHP_CGI_ARGS="- USER=$USER PATH=/usr/local/bin PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS $PHP_CGI -b $BIND" RETVAL=0 start() { echo -n "Startet 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 "Stoppt 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 "Benutzung: php-fastcgi {start|stop|restart}" exit 1 ;; esac |
Zuerst gilt es nun zu überprüfen, ob die Datei in Zeile 7 überhaupt existiert. Falls nicht, ändert man den Pfad passend ab. Danach ändert man in Zeile 3 den Benutzer, mit dem die FastCGI-Instanzen laufen sollen und zu guter Letzt verpasst man dem Skript noch die passenden Rechte:
chmod a+x /usr/bin/php-fastcgi
Starten tut man die Instanzen nun mit dem Befehl
sudo php-fastcgi start
Experten-Info:
Das Skript kann auch als /etc/init.d/-Skript eingesetzt werden, damit die Instanzen automatisch starten.
Ab Ubuntu Karmic 9.10¶
Zuerst installiert man, falls noch nicht geschehen, das Paket
spawn-fcgi (universe)
Befehl zum Installieren der Pakete:
sudo apt-get install spawn-fcgi
Oder mit apturl installieren, Link: apt://spawn-fcgi
Dann erstellt man ein Bash-Skript, welches die Instanzen startet (Quelle: Linode.com - Nginx and PHP-FastCGI on Ubuntu 🇬🇧 ):
1 2 | #!/bin/sh /usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www-data -f /usr/bin/php5-cgi |
Das Skript speichert man unter /usr/bin/php-fastcgi ab und setzt mit
chmod a+x /usr/bin/php-fastcgi
die richtigen Rechte.
Starten tut man nun die Instanzen ganz einfach mit dem Befehl
sudo php-fastcgi
Die Konfiguration von nginx anpassen¶
Hinweis:
Dieser Teil gilt wieder für alle Ubuntu-Versionen.
Zu guter Letzt muss jetzt nur noch nginx wissen, wie man sich an die Schnittstelle bindet. Dazu fügt man in den server { [...] }
-Block folgendes ein:
location ~ \.php$ { fastcgi_pass localhost:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }
Hinweis:
Bei Uploads bitte auch "nginx und PHP absichern" beachten!
Python mit nginx¶
In diesem Fall wird Django als FastCGI-Schnittstelle verwendet. Dafür wird aber eine kleine Veränderung in der Konfiguration benötigt:
server { listen 80; server_name localhost; location / { fastcgi_pass 127.0.0.1:9000; fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param QUERY_STRING $query_string; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_pass_header Authorization; fastcgi_intercept_errors off; include fastcgi_params; } }
Zuletzt muss nur noch Django gestartet werden:
python manage.py runfcgi host=127.0.0.1 port=9000 --settings=settings
Achtung!
Läuft bereits eine FastCGI-Schnittstelle mit dem Port 9000, muss der Port geändert werden!
Perl mit nginx¶
Um Perl zum Laufen zu bekommen, ist einige Arbeit nötig: Zuerst einmal muss Perl überhaupt eine FastCGI-Schnittstelle bekommen. Das geht mit dem Befehl
perl -MCPAN -e 'install FCGI'
Dann muss ein Perl-Skript geschrieben werden, über das Perl abläuft (Quelle 🇬🇧) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #!/usr/bin/perl use FCGI; use Socket; use POSIX qw(setsid); require 'syscall.ph'; &daemonize; #this keeps the program alive or something after exec'ing perl scripts END() { } BEGIN() { } *CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; }; eval q{exit}; if ($@) { exit unless $@ =~ /^fakeexit/; }; &main; sub daemonize() { chdir '/' or die "Can't chdir to /: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; umask 0; } sub main { $socket = FCGI::OpenSocket( "127.0.0.1:9000", 10 ); #use IP sockets $request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket ); if ($request) { request_loop()}; FCGI::CloseSocket( $socket ); } sub request_loop { while( $request->Accept() >= 0 ) { #processing any STDIN input from WebServer (for CGI-POST actions) $stdin_passthrough =''; $req_len = 0 + $req_params{'CONTENT_LENGTH'}; if (($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ){ my $bytes_read = 0; while ($bytes_read < $req_len) { my $data = ''; my $bytes = read(STDIN, $data, ($req_len - $bytes_read)); last if ($bytes == 0 || !defined($bytes)); $stdin_passthrough .= $data; $bytes_read += $bytes; } } #running the cgi app if ( (-x $req_params{SCRIPT_FILENAME}) && #can I execute this? (-s $req_params{SCRIPT_FILENAME}) && #Is this file empty? (-r $req_params{SCRIPT_FILENAME}) #can I read this file? ){ pipe(CHILD_RD, PARENT_WR); my $pid = open(KID_TO_READ, "-|"); unless(defined($pid)) { print("Content-type: text/plain\r\n\r\n"); print "Error: CGI app returned no output - "; print "Executing $req_params{SCRIPT_FILENAME} failed !\n"; next; } if ($pid > 0) { close(CHILD_RD); print PARENT_WR $stdin_passthrough; close(PARENT_WR); while(my $s = <KID_TO_READ>) { print $s; } close KID_TO_READ; waitpid($pid, 0); } else { foreach $key ( keys %req_params){ $ENV{$key} = $req_params{$key}; } # cd to the script's local directory if ($req_params{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/) { chdir $1; } close(PARENT_WR); close(STDIN); #fcntl(CHILD_RD, F_DUPFD, 0); syscall(&SYS_dup2, fileno(CHILD_RD), 0); #open(STDIN, "<&CHILD_RD"); exec($req_params{SCRIPT_FILENAME}); die("exec failed"); } } else { print("Content-type: text/plain\r\n\r\n"); print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not "; print "exist or is not executable by this process.\n"; } } } |
Gespeichert wird das Perl-Skript unter /usr/bin/fastcgi-wrapper.pl. Die Schreibrechte müssen auch korrekt gesetzt werden:
chmod a+x /usr/bin/fastcgi-wrapper.pl
Zusätzlich wird noch ein Startskript erstellt, welches unter /usr/bin/perl-fastcgi gespeichert wird (Quelle 🇬🇧) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/bin/bash PERL_SCRIPT=/usr/bin/fastcgi-wrapper.pl RETVAL=0 case "$1" in start) $PERL_SCRIPT RETVAL=$? ;; stop) killall -9 perl RETVAL=$? ;; restart) killall -9 perl $PERL_SCRIPT RETVAL=$? ;; *) echo "Usage: perl-fastcgi {start|stop|restart}" exit 1 ;; esac exit $RETVAL |
Auch diesem Skript werden die richtigen Rechte verpasst:
chmod a+x /usr/bin/perl-fastcgi
Starten tut man nun die Schnittstelle mit
perl-fastcgi start
Zuletzt muss nur noch die nginx-Konfiguration angepasst werden:
location ~ \.pl$ { include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.pl; fastcgi_param SCRIPT_FILENAME /srv/www/www.bambookites.com/public_html$fastcgi_script_name; }
Hinweis:
GZip-Komprimierung verlangsamt die Skripte.
Achtung!
Läuft bereits eine FastCGI-Schnittstelle mit dem Port 9000, muss der Port geändert werden!
nginx steuern¶
nginx bildet sich aus einem „Master”-Prozess und vielen „Slave”- bzw. „Client”-Prozessen. Steuern tut man nginx mit dem Master-Prozess, den man mit dem Befehl nginx anspricht. Dies geht nach folgendem Prinzip:
nginx [-s signal] [-c filename] [-p prefix] [-g directives]
Starten, stoppen und neu Starten¶
Für den Start führt man folgenden Befehl aus:
sudo nginx
Es sind Rootrechte erforderlich, da eine Bindung an einen Haupt-Port stattfindet, die von Ubuntu/dem Root genehmigt werden muss.
Für das Stoppen von nginx:
sudo nginx -s stop
Für das erneute Starten von nginx:
sudo nginx -s quit sudo nginx
Falls /etc/init.d/nginx vorhanden ist, kann man nginx auch mit diesen Optionen steuern:
/etc/init.d/nginx (start|stop|restart|reload|force-reload)
Andere Konfigurationsdatei verwenden¶
Falls eine andere Konfigurationsdatei als /etc/nginx/nginx.conf oder /usr/local/nginx/nginx.conf z.B. zu Testzwecken verwendet werden soll, startet man nginx folgendermaßen:
sudo nginx -c /pfad/der/konfigurationsdatei
nginx optimieren¶
GZip-Komprimierung anschalten¶
Dank der GZip-Komprimierung kann mach sich viel Datenverkehr sparen. Wie die Kompression von Websites funktioniert und warum man sie aktivieren sollte, kann man hier 🇬🇧 nachlesen. nginx kann alle Typen von Websites und Textdateien komprimieren im Gegensatz zu dem ZLib-Modul von PHP, welches nur PHP komprimiert.
Um die Komprimierung anzuschalten ändert man die Zeile
#gzip on;
ab zu
gzip on;
und startet nginx neu. Zusätzlich kann man sogar noch festlegen, welche Dateien geschrumpft werden sollen, und welche Browser ausgenommen werden sollen:
gzip_types text/plain application/xml; gzip_disable "MSIE [1-6]\.";
Achtung!
Die GZip-Kompression kann bei uneingeschränkter Nutzung bei älteren Browsern zu Problemen führen.
Charset festlegen¶
Falls ein Charset (=Zeichensatz) festgelegt werden soll, kann man sich mit folgendem Befehl im server { [...] }
-Block behelfen:
charset utf-8;
Tipps & Tricks¶
Module benutzen¶
nginx besitzt standardmäßig nur Standard-Module, welche hier 🇬🇧 gelistet sind. Allerdings kann man nginx mit vielen weiteren Modulen benutzen, deren offiziellen Anlaufstellen hier 🇬🇧 und hier 🇬🇧 sind. Die Module kann man allerdings - nicht wie bei allen anderen Webservern - direkt benutzen, sondern muss sie mit nginx kompilieren[4]. Wie das funktioniert, steht in aller Regel in der Dokumentation des Modules. Bei optionalen HTTP-Modulen (hier gelistet) funktioniert das folgendermaßen:
Hinweis:
In diesem Beispiel wird das "FLV Streaming Modul" installiert.
Man bezieht sich - wie oben schon beschrieben - den Quellcode von nginx und entpackt ihn. Statt nun einfach
./configure
einzutippen, fügt man nun das Modul an:
./configure --with-http_flv_module
Somit wird bei der weiteren Kompilierung nun auch das FLV-Modul berücksichtigt.
Loadbalancing mit nginx¶
Loadbalancing ist standardmäßig in nginx vorhanden und schlägt laut diesem Artikel 🇩🇪 Pound deutlich. Im folgenden Beispiel verteilt nginx die Last auf 3 Server:
http { upstream loadbalancer { server 127.0.0.1:8000; server 127.0.0.1:8001; server 127.0.0.1:8002; } server { listen 80; server_name www.example.com example.com; location / { proxy_pass http://loadbalancer; } } }
Zur Erklärung: Im Upstream loadbalancer
sind drei (Web-)Server vorhanden und mit ihren jeweiligen Daten (IP:Port
) angegeben. Im server { [...] }
-Block hört nginx an den Domains www.example.com
und example.com
an Port 80 und leitet die Anfrage an den upstream weiter.
Rewriting¶
Statt sich die Domäne wie z.B. „http://www.example.com/index.php?artikel=1234” zu merken, ist es viel einfacher, sich die Domäne „http://www.example.com/artikel/1234” zu merken. In der Konfigurationsdatei kann dies im server { [...] }
-Block erledigt werden:
rewrite ^/artikel/(.*)$ /index.php?artikel=$1? last;
^/artikel/(.*)$
bedeutet folgendes: Sollte irgendwo /artikel/
vorkommen, dann kommt das, was hinter /artikel/
steht, in die Variable $.
/index.php?artikel=$1?
bedeutet, dass statt „ http://www.example.com/artikel/1234 ” „ http://www.example.com/index.php?artikel=1234 ” aufgerufen wird. 1234
ist hier der Wert der Variable $ gewesen.
Achtung!
Wenn das last am Ende vergessen wird, dann produziert nginx einen 500 Server-Error.
Weitere Hilfe findet man hier 🇬🇧.
nginx und PHP absichern¶
Man stelle sich vor, ein Hacker würde eine .php-Datei via PHP in das Verzeichnis /uploads/ hochladen. Diese Datei ist mit Schadcode infiziert und würde bei der Ausführung dem Server schaden. Wenn jetzt aber die Ausführung der Datei nicht verboten wird, könnte der Hacker seinen Angriff starten. Um das zu verhindern, fügt man in den location ~ \.php$ { [...] }
-Block folgendes ein:
if ($uri !~ "^/uploads/") { fastcgi_pass 127.0.0.1:9000; }
Dies löst aus, dass alle .php-Dateien in allen Ordnern mit dem Namen uploads nicht mehr ausgeführt werden.
Erste Hilfe bei Problemen¶
nginx zeigt bei Dateien, die existieren, im Browser "403" an.¶
Schreibrechte überprüfen! Diese Meldung kommt meistens, wenn nginx bzw. der Benutzer, mit dem nginx läuft, keinen Zugriff auf die Dateien hat.
nginx startet nicht automatisch.¶
Eventuell fehlt das /etc/init.d-Startskript. Hier 🇬🇧 findet man Hilfe.
nginx startet nicht, da die Konfigurationsdatei angeblich falsch ist.¶
Die Konfigurationsdatei überprüfen, ob überall am Ende jedes Befehls/jeder Zeile ein Semikolon ist, und ob der server { [...] }
-Block auch mit dem Zeichen "}" geschlossen ist!
Obwohl nginx richtig konfiguriert ist, passiert beim Aufrufen von Subdomains nichts.¶
Das kann passieren, wenn man sich vertippt hat, oder der Namensserver falsch eingestellt ist.
Wieso bliebt nginx an der Meldung "[...]:80 failed (98: Address already in use)" hängen?¶
Vielleicht läuft nginx schon. Falls nicht, sollte man überprüfen, ob andere Webserver schon diesen Port nutzen!
Wieso kann Plesk nginx nicht konfigurieren?¶
Das liegt daran, dass Plesk Apache nutzt und nicht auf nginx zugeschnitten ist.
Wieso wird die neue Konfiguration nicht übernommen?¶
Für eine Konfigurationsänderung muss nginx neugestartet werden. Wie das geht, steht im Bereich "nginx steuern".
Links¶
Das Python-Logo ist Eigentum der Python Foundation.