Wer einen eigenen Server betreibt, kennt das Problem: Man möchte Nextcloud, Gitea, Grafana und vielleicht noch ein internes Dashboard gleichzeitig betreiben — aber nur eine öffentliche IP-Adresse steht zur Verfügung. Die Lösung ist ein Reverse Proxy, und Nginx ist dafür eine der robustesten Optionen überhaupt.
In diesem Guide zeige ich, wie man Nginx als Reverse Proxy einrichtet, SSL-Zertifikate terminiert und mehrere Services sauber über Subdomains erreichbar macht.
Was ist ein Reverse Proxy?
Ein Reverse Proxy sitzt vor deinen eigentlichen Anwendungen und nimmt alle eingehenden HTTP/HTTPS-Anfragen entgegen. Anhand des Hostnamens (z.B. nextcloud.example.com vs. grafana.example.com) entscheidet er, an welchen internen Service die Anfrage weitergeleitet wird. Der Client sieht immer nur den Proxy — die internen Ports und Services bleiben versteckt.
Vorteile auf einen Blick:
- Ein einziger Port 443 für alle Services
- Zentrales SSL-Management
- Einheitliche Security-Header für alle Anwendungen
- Interne Services müssen nicht öffentlich exponiert werden
Voraussetzungen
- Ein Linux-Server (Debian/Ubuntu empfohlen)
- Nginx installiert (
apt install nginx) - Certbot für Let's Encrypt (
apt install certbot python3-certbot-nginx) - DNS-Einträge, die alle Subdomains auf die Server-IP zeigen
Virtual Host Konfiguration
Für jeden Service legt man eine separate Nginx-Konfigurationsdatei unter /etc/nginx/sites-available/ an. Hier ein Beispiel für Nextcloud:
server {
listen 80;
server_name nextcloud.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name nextcloud.example.com;
ssl_certificate /etc/letsencrypt/live/nextcloud.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nextcloud.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
Die wichtigsten proxy_pass-Einstellungen:
proxy_set_header Host $host— übergibt den originalen Hostnamen an die AnwendungX-Real-IPundX-Forwarded-For— damit die Anwendung die echte Client-IP kenntX-Forwarded-Proto— damit die Anwendung weiß, dass sie hinter HTTPS läuft
Für Gitea auf Port 3000 und Grafana auf Port 3001 folgt dieselbe Struktur — nur der proxy_pass-Port ändert sich.
Konfiguration aktivieren:
ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
SSL-Terminierung mit Let's Encrypt
Certbot macht die SSL-Einrichtung trivial:
certbot --nginx -d nextcloud.example.com
Certbot modifiziert die Nginx-Konfiguration automatisch und richtet eine Cron-Job für die automatische Erneuerung ein. Für mehrere Domains führt man den Befehl einfach mehrfach aus.
Wichtig: Die SSL-Konfiguration sollte gehärtet werden. Füge folgendes in /etc/nginx/snippets/ssl-params.conf ein:
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;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
Security Headers setzen
Security Headers schützen Nutzer vor einer Reihe von Angriffen. Diese gehören in jeden server-Block oder in eine globale Snippet-Datei:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Der HSTS-Header (Strict-Transport-Security) sollte erst gesetzt werden, wenn man sicher ist, dass alle Subdomains dauerhaft HTTPS nutzen — er ist schwer rückgängig zu machen.
Nginx Proxy Manager: Die GUI-Alternative
Wer lieber eine grafische Oberfläche nutzt, kann Nginx Proxy Manager einsetzen. Er läuft als Docker-Container und bietet eine Web-UI für die komplette Konfiguration inklusive automatischem Let's Encrypt:
# docker-compose.yml
services:
app:
image: jc21/nginx-proxy-manager:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81" # Web-UI
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
Nach dem Start ist die UI unter Port 81 erreichbar. Neue Proxy Hosts legt man per Klick an — Subdomain, Ziel-IP und Port eintragen, SSL-Zertifikat ausstellen lassen, fertig.
Nginx Proxy Manager eignet sich besonders für Teams, die keine direkte Nginx-Konfiguration anfassen möchten, oder für Homelab-Umgebungen mit häufig wechselnden Services.
Häufige Fehler und Debugging
502 Bad Gateway: Der upstream-Service läuft nicht oder ist auf dem falschen Port. ss -tlnp zeigt, welche Ports tatsächlich lauschen.
Endlose Weiterleitungsschleife: Passiert, wenn die Anwendung selbst auf HTTPS besteht, aber X-Forwarded-Proto nicht korrekt gesetzt ist. Der Header sagt der Anwendung: "Du bist schon hinter HTTPS."
Große Datei-Uploads schlagen fehl: Nginx begrenzt standardmäßig die Upload-Größe. Für Nextcloud z.B.:
client_max_body_size 10G;
Logs prüfen:
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/access.log
Fazit
Ein Nginx Reverse Proxy ist die sauberste Lösung, um mehrere Webservices hinter einer IP zu betreiben. Mit Virtual Hosts, zentraler SSL-Terminierung und konsistenten Security-Headern erhält man eine professionelle, wartbare Infrastruktur — egal ob für drei oder dreißig Services.
Wer seine Serverkonfigurationen systematisch versionieren möchte, findet im Artikel Git für Systemadministratoren eine praktische Anleitung dazu.