Nginx Webserver unter Linux einrichten – Installation, Konfiguration und SSL
Nginx (gesprochen „Engine-X") ist einer der meistgenutzten Webserver weltweit. Er glänzt als statischer Dateiserver, Reverse Proxy vor Node.js/Python-Apps und als Load Balancer. Mit seinem ereignisgesteuerten Architekturmodell verarbeitet er tausende gleichzeitige Verbindungen mit minimalem Ressourcenverbrauch.
Installation
Ubuntu / Debian – offizielles Nginx-Repository
# Für die aktuellste stabile Version: offizielles Nginx-Repo nutzen
sudo apt update
sudo apt install -y curl gnupg2 ca-certificates lsb-release
# GPG-Schlüssel hinzufügen
curl https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor \
-o /usr/share/keyrings/nginx-archive-keyring.gpg
# Repository hinzufügen
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# Installieren
sudo apt update
sudo apt install -y nginx
Oder simpler (etwas ältere Version, aber für die meisten Fälle ausreichend):
sudo apt update && sudo apt install -y nginx
Fedora
sudo dnf install -y nginx
Dienst starten
sudo systemctl enable --now nginx
sudo systemctl status nginx
# Test im Browser oder per curl
curl -I http://localhost
# HTTP/1.1 200 OK
# Server: nginx/1.28.2
Version prüfen
nginx -v
# nginx version: nginx/1.28.2
Verzeichnisstruktur und Konfigurationslogik
/etc/nginx/
├── nginx.conf ← Haupt-Konfigurationsdatei
├── conf.d/ ← Zusätzliche Konfigurationen (werden inkludiert)
│ └── default.conf ← Standard-Server-Block
├── sites-available/ ← Ubuntu-Muster: alle definierten Sites
│ └── example.com ← (nicht auf Debian/Nginx-Standard)
├── sites-enabled/ ← Aktivierte Sites (Symlinks)
├── mime.types ← MIME-Typ-Definitionen
└── fastcgi_params ← PHP/FastCGI Parameter
/var/log/nginx/
├── access.log ← Zugriffsprotokoll
└── error.log ← Fehlerprotokoll
/var/www/html/ ← Standard-Webroot
Ubuntu nutzt
sites-available/sites-enabledper Konvention. Reines Nginx (offizielles Paket) nutzt/etc/nginx/conf.d/. Beide Ansätze funktionieren.
Nginx-Grundkonfiguration verstehen
Die Haupt-Konfigurationsdatei /etc/nginx/nginx.conf:
# Globaler Block
worker_processes auto; # Anzahl Worker-Prozesse (auto = CPU-Kerne)
pid /run/nginx.pid;
events {
worker_connections 1024; # Verbindungen pro Worker
use epoll; # Linux: epoll für beste Performance
}
http {
# MIME-Typen
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Performance
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
# Gzip-Komprimierung
gzip on;
# Server-Blöcke einbinden
include /etc/nginx/conf.d/*.conf;
}
Nginx-Konfiguration neu laden (ohne Neustart, bestehende Verbindungen bleiben):
# Konfiguration auf Fehler prüfen
sudo nginx -t
# nginx: configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
# Neu laden
sudo systemctl reload nginx
Wichtig: Immer
nginx -tvorsystemctl reloadausführen!
Virtual Hosts: mehrere Domains auf einem Server
Mit Server-Blöcken (Virtual Hosts) kann ein Nginx mehrere Domains bedienen.
Neue Site konfigurieren
sudo nano /etc/nginx/conf.d/beispiel.de.conf
server {
listen 80;
listen [::]:80; # IPv6
server_name beispiel.de www.beispiel.de;
root /var/www/beispiel.de;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
# Webroot erstellen
sudo mkdir -p /var/www/beispiel.de
echo "<h1>Hallo von beispiel.de!</h1>" | sudo tee /var/www/beispiel.de/index.html
# Berechtigungen setzen
sudo chown -R www-data:www-data /var/www/beispiel.de
sudo chmod -R 755 /var/www/beispiel.de
# Testen und neu laden
sudo nginx -t && sudo systemctl reload nginx
Ubuntu: sites-available/sites-enabled Pattern
sudo nano /etc/nginx/sites-available/beispiel.de
# Aktivieren
sudo ln -s /etc/nginx/sites-available/beispiel.de /etc/nginx/sites-enabled/
# Deaktivieren
sudo rm /etc/nginx/sites-enabled/beispiel.de
Statische Dateien ausliefern
Für statische Websites, SPAs (React, Vue, Svelte Build) oder Downloads:
server {
listen 80;
server_name app.beispiel.de;
root /var/www/app;
index index.html;
# SPA-Routing: alle Anfragen auf index.html umleiten
location / {
try_files $uri $uri/ /index.html;
}
# Statische Assets: lange Cache-Dauer
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Sicherheits-Header
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
}
Reverse Proxy: Apps hinter Nginx
Der häufigste Nginx-Einsatz: Eine Node.js/Python/PHP-App läuft intern, Nginx leitet Anfragen weiter und übernimmt SSL.
Node.js App auf Port 3000
server {
listen 80;
server_name api.beispiel.de;
location / {
proxy_pass http://127.0.0.1:3000;
# Wichtige Proxy-Header
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade'; # WebSockets
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_cache_bypass $http_upgrade;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
Python / Gunicorn (Unix Socket)
server {
listen 80;
server_name app.beispiel.de;
location / {
proxy_pass http://unix:/run/gunicorn.sock;
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;
}
}
Docker Container (Port 8080)
upstream backend {
server 127.0.0.1:8080;
# Für Load Balancing mehrere Server:
# server 127.0.0.1:8081;
# server 127.0.0.1:8082;
}
server {
listen 80;
server_name api.beispiel.de;
location / {
proxy_pass http://backend;
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;
}
}
SSL mit Let's Encrypt (Certbot)
Let's Encrypt stellt kostenlose, automatisch erneuerbare SSL-Zertifikate aus.
Certbot installieren
# Ubuntu / Debian
sudo apt install -y certbot python3-certbot-nginx
# Fedora
sudo dnf install -y certbot python3-certbot-nginx
Zertifikat ausstellen
# Zertifikat für Domain ausstellen UND Nginx automatisch konfigurieren
sudo certbot --nginx -d beispiel.de -d www.beispiel.de
# Nur Zertifikat (ohne automatische Nginx-Konfiguration)
sudo certbot certonly --nginx -d beispiel.de
Certbot fragt nach E-Mail-Adresse und Nutzungsbedingungen. Danach wird Nginx automatisch auf HTTPS umgestellt.
Resultierende HTTPS-Konfiguration
server {
listen 80;
server_name beispiel.de www.beispiel.de;
return 301 https://$host$request_uri; # HTTP → HTTPS Redirect
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name beispiel.de www.beispiel.de;
ssl_certificate /etc/letsencrypt/live/beispiel.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/beispiel.de/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/beispiel.de;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Automatische Erneuerung
Certbot richtet einen systemd Timer ein (Zertifikate laufen nach 90 Tagen ab):
# Timer-Status prüfen
sudo systemctl status certbot.timer
# Manuelle Erneuerung testen
sudo certbot renew --dry-run
# Alle Zertifikate anzeigen
sudo certbot certificates
Nginx-Performance-Einstellungen
In /etc/nginx/nginx.conf oder deiner Site-Konfiguration:
http {
# Sendfile: Kernel-Level Dateiübertragung (sehr effizient)
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# Keep-Alive
keepalive_timeout 65;
keepalive_requests 100;
# Buffer-Größen
client_body_buffer_size 16k;
client_max_body_size 20m; # Max. Upload-Größe
client_header_buffer_size 1k;
# Gzip-Komprimierung
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types
text/plain text/css text/xml text/javascript
application/json application/javascript application/xml
application/rss+xml image/svg+xml;
# Server-Name in Response verstecken
server_tokens off;
}
Logs verstehen und analysieren
# Access-Log live verfolgen
sudo tail -f /var/log/nginx/access.log
# Fehler-Log (die wichtigsten Infos)
sudo tail -f /var/log/nginx/error.log
# Nur Fehler und Warnungen
sudo grep -E "error|warn|crit" /var/log/nginx/error.log | tail -50
# Top-IPs nach Anfragen
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# HTTP-Status-Code-Übersicht
sudo awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
Log-Format anpassen
http {
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time';
access_log /var/log/nginx/access.log main;
}
Häufige Fehler
502 Bad Gateway
Der Upstream-Server (z.B. Node.js) ist nicht erreichbar.
# Läuft die App?
sudo systemctl status myapp
# Korrekter Port?
sudo ss -ltnp | grep :3000
# Nginx-Fehlerlog prüfen
sudo tail -50 /var/log/nginx/error.log
403 Forbidden
# Berechtigungen prüfen
ls -la /var/www/beispiel.de
# Nginx läuft als www-data
sudo chown -R www-data:www-data /var/www/beispiel.de
sudo chmod -R 755 /var/www/beispiel.de
# SELinux (Fedora): Kontext setzen
sudo restorecon -Rv /var/www/beispiel.de
413 Request Entity Too Large
# In nginx.conf oder Server-Block:
client_max_body_size 50m;
nginx -t meldet Fehler
sudo nginx -t
# nginx: [emerg] unknown directive "servr_name" in /etc/nginx/conf.d/beispiel.conf:3
# Tippfehler in Konfiguration → beheben → erneut testen
Zertifikat-Erneuerung schlägt fehl
# Port 80 muss von außen erreichbar sein (HTTP-01 Challenge)
sudo ufw allow 80/tcp
# Certbot-Logs prüfen
sudo journalctl -u certbot
Rollback
Nginx deinstallieren
sudo systemctl stop nginx
sudo apt purge -y nginx nginx-common
sudo apt autoremove -y
sudo rm -rf /etc/nginx /var/log/nginx
Konfiguration auf Backup zurücksetzen
# Vor Änderungen: Backup anlegen!
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
sudo cp -r /etc/nginx/conf.d /etc/nginx/conf.d.bak
# Backup wiederherstellen
sudo cp /etc/nginx/nginx.conf.bak /etc/nginx/nginx.conf
sudo nginx -t && sudo systemctl reload nginx
Fazit
Nginx ist robust, schnell und universell einsetzbar. Die drei häufigsten Einsatzszenarien:
- Statische Dateien: Minimale Konfiguration, maximale Performance
- Reverse Proxy: Node.js/Python/Docker-Apps sicher nach außen exponieren
- SSL-Terminierung: HTTPS mit Let's Encrypt, automatische Erneuerung
Nginx 1.28.2 stable | Tested on: Ubuntu 24.04 LTS, Debian 13 Trixie | Last updated: 2026-02-18