Viele Laravel-Projekte scheitern nicht an PHP-Code, sondern an der ersten Nacht im Produktivbetrieb: ein fehlerhaftes vHost-Layout, ein vergessener Redirect, ein „kurz mal Zertifikat erneuern“-Eingriff zur Unzeit oder ein Deployment, das bestehende Requests abwürgt. Genau hier entscheidet sich, ob ein laravel deployment server wirklich wartbar ist.
In diesem Beitrag geht es um ein Real-World Server Setup für Laravel (Apache vs Caddy vs Nginx) – mit Blick auf drei Dinge, die im Alltag ständig wiederkommen:
- TLS automation (Zertifikate, Renewal, Redirects, ACME-Challenges)
- vhost patterns (saubere VirtualHosts / Server Blocks / Site-Blöcke für mehrere Apps, Staging, Preview-Instanzen)
- zero downtime deploys (Rollouts ohne sichtbare Unterbrechung, auch bei Konfig-Reloads)
Der Fokus liegt auf „so läuft das auf echten Servern“: typische Pfade, verständliche Konfigs, sinnvolle Defaults und die Stolperfallen, die man nach dem dritten Incident nicht mehr sehen will.
Vorab: das unverhandelbare Minimum für Laravel in Produktion
Unabhängig davon, ob Sie Apache, Caddy oder Nginx nutzen: Laravel erwartet in Produktion ein Setup, das ausschließlich das public/-Verzeichnis exponiert. Laravel selbst weist explizit darauf hin, dass der Webserver alle Requests nach public/index.php routen soll und dass man index.php nicht ins Projekt-Root verschieben darf, weil sonst sensitive Dateien erreichbar werden können. (laravel.com)
Ein solides laravel production server configuration-Baseline besteht in der Praxis aus:
- Dokumentenroot:
/var/www/<app>/public(oder ähnliches) - PHP über PHP-FPM (auch bei Apache meist die sauberste Variante)
- getrennte User/Groups und Rechtekonzept (Deploy-User vs. Webserver-User)
- klare Log-Struktur (Access/Error + App-Logs)
- keine „magischen“ Symlinks ohne Plan (Symlinks sind gut, aber nur mit klaren Regeln)
Die Vergleichsfrage richtig stellen: was soll der Webserver für Laravel leisten?
Wenn Teams „Apache vs Nginx vs Caddy“ diskutieren, geht es selten um Roh-Performance. Meist geht es um Betrieb:
- Wie schnell bekomme ich TLS korrekt und dauerhaft stabil?
- Wie standardisiert kann ich vHosts für viele Apps/Umgebungen ausrollen?
- Wie deploye ich neue Releases, ohne dass Nutzer 502/503 sehen?
Wenn Sie diese drei Punkte im Griff haben, sind die Unterschiede zwischen den Webservern zwar weiterhin real, aber nicht mehr existenziell.
Nginx: das klassische Laravel-Rezept (klar, präzise, wenig Magie)
Laravel liefert in seiner Deployment-Dokumentation eine Nginx-Startkonfiguration und betont dabei den Kern: alle Requests müssen nach public/index.php laufen. (laravel.com)
Nginx Server Block als Ausgangspunkt
Ein pragmatisches Muster für ein laravel server setup unter Nginx sieht so aus (Beispielpfade anpassen):
server {
listen 80;
server_name example.com;
root /var/www/myapp/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
location ~ /\. {
deny all;
}
}
Wichtig ist die try_files-Zeile. Das Muster try_files $uri $uri/ /index.php?$query_string; ist die verbreitete Form, um Laravel-Routing zuverlässig über den Front Controller zu fahren. (blog.krybot.com)
TLS automation unter Nginx: extern, dafür kontrolliert
Nginx bringt keine integrierte ACME-Automation mit. In der Praxis setzt man häufig auf Certbot oder ACME-Clients, plus Cron/Systemd-Timer. Das ist nicht „schlecht“, aber es ist ein zusätzlicher beweglicher Teil.
Wenn Sie TLS-Automation mit Nginx sauber betreiben wollen, brauchen Sie ein klares Verfahren:
- Zertifikate werden in einem definierten Pfad abgelegt.
- Renewal läuft automatisch (Timer/Cron).
- Nach erfolgreichem Renewal folgt ein Reload von Nginx.
Der Reload selbst kann ohne Abbruch aktiver Verbindungen passieren. NGINX beschreibt „graceful configuration reloads“ als Mechanismus, bei dem Requests nicht gedroppt werden. (docs.nginx.com)
Zero downtime deploys mit Nginx: Reload ist Ihr Freund
Für „zero downtime“ müssen Sie zwei Dinge auseinanderhalten:
- Deployment Ihrer App (neuer Code, neue Vendor, neue Migrations)
- Reload des Webservers (neue vHost-Konfig, neue Zertifikate)
Nginx kann Konfigurationsänderungen in der Regel ohne sichtbare Unterbrechung übernehmen, wenn Sie einen Reload durchführen (nicht Restart). Ein Reload sendet ein Signal an den Master-Prozess, der neue Worker startet und alte Worker sauber auslaufen lässt. (docs.nginx.com)
Für Deployments in der Praxis hat sich ein Release/Symlink-Schema bewährt:
/var/www/myapp/releases/<timestamp>/.../var/www/myapp/current→ Symlink auf aktives Release
Dann wird beim Rollout nur der Symlink umgebogen und PHP-FPM ggf. „warm“ gemacht (Opcache reset nur, wenn Sie wissen, warum).
Apache: nicht tot, sondern oft schon da (und für viele Teams der Standard)
Apache wird im Laravel-Umfeld manchmal unterschätzt, weil viele Best-Practice-Snippets Nginx zeigen. In realen Umgebungen ist Apache aber häufig vorhanden, gut verstanden, über Jahre gehärtet und in bestehende Monitoring-/Log-Workflows integriert.
PHP-FPM mit Apache (mod_proxy_fcgi)
Für moderne Setups ist PHP-FPM auch bei Apache ein gängiger Weg. Offiziell dokumentiert Apache mod_proxy_fcgi und zeigt unter anderem die Variante, PHP-Dateien über SetHandler an ein Unix-Socket von PHP-FPM zu reichen. (httpd.apache.org)
Ein minimales Muster (Ausschnitt) sieht so aus:
<FilesMatch "\.php$">
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost/"
</FilesMatch>
Das ist kein komplettes vHost-File, aber der entscheidende Teil für „Apache spricht mit PHP-FPM“.
laravel apache vhost: ein sauberes Grundmuster
Ein laravel apache vhost sollte vor allem zwei Dinge richtig machen:
DocumentRootzeigt auf.../public- der Front-Controller wird für nicht vorhandene Dateien/Verzeichnisse genutzt
Beispiel (vereinfachtes Muster, Module vorausgesetzt):
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/myapp/public
<Directory /var/www/myapp/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/myapp_error.log
CustomLog ${APACHE_LOG_DIR}/myapp_access.log combined
</VirtualHost>
Ob Sie AllowOverride All wirklich wollen, hängt davon ab, ob Sie Laravel/Rewrite-Regeln per .htaccess fahren oder lieber alles in der vHost-Konfig abbilden. In vielen Admin-Teams ist „alles in vHost, keine .htaccess“ das Ziel, weil es transparenter und schneller ist. Wenn Sie .htaccess verbieten, müssen die Rewrite-Regeln natürlich in die vHost-Datei.
TLS automation unter Apache
Apache hat ebenfalls keine „out of the box“-ACME-Automation. Wie bei Nginx lösen Sie es meist über Certbot/ACME-Client + Reload.
Der operative Unterschied zu Nginx liegt weniger in TLS selbst, sondern in der Frage, wie viele Abhängigkeiten bereits bestehen:
- Apache in bestehender Umgebung: oft bereits etabliertes Zertifikats-Handling, Reverse-Proxies, WAF/ModSecurity, Log-Rotation etc.
- Migration zu Caddy/Nginx: manchmal sinnvoll, aber nicht automatisch besser
Caddy: TLS automation als Default und Konfiguration, die man auch nach 6 Monaten noch liest
Caddy ist interessant, weil TLS-Automation nicht als „Extra“ gedacht ist, sondern als Standard. Caddy aktiviert Automatic HTTPS implizit, sobald es eine Domain in der Konfiguration sieht, beschafft und erneuert Zertifikate und setzt HTTP→HTTPS-Redirects. (notes.plc.one)
Wenn Sie schon einmal nachts wegen abgelaufener Zertifikate geweckt wurden, ist das nicht nur Komfort, sondern reduziert Betriebsrisiko.
caddy laravel setup: Minimal-Konfiguration
Für Laravel ist Caddy in Kombination mit PHP-FPM sehr direkt. Caddy dokumentiert die Direktive php_fastcgi inklusive Beispielen mit Unix-Socket und empfiehlt die Kombination mit root und file_server. (caddyserver.com)
Ein solides Minimalbeispiel:
example.com {
root * /var/www/myapp/public
php_fastcgi unix//run/php/php8.2-fpm.sock
file_server
}
Das ist (für viele Projekte) bereits ein produktionsnahes Setup, inklusive automatischem HTTPS, sofern Ports/DNS passen. (caddyserver.com)
TLS automation: was Caddy wirklich automatisiert
Caddy automatisiert nicht nur das initiale „Zertifikat holen“, sondern auch Renewals und Redirects als Teil von Automatic HTTPS. (notes.plc.one)
Wenn Sie in Caddy tiefer eingreifen möchten (eigene CA, E-Mail, interne Zertifikate), gibt es dafür die tls-Direktive. (caddyserver.com)
Wichtig aus Admin-Sicht: Automatic HTTPS lässt sich über globale Optionen steuern (z. B. auto_https). (caddyserver.com)
vhost patterns mit Caddy: weniger Boilerplate, klare Blöcke
Der größte Gewinn bei Caddy ist für viele Teams nicht die Performance, sondern die Reduktion von Konfig-Komplexität:
- ein Site-Block pro App
- sehr wenig Wiederholung
- TLS ist „einfach da“, wenn Sie eine Domain konfigurieren (caddyserver.com)
Typischer Aufbau bei mehreren Laravel-Apps:
app1.example.com {
root * /srv/app1/public
php_fastcgi unix//run/php/php8.2-fpm.sock
file_server
}
app2.example.com {
root * /srv/app2/public
php_fastcgi unix//run/php/php8.2-fpm.sock
file_server
}
Wenn Sie Release-Symlinks nutzen, lohnt sich ein Blick auf resolve_root_symlink in php_fastcgi, weil Caddy das Verhalten bei Symlinks bewusst steuerbar macht. (caddyserver.com)
Die Praxisfrage: welcher Webserver passt zu welchem Betrieb?
Statt „Besser/Schlechter“ ist es hilfreicher, typische Betriebsprofile zu betrachten.
Wenn Sie viele Domains und ständiges TLS-Management haben
Caddy nimmt Ihnen viel Arbeit ab, weil Automatic HTTPS Zertifikate holt/erneuert und Redirects setzt. (notes.plc.one)
Für Teams ohne etablierten ACME-Workflow kann Caddy dadurch schneller produktiv werden – und stabiler im Routinebetrieb.
Wenn Sie maximale Kontrolle über Request-Routing, Caching, Upstreams brauchen
Nginx bleibt hier ein Klassiker. Die Konfiguration ist explizit, deterministisch und in großen Umgebungen gut standardisierbar. Laravel selbst liefert Nginx-Konfig als Startpunkt in der offiziellen Doku. (laravel.com)
Wenn Apache in Ihrer Landschaft Standard ist
Wenn Apache bereits Monitoring, Logging, Security-Policies und Know-how bündelt, lohnt sich der Wechsel nicht automatisch.
Technisch bekommen Sie mit Apache + mod_proxy_fcgi ein sauberes PHP-FPM-Setup. (httpd.apache.org)
vhost patterns, die sich im Alltag bewähren (unabhängig vom Webserver)
Der Begriff „vhost patterns“ klingt theoretisch, ist aber praktisch: Es geht darum, dass alle Ihre Apps gleich „aussehen“.
Pattern 1: „public-only“ als Regel erzwingen
- Nginx:
root .../publicundtry_files ... /index.php?... - Apache:
DocumentRoot .../public - Caddy:
root * .../public
Laravel dokumentiert genau dieses Prinzip („alle Requests zu public/index.php“). (laravel.com)
Pattern 2: pro App eigene Logs (und eindeutige Namen)
Machen Sie es sich leicht:
- pro Site: eigener Access-/Error-Log
- Logrotate/Retention sauber definieren
- keine gemischten Logs für 20 vHosts
In Incidents sparen Sie damit Minuten bis Stunden.
Pattern 3: Staging und Preview-Instanzen wie Produktion behandeln
Wenn Sie staging.example.com anders konfigurieren als example.com, dann testen Sie in Staging nicht Produktion.
Besser:
- gleicher Webserver-Stack
- gleiche Header/Redirects
- gleiche TLS-Policy (bei Caddy bekommen Sie das ohnehin automatisch über Domain-Config) (notes.plc.one)
zero downtime deploys: was in der Praxis wirklich „ohne Downtime“ bedeutet
„Zero downtime“ wird oft als Marketingformel benutzt. Im Admin-Alltag geht es um zwei konkrete Versprechen:
- Aktive Verbindungen brechen nicht ab, wenn Sie den Webserver neu laden.
- Neue Requests bekommen Antworten, auch während eines Deployments.
Webserver-Reloads: Nginx kann das sauber
Nginx unterstützt graceful reloads, bei denen Requests nicht gedroppt werden. (docs.nginx.com)
Das ist relevant für:
- neue vHost-Konfigurationen
- TLS-Updates nach Renewal
- neue Upstream-Definitionen
App-Deployments: Symlink-Release-Strategie
Für Laravel ist ein Release-Verzeichnis mit current-Symlink meistens die einfachste Grundlage:
releases/2026-02-23_120000/current→ zeigt auf das aktive Release
Ablauf (typisch):
- Code + Vendor bauen (idealerweise nicht auf dem Live-Server, sondern via CI)
- Release-Verzeichnis ausrollen
artisan-Schritte ausführen (Cache, Migrations nach Verfahren)- Symlink atomar umstellen
Bei Caddy gibt es in php_fastcgi Optionen, die Symlink-Strategien berücksichtigen (z. B. resolve_root_symlink). (caddyserver.com)
Wo „Downtime“ trotzdem passiert (und wie Sie sie vermeiden)
- Datenbank-Migrationen: Nicht jede Migration ist online-safe. Planen Sie, ob Sie „expand/contract“ Migrationen brauchen.
- Cache-Warmup: Wenn Sie Caches leeren, braucht die erste Request-Welle oft länger.
- Queue/Workers: neue Releases erfordern oft Restart von Queue-Workern.
Diese Punkte sind unabhängig vom Webserver.
Konkrete Entscheidungshilfe: Apache vs Caddy vs Nginx
Wenn Sie ein neues Setup starten und möglichst wenig bewegliche Teile möchten:
- Caddy ist attraktiv, weil TLS-Automation und Redirects integriert sind und ein
caddy laravel setupsehr kompakt bleibt. (caddyserver.com)
Wenn Sie bereits eine Nginx-Landschaft haben oder sehr feingranulares Routing benötigen:
- Nginx bleibt eine sichere Wahl, und Laravel liefert Nginx-Konfiguration als Startpunkt. (laravel.com)
Wenn Ihre Organisation Apache als Standard betreibt und Sie die Betriebsprozesse nicht neu erfinden wollen:
- Apache + PHP-FPM via mod_proxy_fcgi ist technisch sauber und gut dokumentiert. (httpd.apache.org)
Checkliste: produktionsreife Basis für Ihr laravel deployment server
Zum Schluss eine kurze, operative Checkliste, die zu allen drei Servern passt:
public/ist der einzige Webroot.- Front-Controller-Routing ist aktiv (bei Nginx per
try_files; bei Caddy überphp_fastcgi; bei Apache über passende Rewrite/Front-Controller-Regeln). - TLS ist automatisiert oder Renewal-Prozess ist getestet (inkl. Reload).
- Logfiles sind pro App getrennt.
- Deployment ist reproduzierbar (Release-Verzeichnisse + Symlink oder Container-Image-Strategie).
Wenn Sie Ihren Laravel-Produktivbetrieb gerade neu aufsetzen oder eine gewachsene Umgebung standardisieren wollen, finden Sie weitere praxisnahe Beiträge im Blog von ADMIN INTELLIGENCE. Wenn Sie bei der Planung oder beim Rollout Unterstützung brauchen, melden Sie sich gerne.

Anwendungsentwickler
ADMIN INTELLIGENCE GmbH