Die Artikelreihe zum Thema “Trennung von Webanwendungen untereinander”, die mit fastcgi, suphp und zwei Artikeln über das klassische suexec begann, findet heute ihren
vorläufigen Abschluss mit dem Setup, für das ich mich letztendlich entschieden habe.
Da auf dem von mir angepeilten Zielsystem nur eine Handvoll Präsenzen mit ähnlich wenigen verschiedenen Webanwendungen
ins Hosting kommen wird, könnte ich mich für eine Lösung entscheiden, deren Skalierungsverhalten sie für
“richtiges” Hosting uninteressant macht. Jede Webapplikation bekommt einen eigenen apache, der gleich unter
einer nicht priviligierten uid gestartet wird und auf einem hohen Port von 127.0.0.1 Verbindungen annimmt. Das Mapping
auf die “offizielle” IP und Port 80 übernimmt ein zentraler “normaler” apache als reverse
proxy.
Dieser Artikel entstand ursprünglich im Jahr 2006. Fünf Jahre später hat auch Debian es geschafft, mehrere
apache-Instanzen “ordentlich” zu unterstützen, und ganz ohne gepatchte Scripts. Diese überarbeitete
Version dieses Artikels beschreibt die Vorgehensweise unter dem in 2011 aktuellen Debian squeeze.
Das ganze Verfahren unter Debian stable mit apache2 zu implementieren war verhältnismäßig einfach. Ich habe mich
bemüht, die Arbeit der Debian-Maintainer so weit wie möglich zu nutzen, da mir das Packaging von apache2
außerordentlich gut gefällt. Also sind ein patch gegen apache2ctl, ein kompletter Rewrite von a2[en|dis][mod|site] und ein severely patched initscript dabei rausgekommen, mit deren Hilfe das Management
der vielen verschiedenen Apaches einfach geworden ist. Debian hat meine Patches natürlich nicht 1:1 übernommen, aber
inzwischen geht es auch ohne gepatchte scripts.
Auf dem Zielsystem setzen wir das Verfahren wie folgt ein:
- Jeder Apache bekommt einen eigenen Unix-User (user-appname) mit
eigenem Homedirectory.
- In diesem Homedirectory kann der User nicht schreiben, die Dateien dort gehören user:user-webapps
- unter /home/user-appname/apache wird eine abgespeckte
Apache-Konfiguration hinterlegt, in der auch konfiguriert ist, dass der apache untr dem Account user-appname laufen und auf einem hohen Port unter 127.0.0.1 horchen soll.
- Diese Konfiguration wird nach /etc/apache2-user verlinkt
- Ein spezielles Initscript /etc/init.d/apache2-user wird aus /usr/share/doc/apache2.2-common/examples/secondary-init-script (z.B. mit
/usr/share/doc/apache2.2-common/examples/setup-instance) erzeugt
- Mit insserv apache2-user wird das Initscript aktiviert und an der
passenden Stelle in die dependency-based Bootreihenfolge eingehängt
- Die Applikation liegt in /home/user-appname/applikation.
- Apache-Module lassen sich mit dem erweiterten a2enmod einfach
lokal aktivieren.
- Der Apache lässt sich dann mit dem erweiterten Initscript einfach unabhängig von den anderen apaches
starten.
- Der “Haupt-Apache” wird per ProxyPass und ProxyPassReverse so konfiguriert, dass Zugriffe auf den entsprechenden
Namensraum zum “richtigen” User-apache weitergereicht werden.
mod_rpaf sorgt in den Applikations-Apachen dafür, dass die vom
Proxy übermittelten Client-IPs in den Logs landen und IP-basierte Auswertungsmechanismen (z.B. zur Spamabwehr)
funktionieren.
Auf diese Weise ist sichergestellt, dass die Webapplikationen getrennt voneinander laufen. Per Rechtevergabe im
Dateisystem kann man nun erreichen, dass eine Webapplikation nur dort lesen und schreiben kann, wo es unbedingt
notwendig ist. Die apache-Konfiguration kann entsprechend abgespeckt sein.
Diese Lösung hat natürlich auch ein paar Nachteile, zum Beispiel den exorbitanten Speicherbedarf duch die wirlich
vielen apache-Prozesse im Speicher und die Tatsache, dass manche Webapplikationen sich herausgefordert fühlen, wenn
plötzlich Portnummern in den URLs stehen und der Client mit anderen URIs kommt als man selbst weggeschickt hat. Weitere
Nachteile sind mir in den fünf Jahren, die das Setup auf dem Zielsystem so bereits in Verwendung ist, bis heute nicht
aufgefallen.
Wenn die Applikation Cookies benutzt, ist zu beachten, dass die Applikation ihre Cookies mit einer Domain versieht, und
zwar in der Regel mit 127.0.0.1:x, weil der Applikations-Apache nicht weiß, unter welchem Domainnamen der Server
letztendlich läuft. Das hat mich mit meinem Blog einige Tage Debuggingarbeit gekostet, und ohne die Hilfe von Garvin,
Isotopp, Rince und anderem wäre das niemals erfolgreich gewesen.
Die Lösung ist in der Konfiguration des Reverse Proxy:
ProxyPassReverseCookieDomain 127.0.0.1:1312 blog.zugschlus.de
ProxyPassReverseCookieDomain 127.0.0.1 blog.zugschlus.de
Der doppelte ProxyPassReverseCookieDomain ist nötig, weil aus irgendwelchen gründen manche Cookies mit und manche ohne
Portnummer gesendet werden.
<p>Marc beschreibt eine Methode Webapplikationen über mehrere Apache-Instanzen sicher voneinander zu trennen - auch wenn man nur eine IP zur Verfügung hat. <br /> Die entsprechenden Patches, Skripte und eine Beschreibung gibt es in seinem Weblog. Ganz ohne Nachteile geht es nicht, vor allem skaliert diese Lösung nicht gut, aber für es gibt sicher genug Anwendungsmöglichkeiten. </p> Comment (1)
Tracked: Feb 18, 23:00