Apache2, nginx oder lighttpd? Der Webserver-Vergleich für Selfhoster
Alle drei liefern HTML aus, alle drei sind erprobt, alle drei sind in jeder Distribution. Und trotzdem ist die Wahl keine Geschmacksfrage: Apache 2.4, nginx und lighttpd unterscheiden sich im Konfigurationsmodell, im Speicherverhalten und darin, wie gut sie als Verteiler vor Anwendungen funktionieren. Dieser Vergleich ordnet die drei ohne Benchmark-Mythologie ein – mit denselben Aufgaben in allen drei Konfigurationssprachen und einer Entscheidungshilfe, die auf deinen Anwendungsfall zielt statt auf Messwerte aus fremden Rechenzentren.
Warum die Frage meist falsch gestellt wird
Die verbreitete Frage lautet: „Welcher Webserver ist der schnellste?“ Sie führt zu Benchmarks, die statische Dateien mit maximaler Nebenläufigkeit ausliefern – eine Situation, die im Selfhosting fast nie vorkommt. Deine Nextcloud, dein Blog, deine Weboberfläche liefern dynamische Antworten: Die Zeit entsteht in Datenbank, PHP-Prozessen oder im Proxy dahinter, nicht im Webserver selbst.
Die tatsächlich relevanten Fragen sind andere:
| Frage | Warum sie entscheidet |
|---|---|
| Wo liegt die Konfiguration? | Zentral in Dateien oder pro Verzeichnis über .htaccess – das bestimmt, wie du wartest und wer ändern darf. |
| Wie viel Speicher darf es kosten? | Der Webserver ist auf kleinen VPS die zweitgrößte RAM-Position nach der Datenbank. |
| Was läuft dahinter? | PHP, Python, Node, Container – jeder Webserver hat dafür eigene Anbindungen. |
| Brauchst du Sonderfunktionen? | WebDAV, mod_security, Zugriffssteuerung pro Ordner, Rewrite-Ketten – hier trennt sich das Feld. |
| Wer wartet das System? | Ein Modul weniger ist ein CVE weniger. Wer selten Updates fährt, profitiert von schlanken Setups. |
.htaccess brauchst. nginx ist die Wahl für statische Inhalte,
TLS-Terminierung und alles, was vor Anwendungen steht. lighttpd ist die Wahl, wenn Platz und Speicher
knapp sind und die Aufgabe überschaubar bleibt.
Drei Architekturen, drei Denkweisen
Der Unterschied zwischen den drei Servern ist nicht „schnell“ oder „langsam“, sondern wie sie mit vielen gleichzeitigen Verbindungen umgehen.
| Modell | Wer arbeitet so | Konsequenz |
|---|---|---|
| Prozess oder Thread pro Verbindung | Apache mit prefork und worker | Einfach zu verstehen, robust – aber jede offene Verbindung kostet Speicher |
| Ereignisbasiert mit vielen Verbindungen pro Prozess | Apache mit event (Standard), nginx, lighttpd | Wenige Prozesse, hohe Nebenläufigkeit, deutlich weniger Speicher pro Verbindung |
| Meister- und Arbeiterprozesse | nginx, Apache, lighttpd | Ein Neustart der Konfiguration trifft nie die laufenden Verbindungen hart |
Wichtig: Das alte „Apache kann keine vielen Verbindungen“-Argument ist überholt. Mit
mpm_event ist Apache der modernen Konkurrenz näher als sein Ruf. Was bleibt, sind andere
Kosten – etwa die Suche nach .htaccess-Dateien entlang des Pfads bei jedem Zugriff.
apache2ctl -M | grep mpm das
aktive Modul, auf Arch/CachyOS httpd -M | grep mpm. Steht dort prefork, lohnt
der Wechsel auf event – auf Debian mit a2dismod mpm_prefork && a2enmod mpm_event.
Apache 2.4: der Vielseitige
Apache ist der älteste der drei und der einzige mit Konfiguration pro Verzeichnis. Genau das ist sein Markenkern – und gleichzeitig sein Preis.
| Stärke | Was das praktisch bedeutet |
|---|---|
.htaccess | Regeln liegen im Website-Ordner und dürfen ohne root geändert werden – ideal für geteilten Webspace, unpraktisch für Server, die du ohnehin zentral pflegst. |
| Modulumfang | WebDAV, mod_security, umfangreiche Authentifizierung, Filter, Rewrite-Engine mit Bedingungen – vieles gibt es nur hier. |
| Dokumentationslage | Fast jedes Problem aus 25 Jahren Betrieb ist irgendwo beschrieben. |
| Verzeichnis-Optionen | Rechte, Indizes, Vererbung und Auth lassen sich pro Pfad sehr genau regeln. |
| Zwei Konfigurationskulturen | Debian/Ubuntu: /etc/apache2 mit sites-available, a2ensite, a2enmod. Arch/Fedora: /etc/httpd/conf/httpd.conf plus conf.d/. Beides ist „Apache“, sieht aber völlig anders aus. |
<VirtualHost *:80>
ServerName static.meine.domain
DocumentRoot /srv/www/static
<Directory /srv/www/static>
Options -Indexes +FollowSymLinks
# .htaccess aus: spart Zugriffe pro Anfrage und ist sicherer
AllowOverride None
Require all granted
</Directory>
DirectoryIndex index.html index.php
Header always set X-Content-Type-Options "nosniff"
ErrorLog /var/log/static-error.log
CustomLog /var/log/static-access.log combined
</VirtualHost>
AllowOverride None # … quittiert Apache beim Start mit
Illegal override option # – das # muss am Zeilenanfang stehen. Bei nginx ist
ein Kommentar hinter der Direktive dagegen üblich und erlaubt; wer zwischen beiden umsteigt, stolpert
genau darüber.
.htaccess: Ist AllowOverride nicht auf
None gesetzt, sucht Apache bei jedem Zugriff nach diesen Dateien im Pfad – nachvollziehbar
messbar als zusätzliche Latenz. Wenn du .htaccess nicht brauchst, schalte es ab und lege die
Regeln in die zentrale Konfiguration.
nginx: der Verteiler
nginx wurde als Ereignis-Server für hohe Nebenläufigkeit entworfen – und hat sich davon zum De-facto-Standard vor Anwendungen entwickelt. In diesem Blog läuft fast alles darüber: Reverse Proxy, TLS-Terminierung, Header und HTTP/3.
| Stärke | Was das praktisch bedeutet |
|---|---|
| Statische Auslieferung | Dateien, Bilder, Downloads gehen extrem günstig über die Bühne – wenig Speicher pro Verbindung. |
| Reverse Proxy | Upstreams, Keepalive, Lastverteilung, Websocket-Upgrade: alles im Kern enthalten, ohne Zusatzmodule. |
| Header und TLS | Security-Header, HSTS, Caching und Zertifikate an einer Stelle für alle Dienste. |
| HTTP/3 | Seit 1.25 im Lieferumfang – als einer der drei der einzige mit QUIC in den Standardpaketen. |
| Snippets | include erlaubt wiederverwendbare Bausteine für Header und Locations – gut wartbar bei vielen Diensten. |
| Grenze | Was das praktisch bedeutet |
|---|---|
Kein .htaccess | Keine Konfiguration pro Verzeichnis. Für Anwendungen, die das erwarten, musst du die Regeln in den Serverblock übersetzen. |
| Andere Rewrite-Logik | rewrite, try_files und location-Prioritäten sind mächtig, aber ein eigenes Denkmodell – und if in einer location ist eine bekannte Falle. |
| Module | Die meisten sind einkompiliert; dynamische Module gibt es, aber nicht jedes Paket bringt sie mit. |
lighttpd: der Leichtgewichtige
lighttpd war früh ereignisbasiert, als „leicht“ noch ein Alleinstellungsmerkmal war. Heute ist sein Argument nicht mehr die Geschwindigkeit, sondern der Fußabdruck: wenige Megabyte Speicher, eine kompakte Konfiguration, wenig Ballast.
| Stärke | Was das praktisch bedeutet |
|---|---|
| Speicherbedarf | Läuft auf Systemen, auf denen jedes Megabyte zählt: kleine VPS, Einplatinenrechner, NAS, Router. |
| Lesbare Konfiguration | Eine Datei, assoziativer Stil – deutlich kürzer als die Alternativen. |
| FastCGI und CGI | Klassische Anbindung für PHP und andere Sprachen, seit jeher solide. |
| Nebenläufigkeit | Viele gleichzeitige Verbindungen bei minimalen Mitteln. |
| HTTP/2 | Seit 1.4.56 enthalten, abhängig vom Build – mit lighttpd -V gegenprüfen. |
| Grenze | Was das praktisch bedeutet |
|---|---|
| Kleineres Ökosystem | Weniger Module, weniger fertige Beispiele, weniger aktuelle Blogbeiträge. Fehlersuche dauert länger. |
| Keine Sicherheitsmodule | Für Web-Application-Firewall-Funktionen brauchst du einen Vorschalter. |
| HTTP/3 | Nicht Teil der Standardpakete – wer HTTP/3 will, nimmt nginx oder einen CDN davor. |
Die große Vergleichstabelle
| Kriterium | Apache 2.4 | nginx | lighttpd |
|---|---|---|---|
| Architektur | MPMs: prefork, worker, event (Standard) | Meister- und Arbeiterprozesse, ereignisbasiert | Ereignisbasiert, minimal |
| Konfiguration | Zentral pro Vhost, zusätzlich pro Verzeichnis via .htaccess | Zentral in Server-Blöcken, keine Verzeichnisdateien | Eine Konfigurationsdatei, assoziativ |
| Struktur der Config | Schachtelung aus Tags, Vererbung pro Verzeichnis | Kontexte http, server, location | Schlüssel-Wert-Zuweisungen und Bedingungen |
| Per-Verzeichnis-Regeln | Ja, über .htaccess | Nein | Nein |
| PHP-Anbindung | php-fpm über Proxy oder fcgi, historisch mod_php | php-fpm über FastCGI-Socket | php-fpm oder FastCGI |
| Rewrite-Sprache | RewriteRule, RewriteCond | rewrite, try_files, location-Prioritäten | url.rewrite*, Bedingungen |
| Module | Größter Umfang, dynamisch ladbar | Überwiegend einkompiliert, dynamische Module möglich | Kompakt, wenig Auswahl |
| Reverse Proxy | Über mod_proxy gut, aber weniger verbreitet | Kernkompetenz | Vorhanden, selten genutzt |
| HTTP/2 | Über mod_http2, Protocols h2 http/1.1 | http2 on; | Seit 1.4.56, je nach Build |
| HTTP/3 | Zum Redaktionszeitpunkt nicht in den Standardpaketen | Seit 1.25 im Lieferumfang (Build-Option) | Nicht Teil der Standardpakete |
| Speicher pro Verbindung | Am höchsten bei prefork, mit event deutlich niedriger | Niedrig | Am niedrigsten |
| Nebenläufigkeit | Sehr gut mit event | Sehr gut | Sehr gut, bei weniger maximaler Ausstattung |
| Fehlersuche | Sehr viele Beispiele, aber Config-Vererbung kann verwirren | Klare Logs, dafür eigene Logik zu lernen | Übersichtlich, weniger Referenzen im Netz |
| Verbreitung im Selfhosting | Viel im Umfeld von Anwendungen, die es erwarten | Höchste Verbreitung vor Containern und Diensten | Nische |
| Typischer Einsatz | Anwendungen mit .htaccess, WebDAV, Sonderfunktionen, geteilter Webspace | Statische Seiten, Reverse Proxy, TLS, Container-Dienste | Kleine VPS, Einplatinenrechner, schlanke statische Setups |
| Lernkurve | Flach, aber viele Details | Mittel – die Konzepte sind anders als bei Apache | Flach |
ps_mem, systemctl show -p MemoryCurrent und einem echten Lastprofil deiner
Anwendung. Alles andere ist Theorie.
Speicherbedarf und Nebenwirkungen
Der größte praktische Unterschied zwischen den dreien ist nicht der Durchsatz, sondern die Frage: Wie viel RAM kostet eine offene Verbindung? Grobe Größenordnungen:
| Situation | Größenordnung | Was daraus folgt |
|---|---|---|
Apache mit prefork | Ein eigener Prozess pro Verbindung, zweistellige Megabyte je Prozess | Auf kleinen VPS der häufigste Grund für Speicherdruck |
Apache mit event | Deutlich weniger pro Verbindung, weil Threads wiederverwendet werden | Moderner Standard – vor dem Optimieren prüfen, welches MPM läuft |
| nginx und lighttpd | Wenige Prozesse, einstelliger bis niedriger zweistelliger Bereich als Grundlast | Reserven für Anwendungen statt für den Webserver |
| PHP-FPM | Jeder Arbeiterprozess mit eigenem Speicherbedarf | Pools begrenzen – hier entsteht meist der eigentliche Verbrauch, nicht im Webserver |
# Speicherverbrauch der Webserver-Prozesse vergleichen (Debian/Arch)
ps_mem -p "$(pgrep -d, -x 'nginx|httpd|lighttpd')" 2>/dev/null || ps -o rss,cmd -C nginx,httpd,lighttpd
# Systemd-Dienste direkt fragen
systemctl show -p MemoryCurrent nginx
systemctl show -p MemoryCurrent apache2 2>/dev/null || systemctl show -p MemoryCurrent httpd
# Offene Verbindungen zaehlen
ss -tn state established '( sport = :443 )' | wc -l
Dieselbe Aufgabe in allen drei
Eine statische Seite mit index.html, ohne Verzeichnislisting, mit Upload-Limit, einem
Sicherheits-Header und Protokolldateien. Nichts davon ist exotisch – und man sieht gut, wie unterschiedlich
die drei Denkweisen sind.
Apache (Konfiguration pro Vhost):
<VirtualHost *:80>
ServerName static.meine.domain
DocumentRoot /srv/www/static
<Directory /srv/www/static>
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
DirectoryIndex index.html
LimitRequestBody 0
Header always set X-Content-Type-Options "nosniff"
ErrorLog /var/log/static-error.log
CustomLog /var/log/static-access.log combined
</VirtualHost>
nginx (Serverblock):
server {
listen 80;
server_name static.meine.domain;
root /srv/www/static;
index index.html;
autoindex off;
client_max_body_size 0;
add_header X-Content-Type-Options "nosniff" always;
location / { try_files $uri $uri/ =404; }
access_log /var/log/static-access.log;
error_log /var/log/static-error.log;
}
lighttpd (eine Konfigurationsdatei):
server.document-root = "/srv/www/static"
server.port = 80
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
index-file.names = ( "index.html" )
# Kein Verzeichnislisting und ein Header
server.dir-listing = "disable"
setenv.add-response-header = ( "X-Content-Type-Options" => "nosniff" )
# Umleitung, wenn die Datei nicht existiert
url.rewrite-if-not-file = ( "^/(.*)$" => "/index.html" )
PHP: mod_php gegen php-fpm
Die PHP-Anbindung ist der Punkt, an dem sich viele Setups historisch entschieden haben – und an dem
Apache heute am häufigsten zu Unrecht mit mod_php betrieben wird.
| Variante | Wie es funktioniert | Bewertung |
|---|---|---|
mod_php (nur Apache) | PHP läuft als Modul im Webserverprozess selbst | Einfach, aber: PHP hat die Rechte des Webservers, eigener Speicher in jedem Prozess, Neustart von PHP heißt Neustart von Apache |
php-fpm | PHP läuft als eigener Dienst, der Webserver reicht Anfragen per FastCGI weiter | Standard heute: getrennte Pools pro Anwendung, eigene Nutzer und Rechte, Neustart unabhängig vom Webserver |
# Apache an php-fpm (Debian-Pfad, Socket statt TCP)
<FilesMatch "\.php$>">
SetHandler "proxy:unix:/run/php/php-fpm.sock|fcgi://localhost"
</FilesMatch>
# nginx an php-fpm
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# lighttpd an php-fpm
fastcgi.server = ( ".php" => (( "socket" => "/run/php/php-fpm.sock" )) )
mod_php, das alles im
selben Prozess mit den Rechten des Webservers ausführt.
TLS, HTTP/2 und HTTP/3
Alle drei terminieren TLS direkt. Die Unterschiede liegen in Bequemlichkeit und darin, welche Protokollversionen überhaupt verfügbar sind.
| Thema | Apache 2.4 | nginx | lighttpd |
|---|---|---|---|
| TLS-Konfiguration | mod_ssl, pro Vhost, sehr viele Optionen | ssl_certificate und ein paar Direktiven | ssl.engine, kompakt |
| Zertifikat von acme.sh | --reloadcmd "systemctl reload apache2" | --reloadcmd "systemctl reload nginx" | --reloadcmd "systemctl reload lighttpd" |
| Sicherheits-Header | Header always set | add_header … always | setenv.add-response-header |
| HTTP/2 | Protocols h2 http/1.1 mit mod_http2 | http2 on; | Build-abhängig, seit 1.4.56 |
| HTTP/3 | Nicht in den Standardpaketen | Ab 1.25, mit --with-http_v3_module | Nicht in den Standardpaketen |
Kombinationen und Reverse Proxy
Man muss sich nicht entscheiden: Ein kleiner Server vor einem großen ist ein klassisches Muster. Sinnvoll ist es aber nur mit einem Grund.
| Kombination | Sinnvoll, wenn | Nachteil |
|---|---|---|
| nginx oder lighttpd vor Apache | Statische Inhalte und TLS sollen getrennt laufen, die Anwendung braucht aber Apache-Funktionen (.htaccess, WebDAV, Module) | Zwei Konfigurationen, zwei Logquellen, eine Fehlerstelle mehr |
| nginx vor Anwendungen (php-fpm, Container) | Der Normalfall im Selfhosting – genau dafür ist nginx gebaut | Keine – solange du die Anwendung nicht zusätzlich von außen erreichbar machst |
| Apache vor Anwendungen | Anwendungen, die Apache-Dokumentation mitliefern oder .htaccess erwarten | Mehr Speicher, mehr Konfigurationspfade |
| lighttpd vor Apache | Sehr wenig RAM und überwiegend statische Inhalte | Zwei Systeme zu pflegen, kleineres Ökosystem |
Umsteigen: die Stolpersteine
Ein Wechsel ist selten das Problem der Software, sondern der übersehenen Kleinigkeiten:
| Apache | nginx | lighttpd |
|---|---|---|
DocumentRoot | root | server.document-root |
DirectoryIndex | index | index-file.names |
Alias /pfad /ziel | location /pfad { alias /ziel; } | alias.url = ( "/pfad" => "/ziel" ) |
RewriteRule aus .htaccess | rewrite mit ^-Anker und try_files als Fallback | url.rewrite-once / url.rewrite-if-not-file |
Require valid-user | auth_basic plus auth_basic_user_file | auth.backend und auth.require |
Header set | add_header (Achtung: nur mit always auch bei Fehlern) | setenv.add-response-header |
LimitRequestBody | client_max_body_size | server.max-request-size |
| Zugriffs- und Fehlerlogs | Getrennte access_log/error_log pro Serverblock | Zentrale Logziele in der Konfiguration |
| HTTPS-Umleitung | Eigener Serverblock auf Port 80 mit return 301 | $HTTP["scheme"] == "http"-Bedingung |
.htaccess sammeln und übersetzen, nicht
abschreiben. Achte besonders auf Reihenfolgen – Apache arbeitet Verzeichnisse von oben nach unten ab,
nginx arbeitet mit Prioritäten von location-Blöcken. Genau hier entstehen die Fehler, die
man später schwer findet.
Sicherheit und Wartung
| Maßnahme | Apache | nginx | lighttpd |
|---|---|---|---|
| Version verbergen | ServerTokens Prod, ServerSignature Off | server_tokens off; | server.tag festlegen |
| Verzeichnislisting aus | Options -Indexes | autoindex off; plus try_files | server.dir-listing = "disable" |
| Module sparsam | a2dismod für Ungenutztes | Build-Auswahl, keine Laufzeitmodule | Kompakt von Haus aus |
| Rechte | Webservernutzer nur lesend auf Inhalte | ebenso | ebenso |
| Header-Hygiene | HSTS, nosniff, Referrer-Policy und eine Content Security Policy an einer Stelle – bei Kombinationen im Vorschalter, damit es nur einen Ort der Wahrheit gibt. | ||
Entscheidungshilfe
| Deine Situation | Wahl | Warum |
|---|---|---|
| Blog oder statische Seite, dazu Dienste als Container | nginx | Ein Werkzeug für Dateien, TLS und Proxy – weniger bewegliche Teile |
Anwendung erwartet .htaccess oder ein Apache-Modul | Apache | Alles andere wäre eine Übersetzungsarbeit mit Fehlerpotenzial |
| Kleiner VPS mit wenigen hundert MB RAM, einfache Aufgabe | lighttpd | Wenig Speicher, wenige Zeilen Konfiguration |
| Einplatinenrechner oder NAS | lighttpd oder nginx | Beide schlank; lighttpd ist noch genügsamer |
| Viele Dienste, alle mit HTTPS und Headern | nginx als zentrale Stelle | Eine Konfiguration, ein Ort für Zertifikate und Header |
| Du willst möglichst wenig selbst pflegen | Das, was deine Anleitung vorgibt | Fertige Anleitungen passen meist zu genau einem Server – Eigenbau kostet mehr Zeit als jede Wahl |
Häufige Fragen (FAQ)
| Frage | Antwort |
|---|---|
| Welcher ist der schnellste? | Bei statischen Dateien sind alle drei schnell genug, dass der Unterschied in echten Setups verschwindet. Über deine Ladezeiten entscheiden Datenbank und Anwendung. |
| Ist Apache veraltet? | Nein. Mit mpm_event ist er konkurrenzfähig, und für Anwendungen mit Apache-Anforderungen bleibt er die richtige Wahl. |
Kann ich .htaccess mit nginx nutzen? | Nein. Die Regeln müssen in den Serverblock übersetzt werden – das ist Handarbeit, aber einmalig. |
| Brauche ich lighttpd heute noch? | Wenn dir Speicher und Einfachheit wichtiger sind als Ökosystem und HTTP/3 – ja, genau dafür ist es gut. |
| Was ist mit Caddy? | Der vierte Kandidat: automatische Zertifikate und HTTP/3 out of the box, eigene Konfigurationssprache. Er ist kein klassischer Webserver-Vergleich, sondern ein eigener Ansatz – im Proxy-Vergleich dieses Blogs steht er ausführlich. |
| Kann ich zwei parallel betreiben? | Ja, auf verschiedenen Ports oder Rechnern. Für dieselbe Adresse brauchst du aber einen Vorschalter – und damit eine Architekturentscheidung. |
| Was ist mit Windows? | Alle drei gibt es dort, sinnvoll ist Selfhosting aber auf Linux – die Konfigurationswege in diesem Artikel sind Linux-Pfade. |
| Was, wenn ich mich falsch entscheide? | Der Wechsel ist meist ein Nachmittag: Vhosts übersetzen, Header nachziehen, Logs umbiegen. Zertifikate und der Rest der Infrastruktur bleiben unverändert. |
Fazit
Apache, nginx und lighttpd sind keine Konkurrenten im Sinne von „richtig und falsch“. Sie verkörpern drei Denkweisen: Regeln pro Verzeichnis (Apache), Kontexte und Standorte (nginx), Eigenschaften eines schlanken Servers (lighttpd). Wer das weiß, wählt nach seinem Anwendungsfall – und nicht nach einem Benchmark, der eine Situation misst, die bei ihm nie eintritt.
Für dieses Blog ist die Antwort unspektakulär: nginx vorne, weil dort TLS, Header, HTTP/3 und die Dienste zusammenlaufen; Apache nur, wo eine Anwendung es verlangt; lighttpd dort, wo ein System wirklich klein sein muss.
.htaccess ist Apaches Alleinstellung: brauchst du sie, ist Apache gesetzt.
③ nginx ist ein Verteiler, nicht nur ein Dateiserver – das erklärt seine Verbreitung im Selfhosting.
④ lighttpd gewinnt über den Fußabdruck, nicht über Funktionen.
⑤ Bei jedem Kandidaten gilt: mpm_event statt prefork, php-fpm statt mod_php, Module sparsam, Header zentral.