[HOWTO] LEMP Stack + SSL - Debian 6.0

  • [HOWTO] LEMP Stack + SSL - Debian 6.0



    0.) Einleitung
    0.1) Was ist das überhaupt? Ich kenne nur LAMP
    Ein LAMP und LEMP Stack unterscheiden sich schon beim Hinsehen nur durch den 2. Buchstaben: A wird durch E vertauscht, doch was bedeutet das?
    LEMP ist das selbe wie LAMP mit dem Unterschied, dass statt Apache (A) nun nginx(sprich: "engine-ex") also (E) verwendet wird.
    0.2) Warum nginx?
    Apache ist zwar der populärste Webserver, aber als eine Art eierlegende Wollmilchsau auch nicht gerade der performanteste. V.a. bei vServern stößt Apache schon bei kleinen/mittleren Seiten an die RAM-Limits der VM. nginx ist auch ein Webserver, jedoch ist er im Gegensatz zu Apache sehr leichgewichtig, schnell und Performant ausgelegt. Dies ist auch höchstes Ziel bei dessen Entwicklung. Trotzdem bietet nginx kaum Einschränkungen, was die Funktionalität angeht und auch seine Konfiguration ist der von Apache sehr ähnlich und unterscheidet sich nur in geringen Punkten.
    0.3) Warum nehmen dann alle Apache, wenn nginx doch angeblich so viel besser ist?
    Apache is der de-facto Standard: Sehr einfach zu konfigurieren, multiplattformkompatibel und ist praktisch in jeder Distribution dabei. Nginx ist weniger bekannt und gilt als schwer zu konfigurieren, was jedoch ein weit verbreiteter Irrglaube ist. Doch das wird im weiteren Verlauf offensichtlicher.


    1.)Vorbereitungen / Voraussetzungen
    1.1) Voraussetzungen:

    • Gesunder Menschenverstand(!)
    • Vorerfahrung auf der Kommandozeile
    • Grundwissen Funktionsweise Server/Netzwerke und Linux (SSL bei Bedarf)
    • Bitte informieren sie sich über sog. "Fremdquellen"
    • Gute Laune und Durchhaltevermögen ;)
    • Debian 6.0, up-to-date und passend konfiguriert

    1.2) Vorbereitungen:
    Zuerst müssen wir noch eine sog. Fremdquelle hinzufügen. Leider haben es die aktuelle Version von "php5-fpm" und "nginx" nicht in die Debian-Pakete geschafft.
    Daher empfehle ich, sie via Fremdquelle nachzurüsten. Dotdeb - The repository for Debian-based LAMP servers bietet aktuelle Pakete rund um LAMP auf Debian Servern an, unter anderem die von uns benötigten.


    Disclaimer: Die Pakete dieser Fremdquelle sind nicht durch Debian.org/Netcup/mich geprüft! Pakete aus Fremdquellen können Schadsoftware enthalten und somit das System beschädigen! Installieren sie Pakete aus Fremdquellen nur, wenn sie diesen Quellen vertrauen. Die Installation erfolgt auf eine Gefahr!


    Um dotdeb hinzuzufügen, sind folgende Zeilen an die /etc/apt/sources.list anzuhängen:


    Code
    1. #Dotdeb.org LAMP Packages:
    2. deb http://packages.dotdeb.org squeeze all
    3. deb-src http://packages.dotdeb.org squeeze all


    Zusätzlich muss noch der Schlüssel importiert werden, mit dem die Pakete der Quelle unterschrieben sind:

    Code
    1. :~$ wget http://www.dotdeb.org/dotdeb.gpg
    2. :~$ cat dotdeb.gpg | sudo apt-key add -


    Um auf die neuen Pakete zugreifen zu können, müssen wir die Paketlisten neu laden:

    Code
    1. :~$ apt-get update


    Jetzt ist die Paketquelle eingebunden und wir können Software aus ihr installieren.



    2.)MYSQL


    Den MySQL Server installieren wir mit

    Code
    1. apt-get install mysql-server


    Legt bitte während der Installation ein sicheres Passwort fest.
    Die Standardkonfiguration ist bereits sehr sicher, da der Server nur auf Anfragen von localhost, also 127.0.0.1:3306 reagiert.
    Wer sich mit den Einstellungen trotzdem vertraut machen möchte, kann einen Blick in die /etc/mysql/my.cnf wagen.
    Dort kann man Port und weitere Einstellungen ändern.
    Das init-Script für den MySQL Server liegt unter /etc/init.d/mysql
    Wer seinen Server per GUI verwalten möchte, dem sei die "MySQL Workbench" ans Herz gelegt, diese ermöglicht eine Verwaltung und Zugriff über SSH, daher muss der Server nicht umkonfiguriert werden und steht weiterhin nur localhost zur Verfügung, was u.a. den höchsten Sicherheitsstandard darstellt.
    Infos hierzu:MySQL :: MySQL Workbench :: 6.6.4 Standard TCP/IP over SSH Connection
    Nutzer und Datenbanken anlegen ist nicht Gegenstand dieser Anleitung, diese Informationen liefert euch die Suchmaschine eures Vertrauens.



    3.) PHP
    PHP installieren wir via

    Code
    1. :~$ sudo apt-get install php5 php5-fpm php-pear php5-common php5-mcrypt php5-mysql php5-cli php5-gd


    Auch dieser Dienst bringt Standardmäßig schon gute Einstellungen mit.
    Einige Werte möchte man aber doch verändern. Die Einstellungen für das Verhalten des PHP-FPM(FastCgi Process Manager, der Dienst, der PHP hier bereitstellt),
    kann man in der Datei /etc/php5/fpm/php-fpm.conf beeinflussen.
    Folgende Einstellungen sind sinnvoll:

    Code
    1. emergency_restart_threshold = 15
    2. emergency_restart_interval = 1m
    3. process_control_timeout = 15s


    Und das bedeuten sie: Die ersten beiden Werte geben das Verhalten im Notfall vor: Wenn 15 php prozesse in 1m(inute) mit SIGSEGV/SIGBUS beendet werden(abstürzen), so wird der php5-fastcgi dienst neu gestartet.(Empfohlen)
    Die 3. Zeile legt die Zeit fest, wie lange php prozesse auf signale des "Master-Prozesses" warten dürfen.(Optional)


    Um den FPM zu starten / stoppen bedienen wir uns dem folgenden init-Skript: /etc/init.d/php5-fpm


    Jedoch möchten/müssen viele Admins Werte in der php.ini Datei verändern, um ihre Webanwendungen zu Betreiben.
    Die php.ini liegt bei dieser Konfiguration unter /etc/php5/fpm/php.ini.
    Es sei jedem angeraten die php.ini abzusichern, da sonst ungesicherte PHP-Skripte eine Schwachstelle bieten können. Eine passende Erklärung findet sich hier:
    Die PHP.ini - PHP gegen Angriffe absichern


    Es gibt zusätzlich die Möglichkeit, dem FPM anzugeben, wieviel RAM/prozesse er nutzen darf. Dies kann die Performance stark verbessern, sprengt jedoch den Rahmen dieses Howto´s.
    Interessierte können sich einmal diese Werte ansehen:

    Code
    1. pm.max_children = 9
    2. pm.start_servers = 3
    3. pm.min_spare_servers = 2
    4. pm.max_spare_servers = 4
    5. pm.max_requests = 200


    Auch im Netz findet sich dazu einiges.



  • 4.)nginx
    Kommen wir nun zum Sahnehäubchen: Dem Webserver nginx, also dem Herzstück unserer LEMP Umgebung.
    Installation:

    Code
    1. :~$ sudo apt-get install nginx


    Starten/Stoppen lässt sich nginx wie auch die anderen Serverdienste per init-Skript, es liegt unter /etc/init.d/nginx


    Die Konfigurationsdatei von nginx liegt unter /etc/nginx/nginx.conf
    Folgende, wichtigste Einstellungen solltet ihr an euer System anpassen:


    Das war die Serverkonfiguration. Jetzt müssen die sog. Virtual-Hosts konfiguriert werden.
    Ein vHost(Virtual-Host) repräsentiert quasi einen virtuellen Webserver, sodass ein nginx Server mehrere Seiten hosten kann.
    Weitere infos: Virtual Hosting – Wikipedia
    Dafür gibt es zwei ordner:


    • /etc/nginx/sites-available
    • /etc/nginx/sites-enabled


    Sämtliche vHosts werden in "sites-available" erstellt und dann eine Verknüpfung auf sie in "sites-enabled" angelegt.
    Zuersteinmal wollen wir den "Default" loswerden, lösche also dazu die Verknüpfung:

    Code
    1. :~$ rm /etc/nginx/sites-enabled/default


    Erstellt jetzt eine Datei, die wie eure Domain heißt im Ordner "sites-available" mit folgendem, angepasstem Inhalt:


    die Erklärungen zu den Werten sind als Kommentare in der Datei verfasst.
    Diese Beispielkonfiguration "/etc/nginx/sites-available/beispiel.de" hostet z.B. die Seite "Beispiel.de" im Verzeichnis "/var/www/beispiel.de".


    Um die Konfiguration anzuschalten, muss nun noch eine Verknüpfung im "sites-enabled" Ordner angelegt werden:

    Code
    1. :~$ ln -s /etc/nginx/sites-available/beispiel.de /etc/nginx/sites-enabled/beispiel.de


    Dann muss nginx via init-Skript neugestartet werden.
    Das schöne an nginx: Passt seine Konfiguration nich genau/ist stark unsicher, so verweigert er den Start. Startet nginx, habt ihr also alles richtig gemacht.


    Wer eine Zugriffsverwaltung ala .htaccess umsetzen möchte, dem sei folgende Seite aus der nginx-Dokumentation ans Herz gelegt, welche das sehr schön erläutert:
    HttpAuthBasicModule

  • 5.) SSL
    5.1) Voraussetzungen
    Es muss bereits ein gültiges SSL-Zertifikat vorhanden sein! Wie man kostenlos an ein SSL-Zertifikat kommt, das immerhin ein Jahr lang gültig ist, erklärt Heise Security sehr schön:
    SSL für lau | heise Security
    (Natürlich nur bis zu dem Punkt, wo man alle Zertifikate runterlädt; Das Einspielen in den Apache ist für uns natürlich nicht wichtig)
    Und wem das ein wenig zu schnell ging, findet hier noch eine etwas ausführlichere Anleitung:
    SSL für lau Kostenlose Zertifikate einrichtenLazybone | Lazybone


    Ich gehe von folgendem Start-Szenario aus:
    Im HOME Ordner eures Benutzers liegen folgende Zertifikatsdateien(hier wieder am beispiel.de):


    • beispiel.de.crt <- Public Key, Bekommt ihr von StartSSL / Eurer CA
    • beispiel.de.key <-Private Key, Bekommt ihr von StartSSL / Eurer CA
    • sub.class1.server.ca.pem (oder ähnlich) <-
    • CertificateChain: Wird benötigt, um euer Zertifikat euer CA zuzuweisen,
    • bekommt ihr auch von eurer CA


    Die CertificateChain für StartSSL bekommt ihr übrigens unter
    Index of /certs , die Datei heißt "sub.class1.server.ca.pem"


    Jetzt müssen wir noch einen letzten Schritt durchführen, bevor wir die Zertifikate an die passenden Stellen kopieren können:
    Wirmüssen an unser Server-Zertifikat (beispiel.de.crt) noch die sog. Authentifizierungskette(CertificateChain) anhängen, dass auch nachvollzogen werden kann, dass unser Zertifikat von ihr kommt. Das erledigt folgender Befehl und speichert das entstehende Zertifikat als "beispiel.de.chained.crt"

    Code
    1. :~$ cat beispiel.de.crt sub.class1.server.ca.pem > beispiel.de.chained.crt


    Passt in diesem Befehl die Dateinamen euren einfach an.
    Wichtig:
    Die Reihenfolge darf nicht vertauscht werden, sonst wirft nginx beim
    starten einen Fehler. Sie muss immer folgendem Muster folgen:

    Code
    1. :~$ cat PublicKeyFile.crt CertificateChainFile.XXX > ChainedPublicKeyFile.crt


    Die CertificateChainFile kann verschiedene Endungen besitzen, am Gebräuchlichsten sind ".crt" und ".pem"


    Habt ihr diese Datei hergestellt, erstellt folgende Ordner:


    • /etc/ssl
    • /etc/ssl/certs #Für öffentliche Schlüssel, CertificateChains
    • /etc/ssl/private #Für unsere Privaten Schlüssel


    Kopiert in "/etc/ssl/certs" folgende Dateien: "beispiel.de.crt", "beispiel.de.chained.crt". "sub.class1.server.ca.pem"
    Kopiert in "/etc/ssl/certs" folgende Datei: "beispiel.de.key"


    Das wars, jetzt müssen wir nginx nur noch beibringen, diese Zertifikate auch zu verwenden.


    5.2) nginx und SSL
    Der Beispiel vHost, welcher uns schon bekannt ist, jetzt aber sowohl http-, als auch https-Verbindungen unterstützt:



    Die Parameter die neu dazukamen, wurden entsprechend Kommentiert.


    Um die Änderungen zu Übernehmen, muss nginx neugestartet werden.


    5.3) Troubleshooting


    Wenn nginx mit folgender Fehlermeldung versagt, wurden die Parameter beim generieren der CertificateChainKeyFile vertauscht, die Datei beispiel.de.chained.crt ist also falsch:

    Code
    1. SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
    2. (SSL: error:0B080074:x509 certificate routines:
    3. X509_check_private_key:key values mismatch)


    Bei diesem Schritt muss die Reihenfolge genau eingehalten werden.


    6) Testen:


    Jetzt können wir die Umgebung testen. Dazu müssen alle installierten und konfigurierten Server gestartet werden.


    Dann erstellen wir im Verzeichnis der Website (hier: /var/www/beispiel.de/) die Datei index.php


    Und füllen sie mit folgendem Inhalt:

    PHP
    1. <?php
    2. phpinfo();
    3. ?>


    Jetzt müssen wir sie nur noch dem passenden Nutzer zuordnen, sodass nginx auch darauf zugreifen kann:

    Code
    1. :~$ chown -R www-data:www-data /var/www/beispiel.de


    Dieser Befehl setzt im ganzen Ordner /var/www/beispiel.de die Zugriffsrechte
    passend, sodass nginx, der unter www-data läuft darauf zugrifen kann.


    Startet jetzt nginx neu.


    Jetzt kann man im Browser auf seine Domain gehen(hier Beispiel.de) und bekommt eine PHP-Info Seite angezeigt. Wenn man "https://beispiel.de" besucht, so sollte die Verbindung mit https gesichert sein. Bekommt man eine Warnung, dass das Zertifikat nicht verifiziert werden kann und aus einer unbekannten Quelle stamme, so hat dies eine(oder beide) der beiden Ursachen:


    • Beim Einbinden der CertificateChain ist etwas schiefgelaufen, daher kann deine CA nicht ausfindig gemacht werden
    • Deine CA ist nicht vertrauenswürdig(z.B. eigens erstellte CA)

    Um das erstere zu Beheben musst du die Schritte oben zum Einbinden wiederholen oder diverse Suchmaschinen/Foren bemühen. Das zweite ist ein anderes Problem: In gängigen Browsern werden nur Zertifikate von großen CA´s akzeptiert. Eigene CA´s / kleine CA´s produzieren eine Sicherheitswarnung. Jedoch kannst du in deinem Betriebssystem das
    Zertifikat der CA installieren, dann wird von diesem Rechner der CA ebenfalls vertraut. Auch hierfür konsultierst du am besten eine Suchmaschine/ ein Forum.



    Nach einem erfolgreichen Test sollte die Datei in

    PHP
    1. <?php
    2. echo "Hello World!";
    3. ?>


    umgeändert werden, da der phpinfo(); Befehl sehr viel über das installierte PHP System preisgibt.


    Wenn ihr die Datei jetzt mit root Rechten geändert habt, müsst ihr nocheinmal obigen "chown befehl" ausführen!


    Das wars, ihr habt jetzt ein fertiges und schnelles System, das noch dazu wenig Ressourcen braucht. Glückwunsch!


    Ich hoffe, dieses Howto hat ein wenig Licht in die Lage nginx/SSL gebracht und dem ein oder anderen geholfen.


    PS: Bestünde Interesse an einem Howto über PHP Beschleuniger?

  • Hi,


    eine nette Anleitung, ich würde jedoch PHP nicht über den Netzwerkstack laufen lassen (php-cgi), sondern über einen Socket, vor allem wenn du schon php-fpm installierst. So bekommst du keinen Datenmüll, wenn du mal vorhast das "lo" Interface aufzuzeichnen. Das würde bedeuteten in /etc/php5/fpm/pool.d/ die bisherige Konfiguration anzupassen:


    listen = 127.0.0.1:9000
    listen = /var/run/php5-fpm.www.sock


    Anschließend nun den Socket in nginx eintragen:


    fastcgi_pass 127.0.0.1:9000;
    fastcgi_pass unix:/var/run/php5-fpm.www.sock;


    Nun php-fpm neustarten und nginx neuladen.

  • Sehr schöne Anleitung, ich bin auch dafür, dass man sie ins Wiki aufnimmt.
    Es hat sich jedoch ein kleiner Fehler eingeschlichen:


    Quote

    Kopiert in "/etc/ssl/certs" folgende Dateien: "beispiel.de.crt", "beispiel.de.chained.crt". "sub.class1.server.ca.pem"
    Kopiert in "/etc/ssl/certs" folgende Datei: "beispiel.de.key"


    Der Private Key sollte in den private Ordner.

  • Sehr schönes Tutorial, genau sowas habe ich gesucht. :)


    Habe da auch direkt eine Frage.

    Quote

    worker_processes 5; #Wieviele Prozesse darf nginx spawnen? Empfohlen: 12-24, maximal jedoch soviele wie Prozessoren im System verbaut sind.

    Bei den KVM-Servern, wären das ja dann maximal zwei (Uranus), oder? Zumindest sind es nur zwei verfügbare Kerne, laut der /proc/cpuinfo und den Produktinformationen.

  • Wenn du Software kompilierst, lautet die Faustregel n+1 für n CPU-Kerne. Wenn du dabei I/O-intensive Prozesse hast, dann kannst du auch mehr starten. Eine Festplatte bzw. Netzwerk bearbeitet deine Anfrage ja nicht in Nullzeit, sondern es gibt immer eine Verzögerung. Bei 2 Prozessen, wo einer auf die Festplatte und der andere auf das Netzwerk wartet, hättest du eine echte CPU-Auslastung von 0.

  • gutes tutorial,
    ich probiere es gerade aus (mit gleichzeitiger Installation von ispconfig 3)


    Es gibt zusätzlich die Möglichkeit, dem FPM anzugeben, wieviel RAM/prozesse er nutzen darf. Dies kann die Performance stark verbessern, sprengt jedoch den Rahmen dieses Howto´s.
    Interessierte können sich einmal diese Werte ansehen:

    Code
    1. pm.max_children = 9
    2. pm.start_servers = 3
    3. pm.min_spare_servers = 2
    4. pm.max_spare_servers = 4
    5. pm.max_requests = 200


    diese Einträge gehören dann in die jeweiligen "/etc/php5/fpm/pool.d/*.conf" -Dateien ?
    (oder wohin ?)


    ----------



    hierzu eine Syntaxfrage:
    die "listen" Einträge in den
    "/etc/php5/fpm/pool.d/*.conf" -Dateien (die sind doch gemeint oder ?)
    sind bei mir in folgender Sytax angegeben
    "listen = /var/lib/php5-fpm/apps.sock"
    "listen = /var/lib/php5-fpm/ispconfig.sock"
    müsste es dann nicht auch heissen
    "listen = /var/lib/php5-fpm/www.sock"
    (anstatt wie oben angegeben "listen = /var/run/php5-fpm.www.sock"


    entsprechend dann in den vhosts
    fastcgi_pass unix:/var/lib/php5-fpm/www.sock;
    ??


    ----------------------


    genereller Tipp:
    auch hier mal schauen:
    --> HowtoForge Linux Tutorials » Konfigurierung Ihres LEMP Systems (Linux, nginx, MySQL, PHP-FPM) für maximale Leistung

  • Wie du die Socket-Datei nennst ist egal. ;)


    hmmm...
    also bei mir liegen die socks im Verzeichnis "/var/lib/php5-fpm/"
    dementsprechend muss die Angabe doch sein (korrekte Pfad-Syntax) z.B.: /var/lib/php5-fpm/www.sock
    steht hier zumindest auch so:
    HowtoForge Linux Tutorials » Konfigurierung Ihres LEMP Systems (Linux, nginx, MySQL, PHP-FPM) für maximale Leistung
    unter Punkt 3.5


    [Edit] sorry, jetzt hab ich's auch verstanden :whistling:

  • Leider komme ich im Moment wenig zum schreiben, sonst würde ich ne bessere Version nachschieben, aber das sollte in ca. 2 Wochen vorbei sein.


    Zu einigen Sachen oben möchte ich trotzdem was schreiben, auch wenn es sicher schon ein paar Tage her sein mag ;)


    @Slavit: Bei den KVM Servern: Ja, im Prinzip schon, aber bei wenigen Kernen kann man auch von dieser groben Maßgabe abweichen ;)
    Es ist nur folgendes wichtig: Man sollte sich im klaren sein, dass ein Linux-Server jedem Prozess/Thread möglichst gleich viel Rechenzeit geben möchte(sog. Scheduling). Hat man pro Kern also 10 Threads, bekommen alle 10 nur jeweils 1/10 der Rechenzeit. D.h. man hat de facto keinen Performancegewinn gegenüber 5 Threads(zumindest nicht spürbar), welche jeweils 1/5 der Rechenzeit bekommen. Der Vorteil an der einstellbaren Threadanzahl sind die "ganz normalen" vServer von netcup: Da man bis zu 24 Prozessorkerne nutzen kann, kann man auch 24 Kernen Aufgaben zuweisen für maximale Parallelität und kein Kern ist untätig.


    Bei deinem KVM Server würde ich eine Threadanzahl zwischen 2 und 6 empfehlen. Weniger macht keinen Sinn, da sonst ein Kern nicht ausgelastet wäre, mehr auch nicht, da sich die nginx Threads sonst dank Linux-Scheduling selbst im Weg sind(zumindest, wenn du nicht grade planst, einen riesigen Internetauftritt zu hosten). ;)



    Dirk67 :


    Zu den Werten für die Performance:


    Code
    1. pm.max_children = 9
    2. pm.start_servers = 3
    3. pm.min_spare_servers = 2
    4. pm.max_spare_servers = 4
    5. pm.max_requests = 200


    Die Schalter müssten, wie bereits erwähnt, schon in den Pool-Dateien stecken, wenn nicht schreib sie da einfach rein ;)
    Wobei ich über gute und schnelle Konfiguration sowieso noch ein Howto machen würde.
    Dieses war dediziert eigentlich nur zur Einrichtung da ;)


    Das mit dem Socket war ja dann auch schon geklärt :)



    Wisst ihr wie/ob man hier als Kunde denn was ins Netcup Wiki schreiben kann?


    \TIA