Nginx Proxy Manager: Reverse Proxy mit Web-UI für dein Homelab
Jedes Homelab steht irgendwann vor derselben Herausforderung: Du hast 20+ Services am Laufen - Jellyfin, Immich, GitLab, Home Assistant - und willst nicht ständig mit IP-Adressen und Ports hantieren. Du willst einfach media.homelab.local im Browser eingeben und deine Filme schauen. Oder noch besser: richtige Domains mit gültigem SSL-Zertifikat, ohne dass dein Browser eine Sicherheitswarnung anzeigt. Nginx Proxy Manager (NPM) löst genau dieses Problem - und das mit einer Web-UI, die so intuitiv ist, dass du in fünf Minuten deine ersten Services am Laufen hast.
Was ist Nginx Proxy Manager?
Nginx Proxy Manager ist ein Open-Source Reverse Proxy mit einer modernen Web-Oberfläche. Unter der Haube werkelt der bewährte Nginx Webserver, aber du musst keine einzige Zeile Nginx-Konfiguration schreiben. Stattdessen klickst du dich durch eine übersichtliche UI und konfigurierst deine Proxy-Hosts, SSL-Zertifikate und Weiterleitungen.
Die wichtigsten Features auf einen Blick:
- Schicke Web-UI für alle Einstellungen
- Automatische Let’s Encrypt SSL-Zertifikate mit Auto-Renewal
- Nginx unter der Haube - stabil und bewährt
- Docker-ready und in Sekunden installiert
- Für Anfänger einfach, für Fortgeschrittene flexibel
- Aktive Community und regelmäßige Updates
Das Projekt wird auf GitHub gehostet und ist komplett kostenlos: NginxProxyManager/nginx-proxy-manager
Warum ein Reverse Proxy?
Bevor wir in die Installation einsteigen, lass uns kurz klären, warum du überhaupt einen Reverse Proxy brauchst. Das Konzept ist einfacher als es klingt:
Ohne Reverse Proxy:
- Du merkst dir IP:Port für jeden Service (192.168.1.100:8096 für Jellyfin, 192.168.1.101:2283 für Immich…)
- Kein SSL - dein Browser meckert bei sensiblen Services
- Jeder Service braucht einen eigenen Port nach außen
- Unübersichtlich und fehleranfällig
Mit Reverse Proxy:
- Du rufst lesbare Domains auf:
media.homelab.local,photos.homelab.local - Der Proxy leitet Anfragen an die richtigen Backend-Services weiter
- Ein zentraler SSL-Einstiegspunkt für alle Services
- Die Backend-Services können einfaches HTTP sprechen
Hier eine visuelle Darstellung:
graph LR
A[User Browser] -->|HTTPS| B[Nginx Proxy Manager]
B -->|HTTP| C[Jellyfin :8096]
B -->|HTTP| D[Immich :2283]
B -->|HTTP| E[GitLab :80]
B -->|HTTP| F[Home Assistant :8123]
style A fill:#e1f5ff
style B fill:#fff4e6
style C fill:#f3e5f5
style D fill:#f3e5f5
style E fill:#f3e5f5
style F fill:#f3e5f5
Der Reverse Proxy ist also dein zentraler Eingangspunkt. Er übernimmt die SSL-Terminierung (entschlüsselt HTTPS) und leitet die Anfrage dann per HTTP an den richtigen Service weiter. Das Backend muss sich nicht um Zertifikate kümmern.
Ein Reverse Proxy ist wie ein intelligenter Türsteher für dein Homelab: Er prüft, wer herein will, leitet an die richtige Stelle weiter und kümmert sich um die Sicherheit.
Features im Überblick
NPM bietet weit mehr als nur einfaches Routing. Hier eine Übersicht der wichtigsten Features:
| Feature | Beschreibung |
|---|---|
| Proxy Hosts | Domain-Routing zu Backend-Services (HTTP/HTTPS) |
| Redirection Hosts | 301/302 Weiterleitungen (alte Domain zu neuer Domain) |
| Streams | TCP/UDP Forwarding für Non-HTTP Services (z.B. Game-Server, MQTT) |
| 404 Hosts | Custom Error Pages für nicht existierende Domains |
| SSL Certificates | Let’s Encrypt (HTTP/DNS Challenge), Custom Certificates, Wildcard Support |
| Access Lists | IP-Whitelisting, Basic Authentication, Custom Rules |
| Advanced Config | Custom Nginx-Snippets für spezielle Anforderungen |
| Multi-User | Mehrere Benutzer mit unterschiedlichen Berechtigungen |
| Audit Log | Protokollierung aller Änderungen |
| API | REST API für Automatisierung |
Die meisten Homelab-Nutzer brauchen hauptsächlich Proxy Hosts und SSL Certificates. Aber es ist gut zu wissen, dass NPM mitwächst, wenn deine Anforderungen komplexer werden.
Installation mit Docker
Die Installation ist denkbar einfach. NPM läuft als Docker-Container und braucht nur drei Ports. Hier ist eine fertige Docker Compose Konfiguration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
npm:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
- "81:81" # Admin Web-UI
volumes:
- ./npm/data:/data
- ./npm/letsencrypt:/etc/letsencrypt
environment:
- TZ=Europe/Berlin
restart: unless-stopped
Was passiert hier?
- Port 80: HTTP-Traffic (für Let’s Encrypt HTTP-Challenge und automatische HTTPS-Weiterleitung)
- Port 443: HTTPS-Traffic (der eigentliche verschlüsselte Datenverkehr)
- Port 81: Admin-Interface (sollte nicht nach außen exponiert werden!)
- Volume
data: Datenbank, Konfigurationen, Logs - Volume
letsencrypt: SSL-Zertifikate
Installation:
1
2
3
4
5
6
7
8
9
10
11
12
# Verzeichnis erstellen
mkdir -p ~/nginx-proxy-manager/npm/{data,letsencrypt}
cd ~/nginx-proxy-manager
# docker-compose.yml erstellen (siehe oben)
vim docker-compose.yml
# Container starten
docker compose up -d
# Logs prüfen
docker compose logs -f npm
Nach wenigen Sekunden ist NPM bereit. Öffne http://deine-server-ip:81 im Browser.
Standard-Login:
- Email:
[email protected] - Passwort:
changeme
Ändere das Standard-Passwort sofort nach dem ersten Login! NPM fordert dich beim ersten Login automatisch dazu auf.
Erste Schritte: Proxy Host erstellen
Jetzt wird’s praktisch. Wir richten einen ersten Proxy Host ein - als Beispiel nehmen wir Jellyfin, deinen Media-Server.
Voraussetzungen:
- Jellyfin läuft auf 192.168.1.100:8096
- Du willst ihn unter
media.homelab.localerreichbar machen - Dein lokaler DNS (Pi-hole, AdGuard oder Router) löst
media.homelab.localzu deiner NPM-IP auf
Schritt-für-Schritt:
-
Login ins NPM Admin-Interface (Port 81)
-
Klick auf “Hosts” → “Proxy Hosts” → “Add Proxy Host”
- Tab “Details”:
- Domain Names:
media.homelab.local - Scheme:
http - Forward Hostname/IP:
192.168.1.100 - Forward Port:
8096 - Cache Assets: aktivieren (für statische Dateien)
- Block Common Exploits: aktivieren (Schutz gegen typische Angriffe)
- Websockets Support: aktivieren (wichtig für moderne Web-Apps)
- Domain Names:
- Tab “SSL”:
- SSL Certificate: “Request a new SSL Certificate” auswählen
- Force SSL: aktivieren (automatische Weiterleitung von HTTP zu HTTPS)
- HTTP/2 Support: aktivieren
- HSTS Enabled: aktivieren (zwingt Browser zu HTTPS)
- HSTS Subdomains: optional
- Save
Das war’s! NPM konfiguriert jetzt Nginx im Hintergrund, richtet das SSL-Zertifikat ein (sofern Let’s Encrypt konfiguriert ist) und startet den Proxy.
Öffne https://media.homelab.local im Browser - dein Jellyfin sollte mit gültigem SSL-Zertifikat erreichbar sein.
Wenn du mehrere Services auf demselben Server hast, kannst du auch Docker-Container-Namen statt IPs verwenden. Dazu müssen NPM und der Service im selben Docker-Netzwerk sein.
DNS-Konfiguration
Damit NPM deine Services unter schönen Domains erreichbar macht, muss der DNS stimmen. Es gibt mehrere Ansätze:
Option 1: Öffentliche Domain mit Port Forwarding
Szenario: Du hast eine echte Domain (z.B. example.com) und willst Services von außen erreichbar machen.
Setup:
- A-Record bei deinem DNS-Provider:
*.example.com→ deine öffentliche IP - Port Forwarding im Router: 80 und 443 zu deiner NPM-IP
- Let’s Encrypt HTTP-Challenge funktioniert out-of-the-box
Sicherheitshinweis:
- Exponiere nur Services, die wirklich von außen erreichbar sein müssen
- Nutze Access Lists für zusätzlichen Schutz
- Erwäge VPN (WireGuard) als Alternative
Option 2: Lokales DNS mit Pi-hole/AdGuard
Szenario: Services nur im Heimnetz erreichbar, keine öffentliche Exposition.
Setup:
- Wildcard DNS-Eintrag in Pi-hole:
*.homelab.local→ NPM-IP (z.B. 192.168.60.65) - Alternativ: Einzelne A-Records für jeden Service
- Let’s Encrypt HTTP-Challenge funktioniert nicht (kein Port 80 nach außen)
- Lösung: DNS Challenge oder Self-Signed Certificates
Option 3: Split DNS
Szenario: Öffentliche Domain, die intern auf private IP zeigt.
Setup:
- Öffentlicher DNS:
*.example.com→ öffentliche IP (für extern) - Lokaler DNS Override in Pi-hole:
*.example.com→ NPM-IP (192.168.60.65) - Beste aus beiden Welten: echte Domain, aber intern direkt erreichbar
- DNS Challenge empfohlen für SSL
DNS Challenge für Wildcard-Zertifikate
Die eleganteste Lösung für ein Homelab: Ein Wildcard-Zertifikat (*.example.com) für alle Subdomains, ohne Port 80 nach außen öffnen zu müssen.
Beispiel mit Cloudflare:
- API Token erstellen (Cloudflare Dashboard):
- My Profile → API Tokens → Create Token
- Template: “Edit zone DNS”
- Zone Resources: Include → Specific zone → deine-domain.com
- Token kopieren
- In NPM: SSL Certificate hinzufügen:
- SSL Certificates → Add SSL Certificate
- Domain Names:
*.example.com,example.com(beide!) - Use a DNS Challenge: aktivieren
- DNS Provider: Cloudflare
- Credentials File Content:
1
dns_cloudflare_api_token = dein-cloudflare-token
- Propagation Seconds: 120 (Cloudflare ist schnell)
- Save
- Warten (ca. 2 Minuten)
NPM erstellt jetzt automatisch einen TXT-Record bei Cloudflare, wartet auf DNS-Propagation und holt dann das Zertifikat ab. Dieses gilt für alle Subdomains (*.example.com) und wird automatisch alle 90 Tage erneuert.
Mit einem Wildcard-Zertifikat brauchst du nur ein einziges Zertifikat für alle Subdomains. Kein Port 80 nach außen nötig!
Unterstützte DNS-Provider:
NPM nutzt certbot unter der Haube und unterstützt dessen DNS-Plugins. Die wichtigsten:
- Cloudflare
- AWS Route 53
- Google Cloud DNS
- Azure DNS
- DigitalOcean
- Hetzner
- OVH
- Namecheap
- …und viele mehr
SSL-Zertifikate im Detail
SSL ist ein Kernfeature von NPM. Lass uns die verschiedenen Möglichkeiten genauer anschauen.
Let’s Encrypt mit HTTP-01 Challenge
Wie es funktioniert:
- Let’s Encrypt stellt eine Challenge-Datei unter
http://deine-domain.com/.well-known/acme-challenge/xyz - NPM stellt diese Datei bereit
- Let’s Encrypt prüft, ob die Datei erreichbar ist
- Bei Erfolg wird das Zertifikat ausgestellt
Voraussetzungen:
- Port 80 muss von außen erreichbar sein
- Domain muss auf deine öffentliche IP zeigen
- Router-Port-Forwarding: Port 80 → NPM
Vorteile:
- Einfaches Setup
- Funktioniert sofort
Nachteile:
- Kein Wildcard-Zertifikat möglich
- Port 80 muss offen sein
- Funktioniert nicht bei rein lokalen Domains
Let’s Encrypt mit DNS-01 Challenge
Wie es funktioniert:
- Let’s Encrypt fordert einen TXT-Record im DNS
- NPM erstellt diesen automatisch via API deines DNS-Providers
- Let’s Encrypt prüft den TXT-Record
- Bei Erfolg wird das Zertifikat ausgestellt
Voraussetzungen:
- API-Zugang zu deinem DNS-Provider
- Domain muss existieren (kann aber auf private IP zeigen)
Vorteile:
- Wildcard-Zertifikate möglich (
*.example.com) - Kein Port nach außen nötig
- Funktioniert auch für rein interne Services
Nachteile:
- Etwas komplexeres Setup
- Braucht API-Token vom DNS-Provider
Custom Certificates
Wann sinnvoll:
- Du hast bereits Zertifikate (z.B. von deiner Firma)
- Du nutzt eine interne CA
- Let’s Encrypt ist nicht möglich
Upload:
- SSL Certificates → Add SSL Certificate
- Custom
- Certificate Key: dein Private Key (.key)
- Certificate: dein Certificate (.crt oder .pem)
- Intermediate Certificate: optional
Auto-Renewal
NPM kümmert sich automatisch um die Erneuerung von Let’s Encrypt Zertifikaten:
- Prüfung alle 24 Stunden
- Erneuerung 30 Tage vor Ablauf
- Bei Fehler: Retry mit Exponential Backoff
- Logs unter Admin → Logs
Let’s Encrypt Zertifikate sind 90 Tage gültig. NPM erneuert sie automatisch nach 60 Tagen. Du musst dich um nichts kümmern.
Access Lists und Sicherheit
Nicht jeder Service soll für jeden erreichbar sein. NPM bietet verschiedene Sicherheitsmechanismen:
Access Lists erstellen
Use Case: Du willst dein Proxmox-Interface nur aus deinem Heimnetz erreichbar machen.
-
Access Lists → Add Access List
-
Name: “Heimnetz Only”
- Authorization:
- Satisfy Any: Mindestens eine Regel muss erfüllt sein
- Pass Auth: Authentifizierung übergeben (für externe Auth-Systeme)
- Access:
- Allow:
192.168.0.0/16(dein lokales Netz) - Deny:
all(alle anderen blockieren)
- Allow:
-
Save
- Bei Proxy Host zuweisen:
- Proxy Host bearbeiten
- Tab “Details” → Access List: “Heimnetz Only” auswählen
Fertig! Der Service ist jetzt nur noch aus deinem lokalen Netz erreichbar.
Basic Authentication
Use Case: Du willst einen zusätzlichen Login-Schutz vor dem eigentlichen Service.
-
Access List erstellen (wie oben)
- Users:
- Add User
- Username:
deinname - Password:
sicheres-passwort
- Bei Proxy Host zuweisen
Beim Aufruf der Domain erscheint jetzt zuerst ein Browser-Login-Prompt. Erst nach erfolgreicher Authentifizierung wird die Anfrage an den Backend-Service weitergeleitet.
Basic Auth ist kein Ersatz für echte SSO-Lösungen wie Authelia oder Authentik. Es ist ein zusätzlicher Schutz, aber Passwörter werden Base64-kodiert (nicht verschlüsselt) übertragen. Nutze es nur über HTTPS!
Kombination mit Authelia/Authentik
Für professionelle Single Sign-On (SSO) Lösungen kannst du NPM mit Authelia oder Authentik kombinieren:
-
Authelia/Authentik als Proxy Host einrichten (z.B.
auth.homelab.local) -
In deinem Proxy Host: Custom Locations hinzufügen
-
Forward Authentication konfigurieren:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Forward auth to Authelia
location /auth {
internal;
proxy_pass http://authelia:9091/api/verify;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Method $request_method;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-URI $request_uri;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
# Protect all locations
auth_request /auth;
auth_request_set $user $upstream_http_remote_user;
proxy_set_header Remote-User $user;
Das ist fortgeschritten, aber ermöglicht echtes SSO mit 2FA über alle Services hinweg.
Erweiterte Konfiguration
NPM ist nicht nur für einfache Proxies gedacht. Für Power-User gibt es zahlreiche Anpassungsmöglichkeiten.
Custom Nginx Snippets
Jeder Proxy Host hat einen “Advanced”-Tab, wo du eigene Nginx-Direktiven einfügen kannst.
Beispiel 1: Security Headers
1
2
3
4
5
6
7
8
9
# Security Headers
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 "camera=(), microphone=(), geolocation=()" always;
# Optional: Content Security Policy
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
Diese Headers schützen vor typischen Web-Angriffen (Clickjacking, XSS, etc.).
Beispiel 2: WebSocket Support
Manche Services (Home Assistant, Jellyfin) brauchen WebSocket-Support für Echtzeit-Kommunikation:
1
2
3
# WebSocket Support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
NPM hat in den Basis-Einstellungen bereits eine “Websockets Support”-Checkbox. Die solltest du zuerst nutzen. Custom Config ist nur für spezielle Fälle nötig.
Beispiel 3: Large File Uploads
Standard-Nginx erlaubt nur 1MB Uploads. Für Immich (Foto-Upload) oder Nextcloud brauchst du mehr:
1
2
3
4
5
6
7
8
# Allow large uploads (50GB)
client_max_body_size 50G;
# Increase timeouts for large uploads
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
send_timeout 3600;
Beispiel 4: Custom Error Pages
1
2
3
4
5
6
# Custom 502 Error Page
error_page 502 /custom_502.html;
location = /custom_502.html {
root /data/nginx/error_pages;
internal;
}
Stream Hosts (TCP/UDP)
NPM kann nicht nur HTTP/HTTPS proxyen, sondern auch rohe TCP/UDP-Verbindungen weiterleiten.
Use Cases:
- Game-Server (Minecraft, Valheim)
- MQTT Broker (Port 1883)
- SSH-Zugang (Port 22)
- MySQL/PostgreSQL (nicht empfohlen für Production!)
Beispiel: Minecraft-Server
-
Streams → Add Stream
- Details:
- Incoming Port:
25565 - Forwarding Host:
192.168.1.200(dein Minecraft-Server) - Forwarding Port:
25565 - TCP Forwarding: aktivieren
- UDP Forwarding: aktivieren (für Minecraft wichtig)
- Incoming Port:
- Save
Dein Minecraft-Server ist jetzt über die NPM-IP:25565 erreichbar.
Beachte: Stream Hosts umgehen alle HTTP-Features wie SSL, Access Lists, etc. Sie leiten nur rohe Pakete weiter.
Redirection Hosts
Manchmal willst du einfach nur eine Domain auf eine andere weiterleiten.
Use Case: Alte Domain old.example.com soll auf new.example.com weiterleiten.
-
Redirection Hosts → Add Redirection Host
-
Domain Names:
old.example.com -
Redirect to:
https://new.example.com - Redirect Code:
- 301 Permanent: Suchmaschinen übernehmen die neue URL
- 302 Temporary: Temporäre Weiterleitung
-
Preserve Path: aktivieren (leitet
/pathzunew.example.com/pathweiter) - SSL: Let’s Encrypt Zertifikat für old.example.com
Fertig! Alle Anfragen an old.example.com werden automatisch auf new.example.com weitergeleitet.
Backup und Wartung
NPM ist robust, aber Backups sind dennoch wichtig.
Was muss gesichert werden?
Wenn du die Docker-Volumes wie oben konfiguriert hast:
./npm/data/: Datenbank, User-Accounts, Proxy-Konfigurationen./npm/letsencrypt/: SSL-Zertifikate
Einfaches Backup-Script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
BACKUP_DIR="/backup/nginx-proxy-manager"
DATE=$(date +%Y-%m-%d_%H-%M-%S)
NPM_DIR="/home/darthvaper/nginx-proxy-manager"
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Stop NPM (optional, für konsistente Backups)
cd "$NPM_DIR"
docker compose stop npm
# Backup volumes
tar czf "$BACKUP_DIR/npm-data-$DATE.tar.gz" -C "$NPM_DIR/npm" data
tar czf "$BACKUP_DIR/npm-letsencrypt-$DATE.tar.gz" -C "$NPM_DIR/npm" letsencrypt
# Start NPM
docker compose start npm
# Keep only last 7 backups
find "$BACKUP_DIR" -name "npm-*.tar.gz" -mtime +7 -delete
echo "Backup completed: npm-data-$DATE.tar.gz"
Cron-Job einrichten:
1
2
# Daily backup at 3 AM
0 3 * * * /home/darthvaper/scripts/backup-npm.sh
Restore
1
2
3
4
5
6
7
8
9
10
11
# Stop NPM
docker compose stop npm
# Restore data
cd /home/darthvaper/nginx-proxy-manager/npm
rm -rf data letsencrypt
tar xzf /backup/nginx-proxy-manager/npm-data-2026-02-01_03-00-00.tar.gz
tar xzf /backup/nginx-proxy-manager/npm-letsencrypt-2026-02-01_03-00-00.tar.gz
# Start NPM
docker compose start npm
Updates
NPM-Updates sind einfach:
1
2
3
cd /home/darthvaper/nginx-proxy-manager
docker compose pull npm
docker compose up -d npm
Docker lädt das neue Image herunter und startet den Container neu. Deine Konfiguration bleibt erhalten (liegt ja in den Volumes).
Schau regelmäßig auf der GitHub-Seite nach Updates. NPM zeigt auch in der UI eine Notification, wenn eine neue Version verfügbar ist.
Log-Rotation
NPM schreibt Logs für jeden Proxy Host. Ohne Rotation können diese groß werden.
NPM macht das automatisch, aber du kannst die Retention anpassen:
1
2
3
4
5
6
7
8
# In den Container
docker exec -it nginx-proxy-manager bash
# Logrotate-Config prüfen
cat /etc/logrotate.d/nginx
# Logs manuell rotieren
logrotate -f /etc/logrotate.d/nginx
Standard-Retention: 14 Tage.
Homelab-Beispiele
Jetzt wird’s konkret. Hier sind echte Beispiele aus meinem Homelab:
| Service | Domain | Backend | Port | Besonderheiten |
|---|---|---|---|---|
| Jellyfin | media.homelab.local | 192.168.60.50 | 8096 | WebSocket Support |
| Immich | photos.homelab.local | 192.168.60.80 | 2283 | client_max_body_size 50G |
| GitLab | git.homelab.local | 192.168.60.170 | 80 | - |
| Home Assistant | hass.homelab.local | 192.168.30.85 | 8123 | WebSocket Support |
| Proxmox | pve.homelab.local | 192.168.60.15 | 8006 | HTTPS Backend, proxy_ssl_verify off |
| NetBox | netbox.homelab.local | 192.168.60.136 | 8081 | - |
| Gotify | notify.homelab.local | 192.168.60.100 | 8080 | WebSocket Support |
Beispiel 1: Jellyfin (Media-Server)
Setup:
- Domain:
media.homelab.local - Backend:
192.168.60.50:8096 - Besonderheiten: WebSocket für Live-Transcoding-Status
NPM-Konfiguration:
- Details Tab:
- Domain Names:
media.homelab.local - Scheme:
http - Forward Hostname/IP:
192.168.60.50 - Forward Port:
8096 - Cache Assets: ja
- Block Common Exploits: ja
- Websockets Support: ja
- Domain Names:
- SSL Tab:
- SSL Certificate: Wildcard Cert
*.homelab.local - Force SSL: ja
- HTTP/2 Support: ja
- SSL Certificate: Wildcard Cert
- Advanced Tab: (leer, Defaults reichen)
Beispiel 2: Immich (Foto-Management)
Setup:
- Domain:
photos.homelab.local - Backend:
192.168.60.80:2283 - Besonderheiten: Große Foto-Uploads
NPM-Konfiguration:
-
Details Tab: (wie oben)
-
Advanced Tab:
1 2 3 4 5 6 7
# Allow large photo uploads (50GB) client_max_body_size 50G; # Increase timeouts proxy_connect_timeout 3600; proxy_send_timeout 3600; proxy_read_timeout 3600;
Beispiel 3: Proxmox (HTTPS Backend)
Setup:
- Domain:
pve.homelab.local - Backend:
192.168.60.15:8006(HTTPS!) - Besonderheiten: Proxmox nutzt selbstsigniertes Zertifikat
NPM-Konfiguration:
- Details Tab:
- Domain Names:
pve.homelab.local - Scheme:
https(wichtig!) - Forward Hostname/IP:
192.168.60.15 - Forward Port:
8006 - Block Common Exploits: ja
- Websockets Support: ja
- Domain Names:
- Advanced Tab:
1 2
# Accept self-signed certificate from Proxmox proxy_ssl_verify off;
Ohne
proxy_ssl_verify offbekommst du einen 502 Bad Gateway, weil NPM das selbstsignierte Proxmox-Zertifikat nicht akzeptiert.
Beispiel 4: Home Assistant (WebSocket + Custom Headers)
Setup:
- Domain:
hass.homelab.local - Backend:
192.168.30.85:8123 - Besonderheiten: WebSocket für Live-Updates, Trusted Proxies
NPM-Konfiguration:
-
Details Tab: (wie gehabt, Websockets aktivieren)
-
Advanced Tab:
1 2 3 4 5
# Home Assistant requires these headers 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;
Home Assistant Configuration:
1
2
3
4
http:
use_x_forwarded_for: true
trusted_proxies:
- 192.168.60.65 # NPM IP
Vergleich: NPM vs. Traefik vs. Caddy vs. HAProxy
NPM ist nicht die einzige Option. Hier ein Vergleich mit anderen populären Reverse Proxies:
| Feature | NPM | Traefik | Caddy | HAProxy |
|---|---|---|---|---|
| Web-UI | Ja, sehr gut | Dashboard (read-only) | Nein | Stats-Dashboard |
| Konfiguration | UI (klicken) | Labels/YAML | Caddyfile/JSON | HAProxy.cfg |
| SSL/Let’s Encrypt | Automatisch (UI) | Automatisch (Labels) | Automatisch (out-of-box) | Manuell |
| Docker-Integration | Manuell | Nativ (Labels) | Plugin | Manuell |
| Performance | Gut (Nginx) | Sehr gut | Gut | Exzellent |
| Middlewares | Custom Config | Viele integriert | Plugins | Custom Lua |
| TCP/UDP | Ja (Streams) | Ja | Ja | Ja |
| Lernkurve | Sehr flach | Steil | Mittel | Steil |
| Ideal für | Homelab-Anfänger | Docker-Umgebungen | Einfachheit | High-Performance |
Meine Empfehlung:
- Homelab-Anfänger: NPM - beste UI, einfachstes Setup
- Docker-Umgebungen mit vielen Containern: Traefik - automatische Service-Erkennung via Labels
- Minimalisten: Caddy - einfachste Config, automatisches HTTPS
- High-Performance/Production: HAProxy - beste Performance, aber komplexer
Troubleshooting
Auch mit NPM läuft nicht immer alles glatt. Hier die häufigsten Probleme und Lösungen:
SSL-Zertifikat wird nicht ausgestellt
Symptom: “Failed to obtain certificate” in den Logs.
Ursachen & Lösungen:
- Port 80 nicht erreichbar (HTTP Challenge):
- Prüfe Router Port-Forwarding
- Prüfe Firewall auf dem NPM-Server
- Test:
curl http://deine-domain.com/.well-known/acme-challenge/test
- DNS noch nicht propagiert:
- Warte 5-10 Minuten nach DNS-Änderung
- Prüfe:
nslookup deine-domain.com - Let’s Encrypt cached DNS für kurze Zeit
- Rate Limit erreicht:
- Let’s Encrypt: 5 Fehlversuche pro Stunde, 50 Zertifikate pro Domain pro Woche
- Warte eine Stunde und versuche es erneut
- Nutze Staging-Environment zum Testen
- DNS Challenge: API-Token falsch:
- Prüfe Token-Berechtigungen (Zone DNS Edit erforderlich)
- Prüfe auf Leerzeichen oder Zeilenumbrüche im Token
- Teste Token direkt via Cloudflare API
Debug-Logs anschauen:
1
docker compose logs npm | grep -i "certificate\|acme\|lets"
502 Bad Gateway
Symptom: NPM zeigt “502 Bad Gateway” beim Aufrufen der Domain.
Ursachen & Lösungen:
- Backend nicht erreichbar:
- Ist der Service wirklich auf Port XYZ erreichbar?
- Test:
curl http://backend-ip:port - Läuft der Container/Service?
- Falsche IP/Port in NPM:
- Doppelcheck: Forward Hostname/IP und Forward Port
- Bei Docker: Container-Name statt IP (wenn im selben Netzwerk)
- Firewall blockiert:
- Prüfe UFW/iptables auf dem Backend-Server
- Prüfe Docker-Netzwerk-Isolation
- HTTPS Backend ohne SSL-Verify-Off:
- Wenn Backend HTTPS spricht (z.B. Proxmox), nutze Scheme
https - Füge
proxy_ssl_verify off;im Advanced Tab hinzu
- Wenn Backend HTTPS spricht (z.B. Proxmox), nutze Scheme
Debug:
1
2
# Aus NPM-Container heraus Backend testen
docker exec -it nginx-proxy-manager curl http://192.168.60.50:8096
WebSocket-Verbindung funktioniert nicht
Symptom: Service lädt, aber Echtzeit-Features (Live-Updates, Chat) funktionieren nicht.
Lösung:
-
Websockets Support aktivieren (Checkbox in Details-Tab)
- Manuell in Advanced Tab:
1 2 3
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_http_version 1.1;
- Timeouts erhöhen:
1
proxy_read_timeout 86400;
Large Upload schlägt fehl
Symptom: Upload bricht bei großen Dateien (>1MB) ab.
Lösung:
1
2
3
4
5
6
7
# In Advanced Tab des Proxy Hosts
client_max_body_size 50G; # oder beliebige Größe
# Optional: Timeouts erhöhen
proxy_connect_timeout 3600;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
NPM UI nicht erreichbar (Port 81)
Ursachen:
- Container läuft nicht:
1 2
docker ps | grep nginx-proxy-manager docker compose logs npm - Port-Konflikt:
- Ein anderer Service nutzt bereits Port 81
- Ändere Mapping in docker-compose.yml:
"8181:81"
- Firewall:
1
sudo ufw allow 81/tcp
Tipps für die Praxis
Zum Abschluss noch ein paar Best Practices aus meiner Erfahrung:
1. Container-Namen statt IPs nutzen
Wenn NPM und deine Services im selben Docker-Netzwerk laufen:
1
2
3
4
5
6
7
8
9
# docker-compose.yml
networks:
homelab:
external: true
services:
npm:
networks:
- homelab
Dann kannst du in NPM den Container-Namen statt der IP nutzen:
- Forward Hostname:
jellyfin(statt 192.168.60.50) - Forward Port:
8096
Vorteil: Wenn sich die IP ändert, funktioniert der Proxy weiter.
2. Monitoring aufsetzen
Überwache deine Services mit Uptime Kuma oder ähnlichen Tools:
- Uptime-Checks alle 5 Minuten
- SSL-Zertifikats-Ablauf-Warnings
- NPM selbst monitoren (Port 81 erreichbar?)
3. Naming Convention etablieren
Strukturiere deine Domains konsistent:
- Services:
service.homelab.local(z.B.media.homelab.local) - Admin-Tools:
tool-admin.homelab.local(z.B.npm-admin.homelab.local) - Monitoring:
monitor.homelab.local
So behältst du den Überblick, auch bei 50+ Services.
4. Access Lists konsequent nutzen
Standard-Setup:
- Öffentliche Services (z.B. Blog): keine Access List
- Interne Services (z.B. Proxmox): Access List “Heimnetz Only”
- Admin-Interfaces (z.B. NPM selbst): Access List “Admin Only” (nur deine IP)
5. API für Automatisierung nutzen
NPM hat eine REST API. Du kannst damit Proxy Hosts per Script erstellen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# API Token in NPM UI erstellen (Users → API Tokens)
# Proxy Host erstellen
curl -X POST https://npm.homelab.local/api/nginx/proxy-hosts \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain_names": ["newservice.homelab.local"],
"forward_scheme": "http",
"forward_host": "192.168.60.200",
"forward_port": 8080,
"ssl_forced": true,
"certificate_id": 1
}'
Use Cases:
- Automatisches Hinzufügen von Services via Ansible/Terraform
- Backup-Scripts, die auch NPM-Config exportieren
- Monitoring, das Proxy Hosts automatisch checked
6. Logs regelmäßig checken
Schau ab und zu in die NPM-Logs:
1
2
docker compose logs npm | grep -i error
docker compose logs npm | grep -i certificate
So bemerkst du Probleme (z.B. fehlgeschlagene Zertifikats-Renewals) frühzeitig.
7. Staging-Zertifikate zum Testen
Let’s Encrypt hat Rate Limits. Zum Testen:
1
2
3
4
5
# In NPM-Container
docker exec -it nginx-proxy-manager bash
# Certbot manuell mit Staging ausführen
certbot certonly --staging --manual --preferred-challenges dns -d '*.example.com'
Staging-Zertifikate sind ungültig, aber du kannst Config und DNS testen, ohne echte Rate Limits zu treffen.
8. Documentation führen
Dokumentiere deine NPM-Setup:
- Welche Domain führt zu welchem Service?
- Welche Access Lists sind wo im Einsatz?
- Welche Custom Configs wurden warum hinzugefügt?
Das hilft in 6 Monaten, wenn du nicht mehr weißt, warum du proxy_ssl_verify off für Proxmox brauchst.
Fazit
Nginx Proxy Manager ist für mich der beste Einstiegspunkt ins Reverse Proxying im Homelab. Die Web-UI macht es unglaublich einfach, in Minuten erste Services mit gültigem SSL zu konfigurieren - ohne eine einzige Zeile Nginx-Config zu schreiben.
Was NPM auszeichnet:
- Perfekte Balance zwischen Einfachheit und Flexibilität
- Let’s Encrypt SSL mit Wildcard-Support via DNS Challenge
- Stabil und ausgereift (basiert auf Nginx, einem der meistgenutzten Webserver weltweit)
- Aktive Community und regelmäßige Updates
- Für 95% aller Homelab-Anwendungsfälle mehr als ausreichend
Wann NPM vielleicht nicht die beste Wahl ist:
- Riesige Docker-Umgebungen mit hunderten Containern (→ Traefik mit Auto-Discovery)
- Höchste Performance-Anforderungen (→ HAProxy)
- Du liebst minimalistische Configs (→ Caddy)
Aber für den typischen Homelab-User - vom Anfänger bis zum Fortgeschrittenen - ist NPM die ideale Lösung. Es wächst mit deinen Anforderungen mit: Du startest mit simplen Proxy Hosts, und wenn du später WebSocket-Tweaks, Custom Headers oder Access Lists brauchst, ist alles da.
Mein Homelab läuft seit über zwei Jahren mit NPM, und ich hatte genau null SSL-Probleme (nach initialem Setup). Zertifikate werden automatisch erneuert, neue Services sind in 2 Minuten konfiguriert, und die Web-UI macht es sogar Nicht-Technikern möglich, Services hinzuzufügen.
Also: Installier NPM, richte dein erstes SSL-Zertifikat ein, und genieße dein Homelab mit schönen Domains statt kryptischen IP:Port-Kombinationen!
Ressourcen
Nginx Proxy Manager:
- GitHub: https://github.com/NginxProxyManager/nginx-proxy-manager
- Dokumentation: https://nginxproxymanager.com/guide/
- Docker Hub: https://hub.docker.com/r/jc21/nginx-proxy-manager
Let’s Encrypt:
- Hauptseite: https://letsencrypt.org/
- Rate Limits: https://letsencrypt.org/docs/rate-limits/
- DNS Plugins: https://eff-certbot.readthedocs.io/en/stable/using.html#dns-plugins
DNS-Provider:
- Cloudflare: https://cloudflare.com
- Cloudflare API Tokens: https://dash.cloudflare.com/profile/api-tokens
Alternative Reverse Proxies:
- Traefik: https://traefik.io/
- Caddy: https://caddyserver.com/
- HAProxy: https://www.haproxy.org/
Authentifizierung:
- Authelia: https://www.authelia.com/
- Authentik: https://goauthentik.io/
Community:
- NPM Discord: https://discord.com/invite/Zm8CbXZFXw
- r/selfhosted: https://reddit.com/r/selfhosted