Zum Inhalt springen

Apache-Grundkonfiguration verstehen

Die Stellschrauben ausserhalb der .htaccess: VirtualHost-Aufbau, welche Module wirklich gebraucht werden, die Wahl des MPM und Logformate, aus denen sich etwas ablesen lässt.

Zuletzt geprüft: Gedacht für: eigener Server oder vServer

Das Wichtigste

  • Ein VirtualHost pro Domain, und immer einen Standard-Host definieren – sonst beantwortet der erste geladene Host alle unbekannten Anfragen.
  • Mit mpm_event und PHP-FPM statt mpm_prefork mit mod_php sinkt der Speicherbedarf bei gleicher Last deutlich.
  • AllowOverride None plus Regeln direkt im VirtualHost spart einen Verzeichnis-Scan pro Request.
  • Jedes geladene Modul kostet Speicher in jedem Worker. Der Standardsatz vieler Distributionen enthält Module, die kein Webprojekt braucht.

Auf Shared Hosting endet die Konfiguration bei der .htaccess. Sobald du einen eigenen Server betreibst, verschiebt sich das Meiste in die Serverkonfiguration – und dort ist es schneller, sicherer und leichter zu versionieren.

VirtualHost: eine Datei pro Domain

<VirtualHost *:443>
  ServerName example.com
  ServerAlias www.example.com
  DocumentRoot /var/www/example.com/public

  <Directory /var/www/example.com/public>
    Options -Indexes +FollowSymLinks
    AllowOverride None
    Require all granted
  </Directory>

  SSLEngine on
  SSLCertificateFile      /etc/letsencrypt/live/example.com/fullchain.pem
  SSLCertificateKeyFile   /etc/letsencrypt/live/example.com/privkey.pem

  ErrorLog  /var/log/apache2/example.com-error.log
  CustomLog /var/log/apache2/example.com-access.log combined
</VirtualHost>

Zwei Punkte, die häufig fehlen:

Ein Standard-Host. Apache beantwortet jede Anfrage, deren Host-Header zu keinem ServerName passt, mit dem zuerst geladenen VirtualHost. Ohne bewusst gesetzten Default landen fremde Domains, die versehentlich oder absichtlich auf deine IP zeigen, auf einem echten Projekt. Ein leerer Host, der nur mit Redirect 404 / antwortet und alphabetisch zuerst geladen wird, verhindert das.

AllowOverride None. Steht dort All, sucht Apache bei jedem einzelnen Request in jedem Verzeichnis des Pfads nach einer .htaccess. Auf einem Server, den du selbst konfigurierst, gehören die Regeln in den Directory-Block – dann liest Apache sie einmal beim Start.

Module: weniger ist schneller

apachectl -M | sort

Der Standardsatz vieler Distributionen enthält Module, die ein normales Webprojekt nicht braucht. Was in der Regel bleiben sollte:

Modulwofür
rewriteWeiterleitungen und saubere URLs
headersSicherheits- und Cache-Header
deflate / brotliKompression
expiresCache-Zeiten
sslHTTPS
http2HTTP/2
proxy_fcgiAnbindung an PHP-FPM

Abschalten oder eng beschränken: status, info, userdir, autoindex, cgi. mod_status ist nützlich, gehört aber hinter eine IP-Beschränkung, sonst liest jeder die aktuellen Requests deines Servers mit.

MPM und PHP

Die Prozessverwaltung entscheidet, wie viel Speicher der Server unter Last braucht.

  • mpm_prefork startet pro gleichzeitiger Verbindung einen eigenen Prozess. Nötig, wenn PHP als mod_php eingebunden ist, weil das nicht threadsicher ist. Jeder Prozess trägt dann den PHP-Interpreter mit.
  • mpm_event arbeitet mit Threads und hält wartende Verbindungen in einem eigenen Thread. In Kombination mit PHP-FPM braucht derselbe Server bei gleicher Last spürbar weniger Speicher.
<IfModule mpm_event_module>
  StartServers            2
  MinSpareThreads        25
  MaxSpareThreads        75
  ThreadsPerChild        25
  MaxRequestWorkers     150
  MaxConnectionsPerChild 10000
</IfModule>

MaxRequestWorkers ist die Zahl, die zählt: Multipliziere sie mit dem durchschnittlichen Speicherbedarf pro Request und vergleiche das Ergebnis mit dem verfügbaren RAM. Liegt es darüber, beginnt der Server unter Last zu swappen, und das ist langsamer als jede Ablehnung.

Sicherheits-Header zentral setzen

<IfModule mod_headers.c>
  Header always set X-Content-Type-Options "nosniff"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set X-Frame-Options "SAMEORIGIN"
  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

ServerTokens Prod
ServerSignature Off

Strict-Transport-Security erst setzen, wenn HTTPS wirklich überall funktioniert und du includeSubDomains auch für jede Subdomain einhalten kannst. Browser merken sich den Header für die angegebene Dauer, ein Rückzieher ist praktisch nicht möglich.

Logs, aus denen sich etwas ablesen lässt

Das Standardformat combined reicht für die meisten Fälle. Wer Antwortzeiten sucht, ergänzt sie:

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" timing
CustomLog /var/log/apache2/example.com-access.log timing

%D ist die Bearbeitungsdauer in Mikrosekunden. Damit lassen sich langsame Endpunkte direkt aus dem Log herausziehen:

awk '{print $NF, $7}' access.log | sort -rn | head -20

Für die Auswertung über längere Zeiträume ist eine Logfile-Analyse das passende Werkzeug – sie zählt auch die Zugriffe, die kein JavaScript ausführen, und damit den Bot-Anteil.

Häufige Fragen

Warum liefert mein Server bei einer unbekannten Domain die falsche Seite aus?

Apache beantwortet Anfragen, die zu keinem ServerName passen, mit dem zuerst geladenen VirtualHost. Lege einen bewusst leeren Default-Host an, der mit 404 oder 444 antwortet, und lass ihn alphabetisch zuerst einlesen – üblich ist der Dateiname 000-default.conf.

Welches MPM soll ich nehmen?

mpm_event, sofern PHP über FPM läuft. mpm_prefork ist nur nötig, wenn mod_php eingebunden ist, und kostet dann pro gleichzeitiger Verbindung einen vollständigen Prozess mit PHP im Speicher.

Wie finde ich heraus, welche Module geladen sind?

Mit apachectl -M. Vergleiche die Liste mit dem, was deine Projekte tatsächlich nutzen. Module wie mod_status, mod_info oder mod_userdir gehören auf produktiven Servern in der Regel abgeschaltet oder streng beschränkt.

Muss ich Apache nach jeder Änderung neu starten?

Ein reload genügt für Konfigurationsänderungen und hält bestehende Verbindungen. Prüfe vorher immer mit apachectl configtest – ein Syntaxfehler beim reload lässt den laufenden Dienst zwar stehen, beim restart aber nicht wieder hochkommen.