Nginx Webserver unter Linux einrichten – Installation, Konfiguration und SSL

Nginx 1.28 installieren, Virtual Hosts konfigurieren, Reverse Proxy einrichten und SSL mit Let's Encrypt aktivieren – der komplette Praxisguide für Linux-Server.

8 min Lesezeit

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-enabled per 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 -t vor systemctl reload ausfü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:

  1. Statische Dateien: Minimale Konfiguration, maximale Performance
  2. Reverse Proxy: Node.js/Python/Docker-Apps sicher nach außen exponieren
  3. 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

War dieser Artikel hilfreich?