WordPress auf nginx mit PHP-FPM konfigurieren: Server-Block, Grenzwerte und Sperren
Getestete Konfiguration für WordPress auf nginx mit PHP-FPM unter Debian 13: Installation, Server-Block mit Permalinks und Zugriffssperren, Grenzwerte im PHP-FPM-Pool, Prüfschleife mit curl und typische Fehler wie 502 und 413.
Werbung Mit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Viele Hoster und Administratoren betreiben WordPress mit Apache, weil WordPress seine Regeln für schöne Permalinks selbst in die .htaccess schreibt. Auf einem eigenen Server ist nginx mit PHP-FPM eine verbreitete Alternative: nginx liefert statische Dateien direkt aus und reicht nur PHP-Anfragen an einen separaten PHP-Prozess weiter. Der Preis dafür ist, dass nginx keine .htaccess kennt. Jede Regel für Permalinks, Upload-Größen und Zugriffssperren müssen Sie selbst in die Server-Konfiguration schreiben. Diese Anleitung zeigt eine vollständige, getestete Konfiguration für Debian 13 mit nginx 1.26 und PHP 8.4, erklärt jede Zeile und zeigt die typischen Fehler mit den zugehörigen Meldungen.
Voraussetzungen
- Server: ein Linux-Server oder VPS mit Debian 13 („trixie“). Auf Ubuntu heißen Pakete und Pfade ähnlich, die PHP-Version kann abweichen. Für eine kleine Unternehmenswebsite genügen 2 CPU-Kerne und 2 bis 4 GB RAM.
- WordPress: eine vorhandene Installation mit Datenbank, hier WordPress 7.1.2 in deutscher Sprache.
- PHP: PHP 8.4 aus den Debian-Paketquellen, hier 8.4.26. WordPress empfiehlt PHP 8.3 oder neuer.
- Zugriff: SSH mit Root- oder sudo-Rechten sowie Administrator-Zugang zu WordPress.
- Backup: eine aktuelle Sicherung von Dateien, Datenbank und bisheriger Webserver-Konfiguration, bevor Sie von Apache auf nginx wechseln.
- TLS: Die Anleitung zeigt den HTTP-Teil. Das Zertifikat richten Sie danach ein, siehe Nginx mit TLS einrichten.
Schritt 1: nginx und PHP-FPM installieren
PHP-FPM (FastCGI Process Manager) hält einen Pool von PHP-Prozessen bereit, an die nginx Anfragen weiterreicht. Installieren Sie beide Komponenten und die PHP-Erweiterungen, die WordPress für Datenbank, HTTP-Anfragen, Bildbearbeitung und Sprachdateien braucht:
sudo apt update
sudo apt install --no-install-recommends nginx php8.4-fpm php8.4-mysql \
php8.4-curl php8.4-xml php8.4-mbstring php8.4-zip php8.4-intl php8.4-gd php8.4-imagick--no-install-recommends verhindert, dass Debian zusätzlich Apache als Abhängigkeit mitbringt. Debian installiert dabei nginx 1.26.3 und PHP-FPM 8.4.26. Prüfen Sie die Versionen und den Standard-Pool:
nginx -v
php-fpm8.4 -v
grep -E '^(user|group|listen|pm)' /etc/php/8.4/fpm/pool.d/www.confDer Pool www läuft als Benutzer www-data und lauscht auf dem Unix-Socket /run/php/php8.4-fpm.sock. Diesen Pfad brauchen Sie im Server-Block. Die WordPress-Dateien müssen für www-data lesbar sein, schreibbar nur dort, wo WordPress schreiben soll. Details dazu stehen in Dateirechte in WordPress richtig setzen.
php-fpm8.4 -t meldet „configuration file /etc/php/8.4/fpm/php-fpm.conf test is successful“, und der Socket /run/php/php8.4-fpm.sock existiert nach dem Start des Dienstes.
Schritt 2: Server-Block für WordPress anlegen
Legen Sie die Datei /etc/nginx/sites-available/wordpress an. Die folgende Konfiguration läuft unverändert, ersetzen Sie nur server_name und root:
server {
listen 80;
server_name www.ihre-domain.de;
root /var/www/html;
index index.php;
client_max_body_size 80m;
# Sperren zuerst: nginx nimmt die erste passende Regex-Location
location = /wp-config.php { deny all; }
location = /xmlrpc.php { deny all; }
location ~ /\.(?!well-known) { deny all; }
location ~* /(?:uploads|files)/.*\.php$ { deny all; }
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
}
location ~* \.(?:css|js|jpe?g|png|gif|webp|avif|svg|ico|woff2?)$ {
expires 30d;
access_log off;
try_files $uri =404;
}
}Die wichtigsten Zeilen im Einzelnen:
try_files $uri $uri/ /index.php?$args;ersetzt die Permalink-Regeln der.htaccess. Existiert keine Datei und kein Verzeichnis mit diesem Namen, übernimmt WordPress die Anfrage. Die Beispielkonfiguration im Advanced Administration Handbook verwendet dieselbe Zeile.snippets/fastcgi-php.confist ein Debian-Baustein. Er prüft mittry_files $fastcgi_script_name =404;, ob die PHP-Datei existiert, und bindetfastcgi.confmit dem ParameterSCRIPT_FILENAMEein.client_max_body_sizebegrenzt die Größe einer Anfrage. Der Standard von nginx liegt laut Dokumentation bei 1 MB, zu wenig für Medien-Uploads.location ~ /\.(?!well-known)sperrt versteckte Dateien wie.htaccessoder.git, lässt aber.well-knownfür Zertifikatsprüfungen offen.xmlrpc.phpsperren Sie nur, wenn Sie keine Apps oder Dienste nutzen, die XML-RPC brauchen. Hintergründe stehen in XML-RPC in WordPress deaktivieren oder einschränken.
Die Reihenfolge ist kein Detail. nginx prüft Regex-Locations in der Reihenfolge, in der sie in der Datei stehen, und nimmt die erste passende. Stehen die Sperren hinter dem PHP-Block, wird eine Datei wp-content/uploads/test.php mit Status 200 ausgeführt, weil location ~ \.php$ zuerst passt. Erst nach dem Verschieben der Sperren nach oben antwortet nginx mit 403.
Aktivieren Sie die Konfiguration und prüfen Sie die Syntax:
$ sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/wordpress
$ sudo rm /etc/nginx/sites-enabled/default
$ sudo nginx -t && sudo systemctl reload nginxnginx -t meldet „syntax is ok“ und „test is successful“. curl -s -o /dev/null -w '%{http_code}\n' http://www.ihre-domain.de/ liefert 200.
Schritt 3: Umgebung und Grenzwerte im PHP-FPM-Pool
PHP-FPM startet seine Prozesse mit leerer Umgebung. Laut PHP-Handbuch steht clear_env standardmäßig auf „Yes“, damit keine beliebigen Umgebungsvariablen in die PHP-Prozesse gelangen. Das ist sicher, hat aber eine Folge: Liest Ihre wp-config.php Zugangsdaten per getenv(), etwa weil sie aus einem Container-Image oder einem Deployment-Werkzeug stammt, findet sie nichts. Dann zeigt WordPress die Seite „Database Error“, und nginx liefert den Status 500. Die Lösung ist entweder, die Werte direkt in die wp-config.php zu schreiben, oder sie gezielt im Pool freizugeben:
; /etc/php/8.4/fpm/pool.d/www.conf (am Ende ergänzen)
env[WORDPRESS_DB_HOST] = $WORDPRESS_DB_HOSTIn derselben Datei legen Sie die PHP-Grenzwerte für diesen Pool fest. Ohne Anpassung gelten upload_max_filesize 2M, post_max_size 8M und memory_limit 128M:
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 80M
php_admin_value[memory_limit] = 256Mphp_admin_value kann von PHP-Code nicht überschrieben werden. Für Dateien bis 64 MB lassen post_max_size und client_max_body_size mit 80 MB Reserve für die übrigen Formulardaten. Laden Sie den Dienst neu:
$ sudo php-fpm8.4 -t && sudo systemctl reload php8.4-fpmDie Anzahl der PHP-Prozesse steuert pm.max_children, im Debian-Standard 5. Jeder Prozess kann bis zum memory_limit belegen. Rechnen Sie grob: freier Arbeitsspeicher geteilt durch den typischen Speicherbedarf eines Prozesses. Messen Sie diesen Bedarf auf Ihrem Server, statt Werte aus Foren zu übernehmen.
Eine vorübergehend angelegte Datei mit <?php echo ini_get('upload_max_filesize'); gibt über den Browser den neuen Wert aus, für die gezeigte Konfiguration 64M; prüfen Sie post_max_size und memory_limit entsprechend auf 80M und 256M. Löschen Sie die Datei danach sofort.
Schritt 4: Permalinks, Sperren und Caching prüfen
Prüfen Sie die Konfiguration nicht nur mit der Startseite, sondern systematisch. Die folgende Schleife ruft typische Adressen auf und zeigt den Statuscode:
for p in / /hello-world/ /wp-login.php /wp-json/ /xmlrpc.php /wp-config.php /.htaccess /nicht-vorhanden/; do
echo "$(curl -s -o /dev/null -w '%{http_code}' https://www.ihre-domain.de$p) $p"
doneMit der Permalink-Struktur /%postname%/ lautet das Ergebnis:
| Adresse | Status | Bedeutung |
|---|---|---|
/, /hello-world/, /wp-login.php, /wp-json/ | 200 | Permalinks und REST-API funktionieren |
/xmlrpc.php, /wp-config.php, /.htaccess | 403 | Sperren greifen |
/wp-content/uploads/test.php | 403 | kein PHP im Uploads-Ordner |
/nicht-vorhanden/ | 404 | WordPress liefert seine Fehlerseite |
Für statische Dateien setzt die Konfiguration Cache-Control: max-age=2592000, also 30 Tage. Das entlastet den Server bei wiederkehrenden Besuchern. Mehr zu Caching-Headern und Komprimierung steht in Browser-Caching und Komprimierung für WordPress.
Unter Einstellungen > Permalinks können Sie die Struktur wie gewohnt ändern. Die try_files-Zeile leitet jede nicht vorhandene Adresse an WordPress weiter und deckt damit alle Strukturen ab.
Alle Adressen liefern die Statuscodes aus der Tabelle, und /?p=1 leitet mit 301 auf die schöne Adresse des Beitrags weiter.
Schritt 5: Protokolle lesen und dauerhaft betreiben
nginx schreibt Fehler nach /var/log/nginx/error.log, PHP-FPM nach /var/log/php8.4-fpm.log. Beide Dateien sind die erste Anlaufstelle bei Problemen. Gesperrte Zugriffe erscheinen dort mit „access forbidden by rule“, was zeigt, dass Ihre Sperren arbeiten.
Richten Sie außerdem ein, dass beide Dienste nach einem Neustart des Servers starten:
$ sudo systemctl enable --now nginx php8.4-fpmEin eigener Server bedeutet eigene Verantwortung. Sicherheitsupdates für nginx und PHP kommen über apt, WordPress, Plugins und Themes brauchen ihre eigenen Updates, und nach jeder Änderung an der Konfiguration sollten Sie die Prüfung aus Schritt 4 wiederholen. Wer die WordPress-seitigen Aufgaben nicht selbst im Kalender halten möchte, kann sie abgeben: Die WordPress-Wartung von wordpressupdate.de übernimmt Updates von WordPress, Plugins und Themes mit Kompatibilitätsprüfung, wöchentliche Backups auf externen Speicher und die Firewall.
systemctl is-enabled nginx php8.4-fpm meldet zweimal „enabled“, und nach einem Neustart des Servers liefert die Website wieder 200.
Typische Fehler
- 502 Bad Gateway
nginx erreicht PHP-FPM nicht. Bei falschem Socket-Pfad steht im Fehlerprotokoll:
connect() to unix:/run/php/php-fpm.sock failed (2: No such file or directory) while connecting to upstream. Pfad auslistenim Pool übernehmen und prüfen, ob PHP-FPM läuft.- 413 Request Entity Too Large beim Upload
client_max_body_sizeist zu klein. nginx protokolliert dazu „client intended to send too large body“.- Upload scheitert trotz passender nginx-Grenze
upload_max_filesizeoderpost_max_sizeim PHP-FPM-Pool ist kleiner. WordPress zeigt dann die Meldung, die Datei überschreite das Upload-Limit.- „Database Error“ und Status 500 nach dem Wechsel
Die
wp-config.phpliest Umgebungsvariablen, die PHP-FPM wegenclear_envnicht weitergibt.- Beiträge liefern 404, die Startseite funktioniert
Die Zeile
try_files … /index.php?$args;fehlt oder steht im falschenlocation-Block.- PHP-Dateien im Uploads-Ordner werden ausgeführt
Die Sperre steht hinter
location ~ \.php$. Sperren nach oben verschieben.
Häufige Fragen
Ist nginx schneller als Apache?
Das hängt von Konfiguration und Last ab. nginx liefert statische Dateien effizient aus, die Laufzeit von WordPress selbst bestimmt aber PHP. Für die meisten kleinen Websites wirken Seiten-Cache und OPcache stärker als die Wahl des Webservers.
Funktionieren Sicherheits- und Cache-Plugins, die in die .htaccess schreiben?
Deren Regeln wirken auf nginx nicht. Viele Plugins zeigen deshalb eigene nginx-Beispiele an, die Sie in den Server-Block übernehmen und mit nginx -t prüfen.
Brauche ich einen eigenen PHP-FPM-Pool pro Website?
Bei mehreren Websites auf einem Server ja. Ein eigener Pool mit eigenem Benutzer trennt die Websites, sodass eine kompromittierte Installation nicht die Dateien der anderen lesen kann.
Fazit
WordPress läuft auf nginx mit PHP-FPM stabil, wenn Sie drei Dinge beachten: try_files für Permalinks, Sperren vor dem PHP-Block und abgestimmte Grenzwerte in nginx und PHP-FPM. Mit der Prüfschleife aus Schritt 4 erkennen Sie nach jeder Änderung, ob alles noch greift. Wenn Sie die Pflege von WordPress, Plugins und Backups auf diesem Server lieber abgeben, übernimmt das die WordPress-Wartung von Marcel Schönfelder.
Weiterführende Anleitungen und Quellen
- Nginx als Reverse Proxy mit TLS manuell einrichten
- Dateirechte in WordPress richtig setzen
- Browser-Caching und Komprimierung für WordPress auf Apache und Nginx
- XML-RPC in WordPress deaktivieren oder einschränken
- Advanced Administration Handbook: Nginx
- nginx-Dokumentation: Core-Modul (location, try_files, client_max_body_size)
- PHP-Handbuch: FPM-Konfiguration


