Eintrag

Nginx Proxy Manager: Reverse Proxy mit Web-UI für dein Homelab

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

NPM Architektur


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:

Ä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.local erreichbar machen
  • Dein lokaler DNS (Pi-hole, AdGuard oder Router) löst media.homelab.local zu deiner NPM-IP auf

Schritt-für-Schritt:

  1. Login ins NPM Admin-Interface (Port 81)

  2. Klick auf “Hosts” → “Proxy Hosts” → “Add Proxy Host”

  3. 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)
  4. 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
  5. 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:

  1. 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
  2. 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
  3. 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.

  1. Access Lists → Add Access List

  2. Name: “Heimnetz Only”

  3. Authorization:
    • Satisfy Any: Mindestens eine Regel muss erfüllt sein
    • Pass Auth: Authentifizierung übergeben (für externe Auth-Systeme)
  4. Access:
    • Allow: 192.168.0.0/16 (dein lokales Netz)
    • Deny: all (alle anderen blockieren)
  5. Save

  6. 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.

  1. Access List erstellen (wie oben)

  2. Users:
    • Add User
    • Username: deinname
    • Password: sicheres-passwort
  3. 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:

  1. Authelia/Authentik als Proxy Host einrichten (z.B. auth.homelab.local)

  2. In deinem Proxy Host: Custom Locations hinzufügen

  3. 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

  1. Streams → Add Stream

  2. 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)
  3. 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.

  1. Redirection Hosts → Add Redirection Host

  2. Domain Names: old.example.com

  3. Redirect to: https://new.example.com

  4. Redirect Code:
    • 301 Permanent: Suchmaschinen übernehmen die neue URL
    • 302 Temporary: Temporäre Weiterleitung
  5. Preserve Path: aktivieren (leitet /path zu new.example.com/path weiter)

  6. 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
  • SSL Tab:
    • SSL Certificate: Wildcard Cert *.homelab.local
    • Force SSL: ja
    • HTTP/2 Support: ja
  • 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
  • Advanced Tab:
    1
    2
    
    # Accept self-signed certificate from Proxmox
    proxy_ssl_verify off;
    

Ohne proxy_ssl_verify off bekommst 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:

  1. 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
  2. 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
  3. 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
  4. 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:

  1. Backend nicht erreichbar:
    • Ist der Service wirklich auf Port XYZ erreichbar?
    • Test: curl http://backend-ip:port
    • Läuft der Container/Service?
  2. Falsche IP/Port in NPM:
    • Doppelcheck: Forward Hostname/IP und Forward Port
    • Bei Docker: Container-Name statt IP (wenn im selben Netzwerk)
  3. Firewall blockiert:
    • Prüfe UFW/iptables auf dem Backend-Server
    • Prüfe Docker-Netzwerk-Isolation
  4. 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

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:

  1. Websockets Support aktivieren (Checkbox in Details-Tab)

  2. Manuell in Advanced Tab:
    1
    2
    3
    
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    
  3. 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:

  1. Container läuft nicht:
    1
    2
    
    docker ps | grep nginx-proxy-manager
    docker compose logs npm
    
  2. Port-Konflikt:
    • Ein anderer Service nutzt bereits Port 81
    • Ändere Mapping in docker-compose.yml: "8181:81"
  3. 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:

Let’s Encrypt:

DNS-Provider:

Alternative Reverse Proxies:

Authentifizierung:

Community:

Dieser Eintrag ist vom Autor unter CC BY 4.0 lizensiert.