nginx_logo_klein2

Nginx + PHP5-fpm auf Debian/Ubuntu

closeDieser Beitrag wurde vor mehr als drei Monaten veröffentlicht. Bedenke bitte, dass die hier angebotene Information nicht mehr aktuell und gültig sein könnte. Informiere dich daher bitte auch an anderer Stelle über dieses Thema. Sollten sich neue Informationen ergeben haben, so kannst du mich auch gerne auf diese über einen Kommentar hinweisen. Vielen Dank!

Zurück zur “Webseiten beschleunigen” – Übersicht

5.3) Nginx als Webserver


nginx_logo

Wer komplett auf nginx als Webserver umsteigen will kann dies auch sehr einfach bewerkstelligen. Ich persönlich nutzte diese Methode und es laufen mehrere WordPress-Webseiten, e107, DokuWiki u.s.w. tadellos mit diesem System.

Als erstes müssen wir unsere sources.list ein wenig erweitern… um php5-fpm direkt mit dem Projektmanager installieren zu können, wie dies Funktioniert habe ich bereits in einem anderen Beitrag beschreiben: php-5-FPM

Danach installieren wir nginx (Webserver) + PHP, wenn du noch apache2 oder einen anderen Webserver, welcher auf Port 80 lauscht installiert hast, musst du diesen nun deinstallieren bzw. erst einmal stoppen und ggf. einige libraries nachinstallieren, falls du Ubuntu und nicht Debian nutzt.


ggf. nur bei Ubuntu

wget http://us.archive.ubuntu.com/ubuntu/pool/main/k/krb5/libkrb53_1.6.dfsg.4~beta1-5ubuntu2_i386.deb
wget http://us.archive.ubuntu.com/ubuntu/pool/main/i/icu/libicu38_3.8-6ubuntu0.2_i386.deb
sudo dpkg -i *.deb

ggf. root-Rechte

sudo bash

ggf. apache stoppen

/etc/init.d/apache2 stop
aptitude install nginx php5-fpm

Nun kommen wir zur Konfiguration, ich poste hier einfach mal meine komplette Konfig, daher sollte diese ohne Probleme lauffähig sein, wenn du die aktuelle Version installiert hast.

vim /etc/nginx/nginx.conf
user www-data;
worker_processes 4;
worker_rlimit_nofile 3000;
pid /var/run/nginx.pid;

# [ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log;

#google_perftools_profiles /tmp/profile/;

events {
        worker_connections 2048;
        # use [ kqueue | rtsig | epoll | /dev/poll | select | poll ] ;
        use epoll;
        multi_accept on;
}

http {
        server_names_hash_bucket_size 64;

        ## Size Limits
        client_max_body_size        10M;
        client_header_buffer_size   32k;
        client_body_buffer_size     128k;
        large_client_header_buffers 64 8k;

        ## Timeouts
        client_body_timeout   3m;
        client_header_timeout 3m;
        send_timeout          3m;
        #expires              24h;
        keepalive_timeout     120 120;

        ## General Options
        ignore_invalid_headers   on;
        keepalive_requests       100;
        limit_zone normal $binary_remote_addr 5m;
        recursive_error_pages    on;
        sendfile                 on;
        server_name_in_redirect  off;
        server_names_hash_max_size 512;
        server_tokens            off;
        set_real_ip_from 127.0.0.1;
        real_ip_header X-Forwarded-For;

        ## TCP options
        #tcp_nopush on;
        tcp_nodelay off;
        #send_lowat 12000;

        include mime.types;
        default_type application/octet-stream;

        access_log /var/log/nginx/access.log;

        log_format main '$remote_addr - $remote_user [$time_local] $status '
        '\"$request\" $body_bytes_sent \"$http_referer\" '
        '\"$http_user_agent\" \"http_x_forwarded_for\"';

        ## Cache
        open_file_cache max=1000 inactive=24h;
        open_file_cache_valid    24h;
        open_file_cache_min_uses 2;
        open_file_cache_errors   on;

        ## Compression
        gzip              on;
        gzip_static       on;
        gzip_disable      "MSIE [1-6]\.";
        gzip_buffers      32 8k;
        gzip_comp_level   5;
        gzip_http_version 1.0;
        gzip_min_length   0;
        gzip_proxied      any;
        gzip_types text/plain text/css text/xml text/javascript application/json application/xml application/xml+rss application/x-javascript image/x-icon application/x-perl application/x-httpd-cgi;
        gzip_vary         on;

        output_buffers   10 128k;
        postpone_output  1500;

        # Beispiel: Loadbalance
        #upstream webbackend  {
                #ip_hash;
                #server web1.domain.lan weight=10 max_fails=3 fail_timeout=30s;
                #server web2.domain.lan weight=1 backup;
        #}

        # Beispiel: Reverse-Proxy
        #server {
                #access_log  /var/log/nginx/access.proxy.log main;
                #error_log   /var/log/nginx/error.proxy.log;
                #listen      80;
                #server_name _;

                ## PROXY - Web
                #location ~ \.php$ {
                        #proxy_cache            cache;
                        #proxy_pass  http://127.0.0.1:8080;
                #}
        #}

        # Beispiel: HTTP Server (sollte jedoch besser unter /etc/nginx/sites-available/ angelegt werden)
        #server {
                #listen       80;
                #listen       somename:80;
                #server_name  somename  alias  another.alias;

                #location / {
                        #root   html;
                        #index  index.html index.htm;
                        #}
                #}

        # Beispiel: HTTPS Server (sollte jedoch besser unter /etc/nginx/sites-available/ angelegt werden)
        #server {
                #listen       443;
                #server_name  localhost;

                #ssl                  on;
                #ssl_certificate      cert.pem;
                #ssl_certificate_key  cert.key;

                #ssl_session_timeout  5m;

                #ssl_protocols  SSLv2 SSLv3 TLSv1;
                #ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
                #ssl_prefer_server_ciphers   on;

                #location / {
                #root   html;
                #index  index.html index.htm;
                #}
        #}

#include /etc/nginx/proxy.conf;
include /etc/nginx/sites-enabled/*.conf;
}
vim /etc/nginx/proxy.conf
proxy_buffering            on;
proxy_cache_min_uses       3;
proxy_cache_path           /usr/local/nginx/proxy_cache/ levels=1:2 keys_zone=cache:10m inactive=24h max_size=1000M;
proxy_cache                cache;
proxy_cache_valid          200 24h;
proxy_cache_use_stale      error timeout invalid_header updating http_500 http_502 http_503 http_504;
proxy_ignore_client_abort  off;
proxy_intercept_errors     on;
proxy_next_upstream        error timeout invalid_header;
proxy_redirect             off;
proxy_set_header           Host            $host;
proxy_set_header           X-Real-IP       $remote_addr;
proxy_set_header           X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffers              32 1M;
proxy_busy_buffers_size    31M;
proxy_temp_file_write_size 30M;
proxy_buffer_size          30M;
proxy_connect_timeout      90;
proxy_send_timeout         90;
proxy_read_timeout         90;
proxy_ignore_headers       Expires Cache-Control;

so nun richten wir unsere erste Webseite ein… (domain.de muss in den nachfolgenden Howto durch deine eigene Domain ersetzt werden und natürlich für jede neue Werbepräsenz eine neue Datei angelegt werden.

cd /etc/nginx/sites-available/
vim domain.de.conf
server {
        server_name domain.de www.domain.de *.domain.de;
        root /var/www/www.domian.de/web/;
        listen 80;
        index index.php;
        access_log /var/log/nginx/www.domian.de.access.log main;
        error_log /var/log/nginx/www.domian.de.error.log;

        if (-f $request_filename) {
                break;
        }

        location / {
                try_files $uri $uri/ @domian;
        }

        location ~* ^.+.(htm|html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
                access_log off;
                expires max;
                root /var/www/www.domian.de/web/;
        }

        location @domian {
                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 @domian;
                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;
        }
}
vim /etc/nginx/fastcgi_params
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

fastcgi_param  REDIRECT_STATUS    200;

nun müssen wir die Webseite nur noch aktivieren, indem wir die soeben erstellte Datei verlinken.

cd /etc/nginx/sites-enabled/
ln -s ../sites-available/domain.de.conf .
nginx -t
/etc/init.d/nginx restart

Und schon läuft unser neuer Webserver. :-) Um die neuste Version von Nginx auf Debian/Ubuntu zu installieren kann man ggf. noch folgende Quellen in die “sources.list” eintragen.

echo "deb  http://ppa.launchpad.net/nginx/stable/ubuntu lucid main" >> /etc/apt/sources.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C
apt-get update
apt-get install nginx

… oder du verwendest die letzte Development-Version:

echo "deb  http://ppa.launchpad.net/nginx/development/ubuntu lucid main" >> /etc/apt/sources.list
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C
apt-get update
apt-get install nginx

Nun müssen wir PHP5-FPM noch ein wenig anpassen, so dass php-fpm mit den Rechten des jeweilligen Webs ausgeführt wird:

mkdir /etc/php5/fpm/pools/
vim /etc/php5/fpm/php5-fpm.conf
[...]
[global]
pid = /var/run/php5-fpm.pid
error_log = /var/log/php-fpm.log
log_level = notice
emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 5s
daemonize = yes

;  pools defined in virtual hosts
include=/etc/php5/fpm/pools/*.conf
[..]

Nun leben wir für eine Webseite eine PHP-Konfiguration an:

vim /etc/php5/fpm/pools/domain.conf
[domain]

; one Port for one Website
listen = 127.0.0.1:11000

; uid/gid
user = domain_user
group = domain_group

; 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 = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 500

; Pass environment variables
env[TMP] = /var/www/www.domain.de/phptmp
env[TMPDIR] = /var/www/www.domain.de/phptmp
env[TEMP] = /var/www/www.domain.de/phptmp

; inculde defaults
include = /etc/php5/fpm/common.conf

; host-specific php ini settings here
;php_admin_value[open_basedir] =
vim /etc/php5/fpm/common.conf
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
Jetzt läuft der PHP-fpm Prozess mit den Rechten des jeweiligen Users und mit eigenem Tmp-Verzeichnis, wer will kann php-fpm sogar in einer chroot-Umgebung ausführen lassen :-)
Links:
  • http://suckup.de/ Lars Moelleken

    php-fpm + nginx mit verschiedenen Usern (uid/gid) für virtual hosts

  • Starflow

    sudo bash?
    su?
    ^^

  • http://suckup.de/ Lars Moelleken

    “sudo bash” -> “root bash”
    “su” -> z.B. “root zsh”

  • http://www.axelsegebrecht.com/ Axel Segebrecht

    Danke fuer die super Anleitung :-)

    Leider laueft alles prima nur the php Seiten werden im Browser runtergeladen anstelle richtig angezeigt.

    Ich sehe das richtig, das php5-fpm pools alles automatisch machen und ich in den vhosts wie bisher 127.0.0.1:9000 als Ziel angebe? Hatte das mit dem Port von dem Pool fuer meine Testsite probiert, was aber auch nichts geaendert hat.

    PS: Hetzner X4 server, Ubuntu 10.04 LTS x64, mit php5.3.2

  • http://suckup.de/ Lars Moelleken

    … du musst schon den passenden (selben) Port (z.B. 9000) in der nginx- / und der php-fpm Konfiguration angeben! Schau ggf. einfach mal in Logfile von php-fpm ggf. findest du dort weitere Hinweise wo der Fehler ist …

    Mfg

  • http://www.axelsegebrecht.com/ Axel Segebrecht

    Hi Voku, Danke fuer die Antwort. Leider ist das php-fpm log leer bis auf den Eintrag das es re-opened wurde… .

    Koennte ich Dich fuer eine Stunde gegen Bezahlung borgen?

  • Mr Seartrix

    Saubere Sache… Habe es zwar noch nicht ausprobiert, aber es sieht genau nach dem aus, was ich seit Stunden gesucht habe. 

    Vielen Dank für Mühe, die Du dir gemacht hast, um das mit uns allen zu teilen. :)

  • HerrMaulwurf

    Sehr lecker, dein Tutorial :)

    Ein “Basic-Setup” für nginx und PHP-FPM habe ich schon hinbekommen, aber dabei das leidige Problem, dass jeder PHP-Prozess auf dem System unter dem gleichen User läuft, was bei mehreren Webhosting-Nutzern natürlich suboptimal ist. Werde gleich mal dein Tutorial ausprobieren, um das miti den mehreren “PHP-Nutzern” hinzukriegen.

    Gehe ich Recht in der Annahme, dass ich für jede Website einen eigenen Port benutzen muss? Ist es dabei egal, welchen Port man nimmt? (Ports < 1024 mal ausgeschlossen). Kann ich also einfach für Seite 1 Port 9001, für Seite 2 Port 9002 usw. nehmen, oder gibt es da auch bestimmte Regeln?

    Thx schonmal,
    HerrMaulwurf

  • HerrMaulwurf

    Btw., dein Server kommt mir recht langsam vor… Wundert mich ein bisschen, da ich bei dir schonmal was über Serveroptimierung gelesen habe… :D

  • http://suckup.de Voku


    HerrMaulwurf:

    Sehr lecker, dein Tutorial Ein “Basic-Setup” für nginx und PHP-FPM habe ich schon hinbekommen, aber dabei das leidige Problem, dass jeder PHP-Prozess auf dem System unter dem gleichen User läuft, was bei mehreren Webhosting-Nutzern natürlich suboptimal ist. Werde gleich mal dein Tutorial ausprobieren, um das miti den mehreren “PHP-Nutzern” hinzukriegen.Gehe ich Recht in der Annahme, dass ich für jede Website einen eigenen Port benutzen muss? Ist es dabei egal, welchen Port man nimmt? (Ports < 1024 mal ausgeschlossen). Kann ich also einfach für Seite 1 Port 9001, für Seite 2 Port 9002 usw. nehmen, oder gibt es da auch bestimmte Regeln?Thx schonmal, HerrMaulwurf

    jop, einfach den Port um +1 erhöhen und in php-fpm und nginx angeben ;)

  • http://suckup.de Voku


    HerrMaulwurf:

    Btw., dein Server kommt mir recht langsam vor… Wundert mich ein bisschen, da ich bei dir schonmal was über Serveroptimierung gelesen habe…

    http://suckup.de/2010/07/26/webseiten-beschleunigen/#comment-1205 > kleiner günstiger V-Server auf dem auch noch andere Projekte laufen & somit zwischenzeitlich 100% ausgelastet ist! :)

  • Horrork1d

    Einfach geil das Tutorial, vielen Dank!

  • Horrork1d

    Noch eine Frage: Warum das ganze mit location @domain? Kann man sich das prinzipiell nicht sparen?

  • Shou

    Vielen Dank für das Tutorial. Auf einem 256MB vServer kann man Apache + WordPress einfach so in die Tonne kloppen.. es läuft niemals flüssig, egal was man tut. Aber mit nginx ist es super schnell, nur hatte ich immer Probleme mit der Php Config!

  • http://suckup.de Voku

    … kein Problem :)

    PS: hier habe ich meine aktuelle Konfig hochgeleaden -> https://github.com/voku/CONFIG–nginx—php-fpm—mysql

  • wtf

    Dude can you translate this shit to english ?

  • http://suckup.de/about voku

    shit? -> ;)

    if you have at least a minimum idea of ​​the theme (linux), then you can easily use my example-config -> https://github.com/voku/CONFIG–nginx—php-fpm—mysql

  • http://ph0enyx.de Martin Ehrentraut

    Hi,

    ich test gerade deine Anleitung und habe da noch ein paar Fragen.

    1. Du schreibst hier von unterschiedlichen User/Gruppen je Webseite, ich gehe mal davon aus das User und Gruppe angelegt sein müssen.

    2. Werden die Logs vom Root User geschrieben bzw vom Nginx User

    3. da ich einen CentOS Server als Basis benutze sind meine Pfade ein bisschen angepasst desweiteren habe ich versucht meinen php-fpm als Unix Socket laufen zu lassen kann ich diese Config ( /etc/php-fpm.d/www.conf >> “” listen = /tmp/php5-fpm.sock “” anstatt “”listen = 127.0.0.1:9000″” ) oder muss ich da noch was in deiner Config beachten.

    4. ich gehe mal davon aus das es deswegen auch zu folgender Fehlermeldung kommt

    2011/09/14 20:52:18 [error] 2142#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.190.1, server: server.ph0enyx.de, request: “GET / HTTP/1.1″, upstream: “fastcgi://127.0.0.1:9000″, host: “server.ph0enyx.de”
    2011/09/14 20:52:18 [error] 2142#0: *1 open() “/var/www/server.ph0enyx.de/web/favicon.ico” failed (2: No such file or directory), client: 192.168.190.1, server: server.ph0enyx.de, request: “GET /favicon.ico HTTP/1.1″, host: “server.ph0enyx.de”

    Ich weis viele Fragen aber ich hoffe du kannst mir sie vielleicht beantworten.

    G Martin

  • http://suckup.de/about voku

    zu 1.) jop

    zu 2.) der user von nginx schreibt die Logs z.B.: /etc/nginx/nginx.conf -> user www-data;

    zu 3.) du musst den selben Port in der nginx-config (z.B.: fastcgi_pass 127.0.0.1:9000;) und in der php-fpm-config angeben

    Mfg