# Kapitel 3 – Nginx Proxy Manager ##Einleitung Im Heimnetz rufen wir unsere Container über ihre internen IP-Adressen auf – einfach, solange wir im gleichen Netzwerk sind. Sobald wir aber einen Dienst **aus dem Internet** erreichbar machen wollen, stoßen wir auf ein zentrales Problem: Unser Router besitzt nach außen nur **eine öffentliche IP-Adresse**, die vom Internetanbieter zugeteilt wird. ### Domain und DNS Eine **Domain** (z. B. `meinedomain.de`) ist nichts anderes als ein Name, der in eine IP-Adresse aufgelöst wird. Diesen Übersetzungsdienst übernimmt das **Domain Name System (DNS)**. Ruft jemand deine Domain auf, fragt DNS im Hintergrund nach, welche IP dahintersteckt, und stellt die Verbindung her. ### Dynamische IP Bei Privatanschlüssen vergeben die Provider in den allermeisten Fällen **dynamische IP-Adressen**. Das heißt: deine öffentliche IP ändert sich regelmäßig – manchmal einmal am Tag, manchmal bei jeder Router-Neuverbindung. Ohne zusätzliche Technik müsstest du jedes Mal, wenn sich die IP ändert, den DNS-Eintrag deiner Domain von Hand aktualisieren. Das ist nicht nur zeitaufwendig, sondern kann auch zu längeren Ausfällen führen, wenn die Domain auf eine alte, falsche IP zeigt. ### DynDNS Hier setzt **Dynamic DNS (DynDNS)** an. DynDNS-Anbieter bieten dir eine einfache Möglichkeit, deine aktuelle IP automatisch in DNS einzutragen: - Ein kleiner Client im Router oder auf deinem Server meldet die aktuelle IP an den DynDNS-Dienst. - Dieser aktualisiert sofort den hinterlegten DNS-Eintrag. - Damit bleibt dein Domainname immer aktuell erreichbar, auch wenn sich deine IP-Adresse ändert. > [!NOTE] > **Domain und DynDNS sind nicht dasselbe.** > - Eine Domain ist der **Name**, der über DNS in eine IP-Adresse übersetzt wird. > - DynDNS ist ein **Mechanismus**, um diese Übersetzung automatisch aktuell zu halten, wenn sich deine IP ändert. > Am professionellsten ist die Kombination: eine eigene Domain, deren Einträge per DynDNS-Dienst regelmäßig aktualisiert werden. --- ### Praktisches Beispiel: Nextcloud, Pi-hole Dashboard und NPM Nehmen wir drei Container, die wir von außen erreichen wollen: - die **Nextcloud** (Dateizugriff von unterwegs), - das **Pi-hole Dashboard** (nur Verwaltung, nicht der eigentliche DNS-Dienst), - und die **Weboberfläche des Nginx Proxy Manager** selbst. **Ohne NPM** müssten wir für jeden Dienst einen Port am Router freigeben: - `meineip:8080` → Nextcloud - `meineip:8443` → Pi-hole Dashboard - `meineip:9000` → NPM Web-UI Das ist unübersichtlich, schwer zu merken und öffnet mehrere Angriffsflächen. **Mit NPM** sieht es professionell und sicher aus: - `cloud.meinedomain.de` → Nextcloud - `dns.meinedomain.de` → Pi-hole Dashboard - `proxy.meinedomain.de` → NPM Web-UI Alle Anfragen laufen durch **eine einzige Adresse** (deine Domain) und werden vom Proxy an den richtigen Container verteilt. Von außen sind nur Port 80 und 443 sichtbar, alle internen Dienste bleiben geschützt. 👉 *Schaubild einfügen: Vergleich „ohne NPM“ (mehrere Ports, Chaos) vs. „mit NPM“ (eine Adresse, klare Subdomains).* > [!TIP] > Dieses Beispiel zeigt: Ein Reverse Proxy ist wie ein **Wegweiser**. > Ohne ihn endet alles in Port-Chaos, mit ihm hast du klare Adressen und eine verschlüsselte, zentrale Stelle für deine Dienste. --- ## Voraussetzungen Für den Nginx Proxy Manager benötigen wir einen eigenen LXC-Container in Proxmox. Dieser Container bildet die Basis, auf der wir den Proxy später installieren und betreiben. ### Anforderungen an den Container - **Betriebssystem:** Debian 12 Debian ist schlank, stabil und für Serverdienste wie NPM bestens geeignet. - **Ressourcen:** - 2 CPU-Kerne - 2 GB RAM - 8–16 GB Speicherplatz (je nach Anzahl der später verwalteten Dienste) - **Netzwerk:** Eine feste IPv4-Adresse im Heimnetz (z. B. `192.168.1.6`). Diese Adresse wird später im Router für die Weiterleitung von Port 80 und 443 benötigt. - **Internetverbindung:** Notwendig für Paketdownloads und das Einrichten von SSL-Zertifikaten. ### Hinweis bei Problemen Falls du unsicher bist, wie ein LXC-Container in Proxmox erstellt wird, sieh dir bitte noch einmal **Kapitel 1** an. Dort haben wir den Prozess ausführlich beschrieben – von der Auswahl des Templates über die Konfiguration bis hin zum ersten Zugriff. > [!TIP] > Wähle für die IP-Adresse einen Bereich **außerhalb** des DHCP-Pools deines Routers. > Damit stellst du sicher, dass es später keine Konflikte mit automatisch vergebenen Adressen gibt. 👉 *Screenshot geeignet: Proxmox-Dialog „Neuen LXC erstellen“ (Allgemeine Einstellungen).* --- ## Schritt für Schritt Anleitung ### Installation Wir starten im bereits erstellten LXC-Container (Debian 12) und installieren den Nginx Proxy Manager als Docker-Applikation. Alle Befehle werden direkt im Container per SSH ausgeführt. #### 1) System aktualisieren & Basis-Tools ```bash apt update apt upgrade -y # Basis-Tools, die wir sicher benötigen: apt install -y ca-certificates curl gnupg lsb-release # Dummy-Zeile: ggf. fehlende Tools im Debugging nachinstallieren # apt install -y nano wget sudo ``` #### 2) Docker-Engine + Compose-Plugin installieren Wir installieren Docker aus dem offiziellen Repository: ```bash install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \ https://download.docker.com/linux/debian \ $(. /etc/os-release && echo $VERSION_CODENAME) stable" \ > /etc/apt/sources.list.d/docker.list apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ``` > [!TIP] > Prüfe die Installation mit: > ```bash > docker --version > docker compose version > ``` #### 3) Verzeichnisse für NPM anlegen ```bash mkdir -p /opt/npm/data mkdir -p /opt/npm/letsencrypt ``` #### 4) `docker-compose.yml` erstellen Wir legen die Compose-Datei für NPM an: ```bash nano /opt/npm/docker-compose.yml ``` Inhalt einfügen: ```yaml services: npm: image: jc21/nginx-proxy-manager:latest restart: unless-stopped ports: - "80:80" # HTTP - "443:443" # HTTPS - "81:81" # Web-UI volumes: - /opt/npm/data:/data - /opt/npm/letsencrypt:/etc/letsencrypt ``` #### 5) NPM starten ```bash cd /opt/npm docker compose up -d docker ps ``` Wenn alles klappt, sollte in der Ausgabe ein Container **jc21/nginx-proxy-manager** mit Status *Up* erscheinen. 👉 *Screenshot geeignet: Terminalausgabe `docker ps`.* #### 6) Erste Anmeldung in der Weboberfläche Im Browser öffnen: ``` http://:81 ``` Standard-Zugangsdaten: - E-Mail: `admin@example.com` - Passwort: `changeme` Nach dem ersten Login wirst du aufgefordert, E-Mail und Passwort zu ändern. 👉 *Screenshot geeignet: Login-Maske der NPM-Weboberfläche.* ### Router konfigurieren Damit der Nginx Proxy Manager von außen erreichbar ist, müssen wir den Datenverkehr durch unseren Router leiten. Der Router ist das Tor ins Internet: alle Anfragen von außen landen dort zuerst und müssen an die richtige Stelle im Heimnetz weitergeleitet werden. Ohne diese Weiterleitungen würde niemand den Nginx Proxy Manager erreichen können. Und noch wichtiger: Let’s Encrypt könnte keine Zertifikate ausstellen, weil der Validierungsserver nicht bis zu unserem Container durchkommt. #### Portweiterleitungen einrichten Wir brauchen genau zwei Weiterleitungen: - **Port 80 (HTTP)** Wird für die Überprüfung und Ausstellung von Zertifikaten durch Let’s Encrypt benötigt. - **Port 443 (HTTPS)** Wird für den verschlüsselten Zugriff auf unsere Dienste genutzt. Beide Ports müssen auf die **interne IP-Adresse des NPM-Containers** zeigen. Wenn dein Container z. B. die IP `192.168.1.6` hat, dann stellst du im Router Folgendes ein: - Extern: Port 80 → Intern: 192.168.1.6:80 - Extern: Port 443 → Intern: 192.168.1.6:443 👉 *Screenshot geeignet: Router-Oberfläche mit eingerichteter Portweiterleitung.* #### Unterschied zwischen interner und externer Adresse - **Interne Adresse**: `192.168.x.x` (nur im Heimnetz sichtbar) - **Externe Adresse**: vom Provider zugeteilt, im Internet sichtbar (z. B. `87.123.45.67`) Von außen kommend sehen Besucher nur die **externe Adresse oder Domain**. Der Router muss die Anfrage an die richtige interne IP weitergeben – und genau dafür richten wir die Portweiterleitungen ein. #### DynDNS am Beispiel DuckDNS Eine einfache Möglichkeit, deine wechselnde IP-Adresse automatisch aktuell zu halten, ist der Dienst **DuckDNS.org**. DuckDNS ist kostenlos, arbeitet zuverlässig und eignet sich ideal für Homelabs. ##### Anmeldung 1. Gehe auf [https://www.duckdns.org](https://www.duckdns.org). 2. Melde dich mit einem bestehenden Account an (z. B. GitHub oder Google). 3. Nach dem Login kannst du dir einen eigenen Hostnamen anlegen, z. B. ``` meinserver.duckdns.org ``` 👉 *Screenshot geeignet: DuckDNS-Dashboard mit angelegtem Hostnamen.* ##### Funktionsweise Der von dir gewählte Hostname wird bei DuckDNS mit deiner aktuellen öffentlichen IP-Adresse verknüpft. Damit diese Zuordnung auch bei einer neuen IP weiter funktioniert, muss dein Router oder ein Update-Mechanismus die Daten regelmäßig an DuckDNS melden. Wie genau das geschieht, hängt von deinem Router und deiner Technik ab. DuckDNS zeigt dir nach der Anmeldung direkt an, wie du den Update-Mechanismus einrichten kannst – entweder über eine DynDNS-Option im Router oder über ein kleines Skript. ##### Beispiel im Tutorial Für unser Beispiel nutzen wir den Hostnamen `pihole.duckdns.org`. Dieser zeigt immer auf unsere aktuelle öffentliche IP und kann später im Nginx Proxy Manager als Zieladresse für Subdomains verwendet werden. > [!NOTE] > Auch wenn die Adresse von außen erreichbar ist, ist der eigentliche Pi-hole-Zugang mit Login geschützt. > Niemand kann ohne Passwort etwas verändern. > [!TIP] > Im **Premium-Teil** zeigen wir eine komfortable Möglichkeit, DuckDNS automatisch und ohne zusätzliche Handarbeit zu aktualisieren. #### Sicherheitshinweise - Öffne im Router wirklich nur **Port 80 und 443** - Andere Dienste im Heimnetz (z. B. Nextcloud oder Pi-hole) bleiben hinter dem Proxy geschützt - Der Nginx Proxy Manager wird zur zentralen Anlaufstelle - Sobald die Ports freigegeben sind, ist der NPM-Container von außen sichtbar – deshalb unbedingt im nächsten Schritt die Zugangsdaten ändern > [!WARNING] > Jede unnötige Portfreigabe ist ein zusätzliches Risiko. > Stelle sicher, dass wirklich nur die beiden benötigten Ports (80 und 443) nach außen offen sind. #### Test der Weiterleitung Nachdem die Portfreigaben gespeichert sind: 1. Prüfe deine aktuelle **öffentliche IP-Adresse** (z. B. über `https://whatismyipaddress.com`) 2. Öffne im Browser `http://<öffentliche-IP>` – du solltest eine Standard-Seite vom Nginx Proxy Manager sehen 3. Noch besser: nutze deine Domain oder DynDNS-Adresse und öffne `http://meinedomain.de` Wenn du eine Antwort bekommst, ist die Weiterleitung korrekt eingerichtet. Wenn nicht, prüfe: - Stimmt die interne Ziel-IP im Router? - Sind die Ports 80/443 eventuell noch von einem anderen Gerät belegt? - Hat dein Provider evtl. CGNAT oder DS-Lite aktiv (dann sind eingehende Verbindungen eingeschränkt)? > [!NOTE] > **IPv6 / DS-Lite** kann Probleme bereiten. Manche Internetanschlüsse verwenden **DS-Lite** (Dual-Stack Lite), bei dem **keine öffentliche IPv4-Adresse** vergeben wird, sondern du über ein IPv6-Tunneled-Netzwerk (Carrier-NAT) verbunden bist. > In so einem Fall funktioniert eine klassische Portweiterleitung auf IPv4 **nicht**, weil du gar keine öffentliche IPv4 hast. #### Was bedeutet das für NPM? - Dein Reverse Proxy (NPM) mag korrekt laufen und unter IPv6 erreichbar sein, doch viele Dienste oder Clients (Smartphones, Zuschauer, etc.) verwenden **nur IPv4**. - Daher kann es sein, dass trotz funktionierendem Setup **extern keine Verbindung möglich ist**, wenn keine IPv4-Adresse verfügbar ist. - Viele berichtete Fälle zeigen, dass Dienste bei DS-Lite über IPv6 erreichbar sind, aber IPv4-Geräte außen blockiert bleiben. [oai_citation:0‡Medium](https://oglimmer.medium.com/hosting-a-website-at-home-with-ds-lite-5e09fa473e0d?utm_source=chatgpt.com) - Eine mögliche Lösung ist, ein **externes Gateway oder Tunnel** zu nutzen, z. B. einen Server im Internet, der IPv4 annimmt und über IPv6 zum Heimnetz bridgt (z. B. Tools wie Pangolin). [oai_citation:1‡Deployn](https://deployn.de/en/blog/setup-pangolin/?utm_source=chatgpt.com) #### Hinweis für Nutzer - Wenn dein Anbieter DS-Lite nutzt und du **keine öffentliche IPv4-Adresse** hast, wirst du nicht mit dem klassischen NPM-Setup ins Internet kommen. - In diesem Fall steht dir nur **IPv6-Zugriff** zur Verfügung – vorausgesetzt, deine Domain und deine Geräte unterstützen IPv6. - Im **Premium-Tutorial** zeigen wir eine komfortable Tunnel- oder Relay-Lösung, damit dein System auch unter DS-Lite zuverlässig von außen erreichbar ist. > [!WARNING] > Wenn dein Anschluss DS-Lite nutzt, teste unbedingt früh, ob dein NPM über IPv4 erreichbar ist. > Sonst stehst du später vor einer Konfiguration, die intern funktioniert, aber extern nicht erreichbar ist. ### Ersteinrichtung Nginx Proxy Manager Nachdem der NPM-Container gestartet wurde und die Ports 80, 81 und 443 erreichbar sind, öffnen wir die Weboberfläche: ``` http://:81 ``` Beispiel: ``` http://192.168.1.6:81 ``` #### Erster Login Standard-Zugangsdaten: - **E-Mail:** `admin@example.com` - **Passwort:** `changeme` Beim ersten Login wirst du sofort aufgefordert: - eine gültige E-Mail-Adresse einzutragen (diese wird für Zertifikate und Benachrichtigungen genutzt) - ein neues, sicheres Passwort zu vergeben 👉 *Screenshot geeignet: Loginmaske mit Eingabe der Standarddaten.* #### Sprache einstellen In den Einstellungen kannst du die Sprache auf **Deutsch** umstellen. Das erleichtert die spätere Bedienung. 👉 *Screenshot geeignet: Dashboard mit geöffneten Einstellungen.* #### Benutzerverwaltung - Lege dir im nächsten Schritt einen eigenen Benutzer an. - Verteile Admin-Zugänge nur, wenn es wirklich nötig ist. - Für normale Nutzer kannst du eingeschränkte Rollen vergeben (z. B. nur Zugriff auf bestimmte Hosts). > [!WARNING] > Lasse den Standard-Admin-Account nicht bestehen. > Er ist bekannt und stellt ein Sicherheitsrisiko dar – auch dann, wenn du das Passwort änderst. #### Überblick im Dashboard Nach dem ersten Login siehst du das Dashboard: - Übersicht der eingerichteten Proxy Hosts - Status von Zertifikaten - Systeminformationen Hier ist im Moment noch alles leer – das ändern wir im nächsten Schritt, wenn wir den ersten Proxy Host einrichten. 👉 *Screenshot geeignet: NPM-Dashboard direkt nach der Ersteinrichtung.* ### Ersten Proxy Host anlegen (Pi-hole Dashboard) Nun richten wir den ersten Proxy Host im Nginx Proxy Manager ein. Als Beispiel nehmen wir das **Pi-hole Dashboard**, das im Container unter Port 80 läuft. #### 1) Proxy Host hinzufügen 1. Gehe im Dashboard auf **Hosts → Proxy Hosts**. 2. Klicke auf **Add Proxy Host**. 👉 *Screenshot geeignet: Proxy Hosts → Add Proxy Host.* #### 2) Domainname eintragen - **Domain Names**: Gib die Adresse ein, die du im DNS/DynDNS angelegt hast, z. B. ``` pihole.meinedomain.de ``` #### 3) Ziel im Heimnetz festlegen - **Scheme:** http - **Forward Hostname / IP:** interne IP des Pi-hole Containers (z. B. `192.168.1.5/admin`) - **Forward Port:** 80 Damit wird jede Anfrage an `pihole.meinedomain.de` automatisch direkt an die interne Adresse `192.168.1.5/admin` weitergegeben. 👉 *Screenshot geeignet: Eingabemaske mit Scheme, IP und Port.* #### 4) SSL-Zertifikat aktivieren - Gehe zum Tab **SSL** - Wähle **Request a new SSL Certificate** - Setze die Haken bei **Force SSL** und **HTTP/2 Support** - Akzeptiere die Let’s Encrypt Bedingungen Beim Speichern fragt NPM automatisch ein gültiges Zertifikat an. 👉 *Screenshot geeignet: SSL-Tab mit aktivierter Zertifikatsanfrage.* #### 5) Ergebnis prüfen - Öffne im Browser `https://pihole.meinedomain.de` - Du solltest direkt auf das Pi-hole Dashboard weitergeleitet werden. - Anmeldung wie gewohnt mit deinem Pi-hole Passwort. > [!TIP] > Da wir die interne Adresse direkt auf `/admin` setzen, musst du die Endung nicht mehr von Hand angeben – das Dashboard öffnet sofort. ### Troubleshooting & Tipps #### NPM-Weboberfläche nicht erreichbar Wenn du `http://:81` nicht aufrufen kannst, liegt das fast immer daran, dass der Container nicht läuft oder blockiert wird. - Prüfe zuerst, ob NPM läuft: ```bash docker ps ``` In der Liste muss der Container `jc21/nginx-proxy-manager` erscheinen und den Status **Up** haben. - Falls er nicht läuft: ```bash docker start ``` - Falls er gar nicht startet: Logs prüfen mit ```bash docker logs -f ``` - Wenn er läuft, aber kein Zugriff möglich ist: Prüfe im Proxmox-Webinterface, ob die Container-IP korrekt im Netzwerk eingebunden ist. 👉 *Screenshot geeignet: `docker ps` mit laufendem Container.* --- #### Kein Zertifikat von Let’s Encrypt Das häufigste Problem: **Port 80 oder 443 sind nicht von außen erreichbar.** - Prüfe die Portweiterleitung im Router. Beide Ports müssen auf die interne IP des NPM-Containers zeigen. - Test von außen (z. B. mit Handy im Mobilfunknetz): ```bash curl -I http://meinedomain.de ``` Wenn du keine Antwort bekommst, ist die Portweiterleitung falsch oder blockiert. - Prüfe, ob deine Domain/DynDNS auf die richtige IP zeigt: ```bash nslookup meinedomain.de ``` Stimmt die Ausgabe mit deiner öffentlichen IP überein (z. B. `87.x.x.x`)? - Wenn ja, liegt das Problem eher am Router oder Provider. - Falls du DS-Lite hast, bekommst du keine echte öffentliche IPv4 – dann schlägt die Validierung fehl. Lösungsmöglichkeiten erklären wir später im Premium-Bereich. --- #### Zugriff klappt nur intern Du kannst `http://192.168.1.6:81` aufrufen, aber nicht `http://meinedomain.de`? Dann kommt die Anfrage nicht bis in dein Heimnetz. Typische Ursachen: - Domain zeigt noch auf alte IP (DynDNS-Update prüfen). - Router hat Portfreigaben nicht korrekt gespeichert. - Manche Provider blockieren Port 80. In diesem Fall: versuche, Port 80 temporär auf einen anderen Dienst umzuleiten, um zu testen, ob überhaupt etwas von außen ankommt. --- #### SSL funktioniert, aber Browser warnt Manchmal stellt NPM zwar ein Zertifikat aus, aber der Browser meldet trotzdem „unsicher“. - Stelle sicher, dass du die Seite wirklich mit **https://** aufrufst. - Leere den Browser-Cache oder probiere ein anderes Gerät. - In NPM unter Proxy Host → SSL: aktiviere „Force SSL“. Dann wird jede Anfrage automatisch auf HTTPS umgeleitet. --- #### Pi-hole Dashboard nicht erreichbar Wenn du nur die Subdomain `pihole.meinedomain.de` eingetragen hast, landest du auf einer leeren Seite. Pi-hole erwartet den Aufruf unter `/admin`. - Lösung: In NPM beim Forward Hostname die Adresse mit `/admin` hinterlegen, z. B. `192.168.1.5/admin`. - Test direkt im Browser: ``` http://192.168.1.5/admin ``` --- #### Bekannte Einschränkungen - **IPv6:** Manche Router unterstützen Portweiterleitungen nur für IPv4. Dann musst du IPv6 im Heimnetz deaktivieren oder ausschließlich IPv4 nutzen. - **DS-Lite:** Wenn du keine öffentliche IPv4-Adresse hast, kannst du von außen nicht direkt auf NPM zugreifen. Lösungsmöglichkeiten (z. B. Tunnel oder externe Server) behandeln wir im Premium-Teil. --- > [!TIP] > Wenn du nicht weiterkommst, wirf einen Blick in die Logs des NPM-Containers: > ```bash > docker logs -f > ``` > Oft steht dort direkt, warum ein Zertifikat fehlschlägt oder ein Proxy Host nicht erreichbar ist. ## Ergebnis Mit dem Nginx Proxy Manager haben wir einen zentralen Reverse Proxy eingerichtet. Er steht nun als Schaltzentrale zwischen unserem Heimnetz und dem Internet und übernimmt folgende Aufgaben: - **Zentrale Verwaltung:** Alle Anfragen von außen laufen über NPM. - **Saubere Struktur:** Dienste werden nicht mehr über Ports wie `:8080` oder `:8443` erreicht, sondern über klare Subdomains (`cloud.meinedomain.de`, `pihole.meinedomain.de`). - **Sicherheit:** Nur die Ports 80 und 443 sind nach außen offen. Alle internen Dienste bleiben hinter NPM geschützt. - **Verschlüsselung:** Let’s Encrypt sorgt für automatische HTTPS-Zertifikate. - **Komfort:** Neue Proxy Hosts lassen sich einfach über die Weboberfläche hinzufügen. Damit haben wir die Grundlage geschaffen, alle weiteren Container im Homelab sicher und professionell nach außen erreichbar zu machen. 👉 *Screenshot geeignet: NPM-Dashboard mit erstem eingerichteten Proxy Host.* > [!TIP] > Ab diesem Punkt musst du für neue Dienste nur noch im NPM einen Proxy Host anlegen. > Jeder weitere Container wird so nahtlos eingebunden – sicher, verschlüsselt und mit klarer Adresse.