Nginx vs Apache - Produktive Webserver-Konfiguration
Nginx Apache Produktive
devopsNginx vs Apache - Produktive Webserver-Konfiguration
Die Wahl des richtigen Webservers ist eine der wichtigsten Infrastrukturentscheidungen in jedem Webprojekt. Nginx und Apache dominieren den Markt seit Jahren, unterscheiden sich aber grundlegend in ihrer Architektur, der Verarbeitung von Anfragen und den Szenarien, in denen sie jeweils ihre Staerken ausspielen. In diesem Artikel bieten wir einen umfassenden Vergleich beider Server, praesentieren produktionsreife Konfigurationen, Performance-Optimierungen und Empfehlungen, wann welcher Server die bessere Wahl ist.
Architektur - Event-Driven vs Process-Based#
Der fundamentale Unterschied zwischen Nginx und Apache liegt in der Art und Weise, wie eingehende Verbindungen verarbeitet werden. Das Verstaendnis dieses Unterschieds ist entscheidend fuer eine korrekte Produktionskonfiguration.
Nginx - Event-Driven-Architektur#
Nginx verwendet ein asynchrones, ereignisgesteuertes Modell zur Verbindungsverarbeitung. Ein einzelner Worker-Prozess kann dank nicht-blockierender I/O und einer Event-Schleife (epoll unter Linux, kqueue unter BSD) Tausende gleichzeitiger Verbindungen verarbeiten.
# /etc/nginx/nginx.conf - Hauptkonfiguration
user www-data;
worker_processes auto; # Ein Worker pro CPU-Kern
worker_rlimit_nofile 65535; # Limit fuer offene Dateideskriptoren
pid /run/nginx.pid;
events {
worker_connections 4096; # Verbindungen pro Worker
multi_accept on; # Mehrere Verbindungen gleichzeitig akzeptieren
use epoll; # Event-Mechanismus unter Linux
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off; # Serverversion verbergen
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Protokollierung
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
In diesem Modell kann ein einzelner Worker-Prozess mit 4096 Verbindungen bei 4 CPU-Kernen theoretisch bis zu 16.384 gleichzeitige Verbindungen verarbeiten - ohne einen neuen Prozess oder Thread fuer jede Anfrage zu erstellen.
Apache - Process/Thread-basierte Architektur#
Apache verwendet traditionell das Prefork-Modell (ein separater Prozess pro Anfrage) oder Worker/Event MPM (eine Kombination aus Prozessen und Threads). In modernen Installationen wird das Event MPM empfohlen:
# /etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
StartServers 4
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 10000
ServerLimit 16
</IfModule>
Apache mit Event MPM ist deutlich effizienter als Prefork, benoetigt aber immer noch mehr Ressourcen pro Verbindung als Nginx. Jeder MaxRequestWorkers-Slot entspricht einer gleichzeitig bedienten Anfrage.
Nginx als Reverse Proxy#
Nginx wird am haeufigsten als Reverse Proxy vor Anwendungsservern eingesetzt. Hier ist eine vollstaendige Produktionskonfiguration:
# /etc/nginx/sites-available/app.conf
upstream backend_app {
least_conn; # Load Balancing - wenigste Verbindungen
server 127.0.0.1:3000 weight=3; # Primaere Instanz
server 127.0.0.1:3001 weight=2; # Sekundaere Instanz
server 127.0.0.1:3002 backup; # Backup - nur wenn Primaere ausfallen
keepalive 32; # Keep-Alive-Verbindungspool
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL - Konfiguration unten
include /etc/nginx/snippets/ssl-params.conf;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Anfrage-Body-Groesse
client_max_body_size 64M;
client_body_buffer_size 128k;
# Proxy zum Backend
location / {
proxy_pass http://backend_app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Proxy-Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Pufferung
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}
# Statische Dateien direkt ueber Nginx
location /static/ {
alias /var/www/app/static/;
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
location /_next/static/ {
alias /var/www/app/.next/static/;
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
}
Apache - Virtual Hosts und .htaccess#
Apache bietet ein leistungsstarkes Konfigurationssystem basierend auf Virtual Hosts und .htaccess-Dateien:
# /etc/apache2/sites-available/app.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/app/public
# SSL
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# Protokollierung
ErrorLog ${APACHE_LOG_DIR}/app-error.log
CustomLog ${APACHE_LOG_DIR}/app-access.log combined
# Dokumentenstamm-Verzeichnis
<Directory /var/www/app/public>
AllowOverride All
Require all granted
Options -Indexes +FollowSymLinks
</Directory>
# Proxy zu Node.js / Next.js
ProxyPreserveHost On
ProxyPass /api http://127.0.0.1:3000/api
ProxyPassReverse /api http://127.0.0.1:3000/api
# Statische Dateien
<LocationMatch "^/static/">
ExpiresActive On
ExpiresDefault "access plus 1 year"
Header set Cache-Control "public, immutable"
</LocationMatch>
# Sicherheits-Header
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</VirtualHost>
Die .htaccess-Datei fuer eine PHP/Laravel-Anwendung:
# /var/www/app/public/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Weiterleitung auf HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Trailing Slash entfernen
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Front Controller - Laravel
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
# Kompression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css
AddOutputFilterByType DEFLATE text/javascript application/javascript
AddOutputFilterByType DEFLATE application/json application/xml
AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>
# Browser-Caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType font/woff2 "access plus 1 year"
</IfModule>
SSL/TLS mit Let's Encrypt#
Die SSL-Konfiguration ist sowohl fuer die Sicherheit als auch fuer SEO entscheidend. Hier sind die optimalen Einstellungen fuer beide Server.
Nginx - SSL-Snippet#
# /etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# SSL-Sitzungen
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# HSTS - Strict Transport Security
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Diffie-Hellman-Parameter
ssl_dhparam /etc/nginx/dhparam.pem;
DH-Parameter generieren:
openssl dhparam -out /etc/nginx/dhparam.pem 4096
Automatische Zertifikatserneuerung#
# Certbot mit automatischer Erneuerung
sudo certbot --nginx -d example.com -d www.example.com
# Crontab - alle 12 Stunden erneuern
0 */12 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"
PHP-FPM - Konfiguration fuer Nginx und Apache#
PHP-FPM (FastCGI Process Manager) ist die empfohlene Methode zum Ausfuehren von PHP sowohl mit Nginx als auch mit Apache.
PHP-FPM-Pool-Konfiguration#
; /etc/php/8.3/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
; UNIX-Socket - schneller als TCP
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
; Prozessverwaltung
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 1000
; Slow-Log zum Debuggen
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s
; Limits
request_terminate_timeout = 120s
php_admin_value[memory_limit] = 256M
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M
; OPcache
php_admin_value[opcache.enable] = 1
php_admin_value[opcache.memory_consumption] = 256
php_admin_value[opcache.max_accelerated_files] = 20000
php_admin_value[opcache.validate_timestamps] = 0
Nginx mit PHP-FPM#
server {
listen 443 ssl http2;
server_name laravel-app.com;
root /var/www/laravel/public;
index index.php;
include /etc/nginx/snippets/ssl-params.conf;
ssl_certificate /etc/letsencrypt/live/laravel-app.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/laravel-app.com/privkey.pem;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
# FastCGI-Pufferung
fastcgi_buffering on;
fastcgi_buffer_size 16k;
fastcgi_buffers 16 16k;
# Timeouts
fastcgi_connect_timeout 60;
fastcgi_send_timeout 120;
fastcgi_read_timeout 120;
}
# Zugriff auf versteckte Dateien blockieren
location ~ /\.(?!well-known) {
deny all;
}
# Zugriff auf sensible Dateien blockieren
location ~* \.(env|log|git|sql|bak)$ {
deny all;
return 404;
}
}
Apache mit PHP-FPM#
<VirtualHost *:443>
ServerName laravel-app.com
DocumentRoot /var/www/laravel/public
# PHP-FPM ueber Proxy
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
<Directory /var/www/laravel/public>
AllowOverride All
Require all granted
Options -Indexes
</Directory>
# Zugriff auf versteckte Dateien blockieren
<DirectoryMatch "/\.">
Require all denied
</DirectoryMatch>
</VirtualHost>
Load Balancing#
Nginx - Erweitertes Load Balancing#
upstream php_backend {
# Algorithmus - ip_hash sorgt fuer Sticky Sessions
ip_hash;
server 10.0.0.10:9000 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.0.11:9000 weight=3 max_fails=3 fail_timeout=30s;
server 10.0.0.12:9000 weight=2 max_fails=3 fail_timeout=30s;
server 10.0.0.13:9000 backup;
keepalive 64;
}
upstream node_backend {
least_conn;
server 127.0.0.1:3000;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
keepalive 32;
}
server {
listen 443 ssl http2;
server_name app.example.com;
location /api/ {
proxy_pass http://php_backend;
proxy_next_upstream error timeout http_500 http_502 http_503;
proxy_next_upstream_tries 3;
}
location / {
proxy_pass http://node_backend;
proxy_next_upstream error timeout http_502;
}
}
Apache - mod_proxy_balancer#
<Proxy "balancer://app_cluster">
BalancerMember "http://10.0.0.10:8080" route=node1 loadfactor=5
BalancerMember "http://10.0.0.11:8080" route=node2 loadfactor=3
BalancerMember "http://10.0.0.12:8080" route=node3 loadfactor=2 status=+H
ProxySet lbmethod=byrequests stickysession=JSESSIONID
</Proxy>
<VirtualHost *:443>
ServerName app.example.com
ProxyPreserveHost On
ProxyPass / "balancer://app_cluster/"
ProxyPassReverse / "balancer://app_cluster/"
# Load-Balancer-Verwaltungspanel
<Location "/balancer-manager">
SetHandler balancer-manager
Require ip 10.0.0.0/8
</Location>
</VirtualHost>
Caching-Konfiguration#
Nginx - FastCGI Cache und Proxy Cache#
# Cache-Zonendefinition (im http-Block)
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=PHPCACHE:100m
max_size=2g
inactive=60m
use_temp_path=off;
proxy_cache_path /var/cache/nginx/proxy
levels=1:2
keys_zone=PROXYCACHE:100m
max_size=5g
inactive=24h
use_temp_path=off;
server {
# FastCGI-Cache fuer PHP
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
include fastcgi_params;
fastcgi_cache PHPCACHE;
fastcgi_cache_valid 200 301 302 60m;
fastcgi_cache_valid 404 1m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout updating http_500 http_503;
fastcgi_cache_bypass $cookie_nocache $arg_nocache;
add_header X-Cache-Status $upstream_cache_status;
}
# Proxy-Cache fuer oeffentliche API
location /api/public/ {
proxy_pass http://backend_app;
proxy_cache PROXYCACHE;
proxy_cache_valid 200 10m;
proxy_cache_key "$request_uri";
add_header X-Cache-Status $upstream_cache_status;
}
}
Apache - mod_cache#
# Cache-Module aktivieren
# a2enmod cache cache_disk headers
CacheQuickHandler off
CacheLock on
CacheLockPath /tmp/mod_cache-lock
CacheLockMaxAge 5
<VirtualHost *:443>
CacheEnable disk /
CacheRoot /var/cache/apache2/mod_cache_disk
CacheDefaultExpire 3600
CacheMaxExpire 86400
CacheIgnoreNoLastMod On
# Admin-Panel nicht cachen
CacheDisable /admin
CacheDisable /api/auth
# Cache-Header
<LocationMatch "^/static/">
Header set Cache-Control "public, max-age=31536000, immutable"
</LocationMatch>
</VirtualHost>
Gzip- und Brotli-Kompression#
Nginx#
# Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
application/xml+rss
image/svg+xml
font/woff2;
# Brotli (erfordert ngx_brotli-Modul)
brotli on;
brotli_comp_level 6;
brotli_static on; # Vorkomprimierte .br-Dateien ausliefern
brotli_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml
font/woff2;
Apache#
# mod_deflate (gzip)
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
DeflateCompressionLevel 5
AddOutputFilterByType DEFLATE text/html text/plain text/css
AddOutputFilterByType DEFLATE text/javascript application/javascript
AddOutputFilterByType DEFLATE application/json application/xml
AddOutputFilterByType DEFLATE image/svg+xml font/woff2
# Bereits komprimierte Dateien nicht komprimieren
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|gz|zip|br)$ no-gzip
</IfModule>
# Brotli (erfordert mod_brotli - Apache 2.4.26+)
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css
AddOutputFilterByType BROTLI_COMPRESS text/javascript application/javascript
AddOutputFilterByType BROTLI_COMPRESS application/json application/xml
BrotliCompressionQuality 5
</IfModule>
Sicherheits-Header#
Nginx - Vollstaendige Security-Headers-Konfiguration#
# /etc/nginx/snippets/security-headers.conf
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://api.example.com;" always;
# Header entfernen, die den Technologie-Stack verraten
proxy_hide_header X-Powered-By;
fastcgi_hide_header X-Powered-By;
Rate Limiting#
Nginx#
# Rate-Limiting-Zonendefinitionen (im http-Block)
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
# Allgemeines Rate Limit fuer API
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429;
proxy_pass http://backend_app;
}
# Strenges Rate Limit fuer Login
location /api/auth/login {
limit_req zone=login burst=3 nodelay;
limit_req_status 429;
proxy_pass http://backend_app;
}
# Gleichzeitige Verbindungsbegrenzung
location /downloads/ {
limit_conn addr 5;
limit_rate 1m; # 1MB/s pro Verbindung
alias /var/www/downloads/;
}
}
Apache - mod_ratelimit und mod_evasive#
# mod_ratelimit - Bandbreitenbegrenzung
<Location "/downloads">
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 1024 # 1024 KB/s
</Location>
# mod_evasive - DDoS-Schutz
<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 5 # Max. 5 Anfragen pro Seite/s
DOSSiteCount 50 # Max. 50 Anfragen pro Website/s
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 60 # 60s sperren
DOSEmailNotify admin@example.com
</IfModule>
WebSocket-Proxying#
Nginx#
# Map fuer WebSocket-Upgrade-Verarbeitung
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# WebSocket-Timeout (laenger als Standard)
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Apache#
# Erforderliche Module: mod_proxy_wstunnel
# a2enmod proxy_wstunnel
<VirtualHost *:443>
# WebSocket-Proxy
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /ws/(.*) ws://127.0.0.1:3000/ws/$1 [P,L]
ProxyPass /ws/ ws://127.0.0.1:3000/ws/
ProxyPassReverse /ws/ ws://127.0.0.1:3000/ws/
# WebSocket-Timeout
ProxyTimeout 3600
</VirtualHost>
Performance-Vergleich#
Im Folgenden praesentieren wir typische Benchmark-Ergebnisse fuer beide Server in verschiedenen Szenarien:
| Metrik | Nginx | Apache (Event MPM) | |--------|-------|---------------------| | Statische Dateien (Req/s) | ~25.000 | ~10.000 | | Reverse Proxy (Req/s) | ~18.000 | ~8.000 | | PHP-FPM (Req/s) | ~3.500 | ~3.200 | | RAM-Verbrauch (1.000 Verb.) | ~50 MB | ~200 MB | | RAM-Verbrauch (10.000 Verb.) | ~80 MB | ~1,5 GB | | Antwortzeit p99 | ~2 ms | ~8 ms | | Max. gleichzeitige Verbindungen | ~100.000+ | ~10.000 |
Nginx dominiert in Szenarien mit vielen gleichzeitigen Verbindungen und beim Ausliefern statischer Dateien. Bei dynamischen PHP-FPM-Anfragen verringert sich der Abstand, da PHP selbst zum Flaschenhals wird.
Nginx fuer Next.js / Node.js#
# Produktive Nginx-Konfiguration fuer Next.js
upstream nextjs {
server 127.0.0.1:3000;
keepalive 64;
}
server {
listen 443 ssl http2;
server_name app.example.com;
include /etc/nginx/snippets/ssl-params.conf;
include /etc/nginx/snippets/security-headers.conf;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
# Next.js statische Assets - aggressives Caching
location /_next/static/ {
proxy_pass http://nextjs;
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Next.js Bildoptimierung
location /_next/image {
proxy_pass http://nextjs;
proxy_cache PROXYCACHE;
proxy_cache_valid 200 24h;
proxy_cache_key "$request_uri";
}
# Oeffentliche Assets
location /public/ {
alias /var/www/app/public/;
expires 30d;
add_header Cache-Control "public";
access_log off;
}
# Alles andere an Next.js weiterleiten
location / {
proxy_pass http://nextjs;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Apache fuer PHP / Laravel#
# Produktive Apache-Konfiguration fuer Laravel
<VirtualHost *:443>
ServerName laravel.example.com
DocumentRoot /var/www/laravel/public
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/laravel.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/laravel.example.com/privkey.pem
# PHP-FPM
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
# Dokumentenstamm
<Directory /var/www/laravel/public>
AllowOverride All
Require all granted
Options -Indexes +FollowSymLinks -MultiViews
</Directory>
# Zugriff auf sensible Verzeichnisse blockieren
<DirectoryMatch "^/var/www/laravel/(storage|vendor|bootstrap/cache)">
Require all denied
</DirectoryMatch>
# .env-Dateien blockieren
<FilesMatch "^\.env">
Require all denied
</FilesMatch>
# Sicherheits-Header
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
# Kompression
SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json
# Protokollierung
ErrorLog ${APACHE_LOG_DIR}/laravel-error.log
CustomLog ${APACHE_LOG_DIR}/laravel-access.log combined
</VirtualHost>
Wann Nginx und wann Apache waehlen?#
Waehlen Sie Nginx wenn:#
- Sie eine Node.js- / Next.js-Anwendung entwickeln - Nginx ist der natuerliche Reverse Proxy fuer Node-Anwendungen
- Viele gleichzeitige Verbindungen benoetigt werden - WebSocket, SSE, Long Polling
- Viele statische Dateien ausgeliefert werden - Nginx ist deutlich effizienter
- Load Balancing - integrierte Load-Balancing-Algorithmen sind flexibel und performant
- Microservices - als API-Gateway mit Routing zu mehreren Backends
- Begrenzte Ressourcen - geringerer RAM- und CPU-Verbrauch
- Containerisierung (Docker/K8s) - kleinerer Footprint, schnellerer Start
Waehlen Sie Apache wenn:#
- Shared Hosting -
.htaccessermoeglicht verzeichnisbasierte Konfiguration ohne Server-Neustart - PHP/Laravel-Anwendungen - native Integration mit mod_php (obwohl PHP-FPM empfohlen wird)
- Dynamische Konfiguration erforderlich -
.htaccessermoeglicht Aenderungen ohne Neustart - Komplexe Rewrite-Regeln - mod_rewrite ist umfangreicher
- Mehrere Websites auf einem Server - Konfigurationsisolierung durch
.htaccess - Bestehende Infrastruktur - die Migration von Apache zu Nginx ist nicht immer kosteneffizient
Hybridloesung#
In vielen Produktionsumgebungen ist die Kombination beider Server die beste Loesung:
Client -> Nginx (Reverse Proxy, SSL, Cache, statische Dateien)
|-- Node.js / Next.js (Port 3000)
|-- Apache + PHP-FPM (Port 8080)
|-- Andere Microservices
Nginx dient als Frontend-Proxy und uebernimmt SSL-Terminierung, Kompression, Caching und statische Dateien, waehrend Apache PHP-Anwendungen mit der vollen Leistungsfaehigkeit von .htaccess und mod_rewrite verarbeitet.
Fazit#
Sowohl Nginx als auch Apache sind ausgereifte, zuverlaessige Webserver. Nginx dominiert in Szenarien, die hohe Leistung, eine grosse Anzahl gleichzeitiger Verbindungen und Reverse-Proxy-Workloads erfordern. Apache bietet groessere Konfigurationsflexibilitaet und bleibt die traditionelle Wahl fuer PHP-Anwendungen. In modernen Architekturen ist der Einsatz von Nginx als Frontend-Proxy mit Apache als PHP-Backend ein bewaehrter Ansatz, der die Staerken beider Server vereint.
Benoetigst du eine professionelle Webserver-Konfiguration? Das Team von MDS Software Solutions Group ist auf die Optimierung von Web-Infrastruktur spezialisiert. Von der Nginx- und Apache-Konfiguration ueber CI/CD-Deployments bis hin zur Skalierung von Cloud-Anwendungen - wir helfen dir, eine leistungsfaehige und sichere Infrastruktur aufzubauen. Kontaktiere uns, um dein Projekt zu besprechen.
Team von Programmierexperten, die sich auf moderne Webtechnologien spezialisiert haben.