Warum ein Reverse Proxy?
Du hast dein Homelab aufgesetzt, Docker läuft, und ein halbes Dutzend Self-Hosted Dienste sind am Start. Jetzt tippst du im Browser:
- Proxmox:
https://192.168.1.100:8006 - Portainer:
https://192.168.1.110:9443 - Nextcloud:
http://192.168.1.110:8080 - Jellyfin:
http://192.168.1.110:8096 - Zabbix:
http://192.168.1.110:8080— Moment, das war doch schon Nextcloud?
Genau. Du merkst dir IP-Adressen und Ports. Du hast keine SSL-Zertifikate, weil Let’s Encrypt nicht mit IP-Adressen funktioniert. Und von unterwegs erreichst du nichts, weil du nicht für jeden Service einen Port im Router freigeben willst (und solltest).
Ein Reverse Proxy löst alle drei Probleme auf einmal.
Was ein Reverse Proxy tut
Internet/Browser
│
▼
┌──────────────────────────┐
│ Reverse Proxy (:443) │
│ ───────────────────── │
│ nextcloud.domain.de ──────→ 192.168.1.110:8080
│ jellyfin.domain.de ──────→ 192.168.1.110:8096
│ zabbix.domain.de ──────→ 192.168.1.110:8081
│ proxmox.domain.de ──────→ 192.168.1.100:8006
│ ───────────────────── │
│ ✅ SSL für alle │
│ ✅ Ein Port (443) │
│ ✅ Saubere URLs │
└──────────────────────────┘
Der Proxy nimmt alle HTTPS-Anfragen auf Port 443 entgegen. Anhand des Hostnamens (aus dem HTTP-Header) entscheidet er, an welchen internen Service weitergeleitet wird. Der Browser sieht eine saubere URL mit gültigem SSL-Zertifikat. Deine internen Services müssen nicht wissen, dass sie hinter einem Proxy stehen.
Vorteile auf einen Blick
| Problem | Ohne Reverse Proxy | Mit Reverse Proxy |
|---|---|---|
| URL | http://192.168.1.110:8096 | https://jellyfin.mein-homelab.de |
| SSL | Selbstsigniert (Browser-Warnung) | Let’s Encrypt (grünes Schloss) |
| Externer Zugriff | Port-Forwarding pro Service | Ein Port (443) für alles |
| Sicherheit | Jeder Service direkt exponiert | Ein Eintrittspunkt, zentrale Firewall |
| Merken | 15 verschiedene IPs und Ports | Saubere Subdomains |
Domain und DNS: Die Grundlage
Bevor wir den Proxy einrichten, brauchst du eine Domain. Ohne Domain kein SSL-Zertifikat von Let’s Encrypt, ohne SSL keine sichere Verbindung.
Domain kaufen
Eine .de-Domain kostet 5-10€ pro Jahr. Registrare wie Netcup, Hetzner, INWX oder Cloudflare Registrar (oft am günstigsten) bieten das an. Ich empfehle einen Registrar, der auch DNS-Hosting macht — das vereinfacht einiges.
Für diesen Guide nehmen wir mein-homelab.de als Beispiel.
DNS konfigurieren
Du brauchst zwei Dinge:
Für internen Zugriff (Split DNS):
Wenn du nur innerhalb deines Heimnetzwerks auf die Services zugreifen willst (kein Zugriff von unterwegs), reicht eine lokale DNS-Konfiguration:
- In deinem Pi-hole oder lokalen DNS-Server: Wildcard-Eintrag
*.mein-homelab.de → 192.168.1.110(die IP deines Reverse Proxy) - Oder: Einzelne A-Records für jeden Service
# Pi-hole Custom DNS (unter /etc/dnsmasq.d/04-homelab.conf)
address=/mein-homelab.de/192.168.1.110
Das leitet alle Subdomains von mein-homelab.de auf deinen Proxy. Intern. Ohne dass irgendwas ins Internet exponiert wird.
Für externen Zugriff (Zugriff von unterwegs):
Bei deinem Domain-Registrar:
| Typ | Name | Ziel | TTL |
|---|---|---|---|
| A | mein-homelab.de | Deine öffentliche IP | 300 |
| CNAME | *.mein-homelab.de | mein-homelab.de | 300 |
Deine öffentliche IP findest du unter ifconfig.me. Bei dynamischer IP (die meisten DSL-Anschlüsse) brauchst du einen DynDNS-Dienst — dazu gleich mehr.
DynDNS für dynamische IPs
Die meisten Heim-Internetanschlüsse haben eine dynamische IP, die sich alle 24h ändert. Lösungen:
- Fritz!Box eingebautes DynDNS: Unter Internet → Freigaben → DynDNS. Unterstützt Anbieter wie myfritz, No-IP, DynDNS.
- ddclient: Linux-Tool, das deine IP bei diversen DNS-Anbietern aktualisiert. Läuft als Docker-Container.
- Cloudflare API: Wenn dein DNS bei Cloudflare liegt, gibt’s dutzende kleine Tools die deine IP automatisch updaten. Mein Favorit:
cloudflare-ddnsals Container.
# DynDNS mit Cloudflare (Docker)
services:
cloudflare-ddns:
image: oznu/cloudflare-ddns:latest
container_name: cloudflare-ddns
restart: unless-stopped
environment:
- API_KEY=dein-cloudflare-api-token
- ZONE=mein-homelab.de
- SUBDOMAIN=*
- PROXIED=false
DNS-Challenge für Wildcard-Zertifikate
Kleiner Vorgriff: Für Wildcard-SSL-Zertifikate (*.mein-homelab.de) brauchst du die DNS-01 Challenge von Let’s Encrypt. Das heißt, dein SSL-Tool muss DNS-Einträge automatisch erstellen können. Unterstützte DNS-Provider: Cloudflare, Hetzner DNS, INWX, Route53, und viele mehr. Cloudflare ist hier am einfachsten — kostenloser DNS mit API, gut dokumentiert, weitverbreitet.
Option 1: Nginx Proxy Manager (Empfohlen für Einsteiger)
Nginx Proxy Manager (NPM) ist Nginx mit einer Web-Oberfläche. Du klickst statt zu konfigurieren. SSL-Zertifikate per Knopfdruck. Für 90% aller Homelab-Setups mehr als ausreichend.
Installation
mkdir -p /opt/docker/nginx-proxy-manager
cat > /opt/docker/nginx-proxy-manager/docker-compose.yml << 'EOF'
services:
npm:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
- "81:81" # Admin-GUI
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
environment:
- TZ=Europe/Berlin
EOF
cd /opt/docker/nginx-proxy-manager
docker compose up -d
Erster Login unter http://DEINE-IP:81:
- Email:
admin@example.com - Passwort:
changeme
Sofort ändern. Ernst gemeint — Port 81 ist der Admin-Zugang zu deinem gesamten Reverse Proxy.
SSL-Zertifikat einrichten
Bevor du Proxy-Hosts konfigurierst: SSL-Zertifikat holen.
- SSL Certificates → Add SSL Certificate → Let’s Encrypt
- Domain Names:
*.mein-homelab.deundmein-homelab.de - Email: Deine Email
- Use a DNS Challenge: ✅ (Pflicht für Wildcard!)
- DNS Provider: Cloudflare (oder deinen Anbieter)
- API Token eintragen
- Save → NPM holt automatisch das Zertifikat
Das Wildcard-Zertifikat gilt für alle Subdomains. Du musst es nur einmal einrichten, und jeder neue Service bekommt automatisch SSL. Kein weiteres Zertifikat-Klicken mehr.
Ersten Proxy Host einrichten
Beispiel: Nextcloud unter nextcloud.mein-homelab.de erreichbar machen.
- Hosts → Proxy Hosts → Add Proxy Host
- Details:
- Domain Names:
nextcloud.mein-homelab.de - Scheme:
http - Forward Hostname:
192.168.1.110(IP des Docker-Hosts wo Nextcloud läuft) - Forward Port:
8080 - Block Common Exploits: ✅
- Websockets Support: ✅ (brauchen manche Apps)
- Domain Names:
- SSL:
- SSL Certificate: Dein Wildcard-Zertifikat auswählen
- Force SSL: ✅
- HTTP/2 Support: ✅
- HSTS Enabled: ✅ (sagt dem Browser: nur HTTPS, nie HTTP)
Save. Fertig. https://nextcloud.mein-homelab.de funktioniert jetzt mit gültigem SSL.
Weitere Services hinzufügen
Gleicher Prozess für jeden Service:
| Subdomain | Ziel-IP | Ziel-Port | Besonderheiten |
|---|---|---|---|
jellyfin.mein-homelab.de | 192.168.1.110 | 8096 | Websockets ✅ |
portainer.mein-homelab.de | 192.168.1.110 | 9443 | Scheme: https |
zabbix.mein-homelab.de | 192.168.1.110 | 8080 | — |
proxmox.mein-homelab.de | 192.168.1.100 | 8006 | Scheme: https, Websockets ✅ |
pihole.mein-homelab.de | 192.168.1.120 | 80 | — |
Wichtig bei Portainer und Proxmox: Die laufen selbst schon auf HTTPS (selbstsigniert). Im NPM stellst du dann “Scheme” auf
https— der Proxy verbindet sich per HTTPS zum Backend, aber der Browser sieht das gültige Let’s Encrypt-Zertifikat.
Access Lists: Wer darf was?
Nicht jeder Service sollte für die ganze Welt erreichbar sein. NPM hat eingebaute Access Lists:
- Access Lists → Add Access List
- Name:
Nur intern - Access: Allow
192.168.1.0/24, Deny all - Oder: Basic Auth hinzufügen (Benutzername + Passwort als erste Hürde)
Dann in den Proxy-Host-Einstellungen die Access List zuweisen. Portainer und Proxmox würde ich nie ohne Zugriffsbeschränkung ins Internet stellen. Auch nicht mit starkem Passwort. Die Angriffsfläche ist einfach zu groß.
Option 2: Nginx manuell konfigurieren (Für Fortgeschrittene)
Wenn du mehr Kontrolle willst oder NPM dir zu “klickibunti” ist. Der manuelle Weg gibt dir volle Flexibilität, aber du schreibst Nginx-Configs von Hand.
Nginx + Certbot installieren
mkdir -p /opt/docker/nginx-manual
cat > /opt/docker/nginx-manual/docker-compose.yml << 'EOF'
services:
nginx:
image: nginx:alpine
container_name: nginx-reverse-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./ssl:/etc/nginx/ssl
- ./certbot-webroot:/var/www/certbot
- ./letsencrypt:/etc/letsencrypt
environment:
- TZ=Europe/Berlin
certbot:
image: certbot/certbot:latest
container_name: certbot
volumes:
- ./certbot-webroot:/var/www/certbot
- ./letsencrypt:/etc/letsencrypt
EOF
Nginx-Konfiguration pro Service
Jeder Service bekommt eine eigene Config-Datei. Beispiel für Nextcloud:
mkdir -p /opt/docker/nginx-manual/conf.d
cat > /opt/docker/nginx-manual/conf.d/nextcloud.conf << 'NGINXEOF'
server {
listen 80;
server_name nextcloud.mein-homelab.de;
# Certbot ACME Challenge
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Alles andere → HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name nextcloud.mein-homelab.de;
ssl_certificate /etc/letsencrypt/live/mein-homelab.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mein-homelab.de/privkey.pem;
# SSL Hardening
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;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Proxy zum Backend
location / {
proxy_pass http://192.168.1.110: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;
# Für große Datei-Uploads (Nextcloud!)
client_max_body_size 10G;
proxy_request_buffering off;
# Websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
NGINXEOF
SSL-Zertifikat mit Certbot holen
# Erstmaliges Zertifikat (HTTP-Challenge für einzelne Domains):
docker compose run --rm certbot certonly \
--webroot -w /var/www/certbot \
-d nextcloud.mein-homelab.de \
-d jellyfin.mein-homelab.de \
--email deine@email.de \
--agree-tos \
--no-eff-email
# Für Wildcard (DNS-Challenge mit Cloudflare):
docker compose run --rm certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d "*.mein-homelab.de" \
-d "mein-homelab.de" \
--email deine@email.de \
--agree-tos
Auto-Renewal per Cron
Let’s Encrypt-Zertifikate laufen nach 90 Tagen ab. Certbot erneuert sie automatisch — du musst nur dafür sorgen, dass es regelmäßig versucht wird:
# Cronjob: 2x täglich prüfen, ob Erneuerung nötig
(crontab -l 2>/dev/null; echo "0 3,15 * * * cd /opt/docker/nginx-manual && docker compose run --rm certbot renew --quiet && docker compose exec nginx nginx -s reload") | crontab -
Option 3: Traefik (Für Docker-Power-User)
Traefik ist der Liebling der Docker-Community. Statt per Klick oder Config-Datei konfigurierst du den Proxy über Docker Labels. Neuer Container mit den richtigen Labels → Traefik erkennt ihn automatisch und erstellt die Route. Kein Reload nötig.
Warum Traefik?
- Auto-Discovery: Neuer Container startet → Traefik erkennt ihn sofort
- Zero-Downtime: Kein
nginx reloadnötig - Mittels Labels: Die Proxy-Config steht direkt in der docker-compose.yml des Services
- Middleware: Rate-Limiting, Basic Auth, IP-Whitelist — als Labels am Container
Traefik installieren
# /opt/docker/traefik/docker-compose.yml
services:
traefik:
image: traefik:v3.3
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml
- ./acme.json:/acme.json
- ./dynamic:/etc/traefik/dynamic
environment:
- CF_DNS_API_TOKEN=dein-cloudflare-token
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.mein-homelab.de`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$05$$..."
networks:
- proxy
networks:
proxy:
name: proxy
external: true
# /opt/docker/traefik/traefik.yml
api:
dashboard: true
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
http:
tls:
certResolver: letsencrypt
domains:
- main: mein-homelab.de
sans:
- "*.mein-homelab.de"
providers:
docker:
exposedByDefault: false
network: proxy
file:
directory: /etc/traefik/dynamic
watch: true
certificatesResolvers:
letsencrypt:
acme:
email: deine@email.de
storage: acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
log:
level: WARN
Service mit Traefik-Labels
So sieht ein Docker-Service mit Traefik-Labels aus:
# Beispiel: Nextcloud mit Traefik
services:
nextcloud:
image: nextcloud:latest
container_name: nextcloud
restart: unless-stopped
volumes:
- ./html:/var/www/html
labels:
- "traefik.enable=true"
- "traefik.http.routers.nextcloud.rule=Host(`nextcloud.mein-homelab.de`)"
- "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt"
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
# Middleware für große Uploads:
- "traefik.http.middlewares.nextcloud-body.buffering.maxRequestBodyBytes=10737418240"
networks:
- proxy
- default
networks:
proxy:
external: true
Kein Reload, kein manuelles Zertifikat. Container starten → Traefik macht den Rest.
NPM vs. Traefik: Wann was?
| Aspekt | Nginx Proxy Manager | Traefik |
|---|---|---|
| Konfiguration | Web-GUI (klicken) | Docker Labels + YAML |
| Lernkurve | Flach — intuitiv | Steil — Labels, Middleware, Entrypoints |
| Auto-Discovery | Nein (manuell) | Ja (Docker-native) |
| Non-Docker Services | Einfach (IP:Port eintragen) | Möglich, aber per File-Provider |
| Updates | docker compose pull | docker compose pull |
| Ressourcen | ~100 MB RAM | ~50 MB RAM |
| Ideal für | Einsteiger, gemischte Umgebungen | Docker-only, DevOps-Fans |
Meine Empfehlung: Fang mit NPM an. Wenn dir die GUI irgendwann zu einschränkend wird oder du alles in Code haben willst, migriere zu Traefik. Beide machen den gleichen Job, der Weg dorthin ist nur unterschiedlich.
Sicherheit: Der Proxy als Schutzschild
Dein Reverse Proxy ist der einzige Punkt, der nach außen exponiert ist. Das ist gleichzeitig die Stärke (ein Punkt zu schützen) und die Schwachstelle (fällt der, fällt alles). Deswegen:
SSL-Konfiguration härten
# Nur moderne Protokolle (TLS 1.2 und 1.3)
ssl_protocols TLSv1.2 TLSv1.3;
# HSTS: Browser merkt sich "nur HTTPS" für ein Jahr
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Kein Embedding in Frames (Clickjacking-Schutz)
add_header X-Frame-Options "SAMEORIGIN" always;
# MIME-Type-Sniffing verhindern
add_header X-Content-Type-Options "nosniff" always;
Tipp: Teste deine SSL-Konfiguration unter SSL Labs. Ziel: A+ Rating. Mit den obigen Einstellungen erreichst du das.
Rate Limiting
Schützt vor Brute-Force-Angriffen auf Login-Seiten:
# In der nginx.conf (http-Block):
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/s;
# In der Server-Config:
location /login {
limit_req zone=login burst=10 nodelay;
proxy_pass http://backend;
}
Oder in NPM: Custom Nginx Configuration pro Proxy Host → dort eigene Rate-Limits eintragen.
Fail2ban für den Reverse Proxy
Fail2ban kann Nginx-Logs auswerten und IPs sperren, die zu viele fehlerhafte Anfragen stellen:
apt install fail2ban -y
cat > /etc/fail2ban/jail.local << 'EOF'
[nginx-botsearch]
enabled = true
port = http,https
logpath = /opt/docker/nginx-proxy-manager/data/logs/proxy-host-*_access.log
maxretry = 10
findtime = 60
bantime = 3600
[nginx-http-auth]
enabled = true
port = http,https
logpath = /opt/docker/nginx-proxy-manager/data/logs/proxy-host-*_error.log
maxretry = 5
bantime = 3600
EOF
systemctl restart fail2ban
Authelia / Authentik: Single Sign-On
Für zusätzliche Sicherheit kannst du einen SSO-Gateway vor deine Services schalten. Authelia oder Authentik fungieren als Login-Portal — jeder Request muss erst durch das Portal, bevor er zum Service weitergeleitet wird.
Das bedeutet: Selbst wenn eine Software eine Sicherheitslücke hat, kommt niemand dran, ohne sich vorher bei Authelia authentifiziert zu haben. Mit 2FA (TOTP oder WebAuthn/FIDO2) ist das eine verdammt starke Absicherung.
Authelia läuft als Docker-Container und integriert sich nahtlos in NPM und Traefik. Das ist aber einen eigenen Artikel wert — hier nur der Hinweis, dass es existiert und sich lohnt.
Services von unterwegs erreichbar machen
Hier wird’s ernst: Du öffnest Ports in deinem Router. Das heißt, dein Homelab ist aus dem Internet erreichbar. Das birgt Risiken. Mach es nur, wenn du weißt was du tust, und befolge die Sicherheitstipps oben.
Option A: Port-Forwarding (Direkt)
In deinem Router (z.B. Fritz!Box):
- Internet → Freigaben → Portfreigaben → Neue Freigabe
- Gerät: Dein Reverse-Proxy-Host
- Port 80 und 443 weiterleiten
- Fertig
Jetzt ist alles, was der Reverse Proxy bedient, von außen erreichbar. Genau deshalb ist es so wichtig, dass nur der Proxy nach außen zeigt und nicht die einzelnen Services direkt.
Option B: Cloudflare Tunnel (Kein offener Port nötig)
Wenn du keine Ports öffnen willst (oder kannst — manche Provider blocken das), ist ein Cloudflare Tunnel die eleganteste Lösung:
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=dein-tunnel-token
Der Tunnel baut eine ausgehende Verbindung zu Cloudflare auf. Kein eingehender Port nötig, kein Port-Forwarding, keine Firewall-Regeln. Cloudflare routet den Traffic über den Tunnel zu deinem Reverse Proxy.
Nachteile: Dein gesamter Traffic läuft über Cloudflare. Die können theoretisch mitlesen (sie terminieren SSL). Für ein Homelab mit Nextcloud und Jellyfin ist das in der Praxis kein Problem — für wirklich sensible Dinge (Vaultwarden) würde ich eher ein VPN nutzen.
Option C: VPN (Am sichersten)
Die sicherste Variante: Gar keine Ports öffnen. Stattdessen WireGuard-VPN einrichten und von unterwegs zuerst ins VPN verbinden. Dann bist du im lokalen Netz und erreichst alles wie zuhause.
Vorteil: Keinerlei Angriffsfläche von außen. Nachteil: Du musst zuerst VPN aktivieren. Für Sharing mit Familie oder Freunden unpraktisch.
Mein Setup: WireGuard für den persönlichen Zugriff + Cloudflare Tunnel für Services, die ich mit anderen teilen will (Jellyfin Familienzugang, Nextcloud-Shares).
Troubleshooting: Die häufigsten Probleme
502 Bad Gateway
Der Proxy kann den Backend-Service nicht erreichen.
Checkliste:
- Läuft der Backend-Service? →
docker psodersystemctl status - IP und Port korrekt?
- Backend auf
httpoderhttps? (Proxmox/Portainer nutzen HTTPS!) - Container im richtigen Docker-Netzwerk? (bei Traefik muss der Container im
proxy-Netzwerk sein) - Firewall auf dem Docker-Host? →
iptables -L -noderufw status
SSL-Zertifikat wird nicht ausgestellt
DNS-Challenge (Wildcard):
- API-Token korrekt? Hat der Token die richtigen Permissions?
- DNS-Provider richtig konfiguriert?
docker compose logs certbotoder NPM-Logs prüfen
HTTP-Challenge:
- Port 80 von außen erreichbar? → canyouseeme.org auf Port 80 testen
- DNS zeigt auf die richtige IP?
.well-known/acme-challenge/wird nicht von einem anderen Location-Block abgefangen?
“Too many redirects”
Klassiker. Passiert, wenn der Proxy HTTPS erzwingt, aber der Backend-Service auch HTTPS erzwingt, und beide sich gegenseitig umleiten.
Lösung: Im Backend-Service (z.B. Nextcloud) konfigurieren, dass es hinter einem Proxy läuft:
// Nextcloud config/config.php:
'overwriteprotocol' => 'https',
'trusted_proxies' => ['192.168.1.110'], // IP des Reverse Proxy
Websocket-Verbindungen brechen ab
Passiert bei Services wie Proxmox Console, Portainer, Vaultwarden, oder Uptime Kuma.
Lösung: Websocket-Support im Proxy aktivieren:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
In NPM: “Websockets Support” ✅ in den Proxy-Host-Einstellungen.
Upload-Limits
Nextcloud-Upload bricht bei 1 MB ab? Der Proxy hat ein Body-Size-Limit:
# Für Nextcloud: 10 GB erlauben
client_max_body_size 10G;
proxy_request_buffering off;
In NPM: Custom Nginx Configuration des Proxy Hosts:
client_max_body_size 10G;
proxy_request_buffering off;
Performance-Optimierung
Caching für statische Assets
Dein Proxy kann statische Dateien cachen, sodass sie nicht jedes Mal vom Backend geholt werden:
# In der Proxy-Config:
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ {
proxy_pass http://backend;
expires 30d;
add_header Cache-Control "public, immutable";
}
Gzip/Brotli Kompression
Falls der Backend-Service keine Kompression macht (viele Docker-Images tun’s nicht):
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml;
gzip_min_length 256;
gzip_vary on;
Reduziert den Traffic um 60-80% für Textinhalte. Besonders spürbar bei mobilem Zugriff.
HTTP/2 und HTTP/3
HTTP/2 ist bei NPM und Traefik standardmäßig aktiv. HTTP/3 (QUIC) bietet nochmal bessere Performance bei instabilen Verbindungen (Mobilfunk):
In Traefik:
entryPoints:
websecure:
address: ":443"
http3: {}
In NPM: HTTP/2 ist per Default an, HTTP/3 muss man über Custom Config aktivieren.
Monitoring: Weiß dein Proxy noch was er tut?
Dein Reverse Proxy ist kritische Infrastruktur. Wenn er down ist, sind alle Services down. Also: überwachen.
Mit Zabbix
Wenn du den Zabbix-Guide befolgt hast:
- Zabbix Agent auf dem Proxy-Host installieren
- Template “Nginx by Zabbix agent” zuweisen
- Nginx Status-Seite aktivieren:
server {
listen 127.0.0.1:8888;
location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
}
Jetzt überwacht Zabbix: Active Connections, Requests/s, Accepted/Handled, und alarmiert wenn Nginx nicht mehr antwortet.
Mit Uptime Kuma
Einfacher: In Uptime Kuma für jeden Proxy-Host einen HTTP-Monitor einrichten. Damit weißt du zumindest, ob die Services von außen erreichbar sind.
Nächste Schritte
Dein Reverse Proxy steht. Alle Services sind über saubere URLs mit SSL erreichbar. Was jetzt?
- Authelia oder Authentik einrichten für Single Sign-On und 2FA vor allen Services
- Monitoring konfigurieren — SSL-Ablaufdaten überwachen, Proxy-Status, Response-Times
- Crowdsec installieren — Community-basierte IP-Blocklisten, integriert sich direkt in Nginx
- Automatische Backups der Proxy-Konfiguration (NPM: das
data/-Verzeichnis sichern, Traefik:acme.json+ die YAML-Configs)
Fazit
Ein Reverse Proxy verwandelt dein Homelab vom Bastelprojekt mit IP:Port-Bookmarks in eine professionelle Infrastruktur mit sauberen URLs und gültigem SSL. Nginx Proxy Manager hat die gesamte Einrichtung auf ein paar Klicks reduziert — es gibt keine Ausrede mehr, Services ohne HTTPS zu betreiben.
Die Kombination aus Wildcard-Zertifikat, Split-DNS für intern und WireGuard oder Cloudflare Tunnel für extern ist meiner Erfahrung nach das beste Setup fürs Homelab. Neue Services hinzufügen dauert 30 Sekunden statt 30 Minuten. Und das grüne Schloss im Browser fühlt sich jedes Mal ein bisschen gut an.
Fang mit NPM an, richte 2-3 Services ein, und du wirst nie wieder 192.168.1.110:8096 in die Adressleiste tippen.
Zuletzt aktualisiert: Februar 2026 | Nginx Proxy Manager 2.x | Traefik 3.x | Let’s Encrypt