NGINX Proxy Manager in Docker installieren

Wenn du den NGINX Proxy Manager in Docker installieren möchtest, bekommst du damit einen angenehm einfachen Reverse Proxy mit Weboberfläche, SSL-Zertifikaten und Proxy Hosts ohne manuelles Gefummel in Nginx-Konfigurationsdateien. Genau das macht das Tool so praktisch: Du kannst mehrere Dienste sauber über Domains erreichbar machen, ohne jedes Mal Portakrobatik auf dem Server zu betreiben.

Ich habe die Installation für diesen Beitrag einmal frisch auf einer Testkiste nachgespielt. Erst die Ports 80, 81 und 443 freigemacht und den Stack per Docker Compose gestartet. Kurz gesagt: Läuft. Und zwar angenehm unspektakulär, was bei Infrastruktur meistens die beste Art von Lob ist.

🧭 Was ist NGINX Proxy Manager?

NGINX Proxy Manager ist eine Weboberfläche für Reverse Proxy Setups. Im Hintergrund arbeitet Nginx, vorne bekommst du aber eine Oberfläche, über die du Proxy Hosts, Weiterleitungen, Streams, Zugriffsbeschränkungen und SSL-Zertifikate verwalten kannst.

Das ist besonders praktisch, wenn auf deinem Server mehrere Webdienste laufen. Statt jeden Dienst direkt mit einem eigenen öffentlichen Port ins Internet zu stellen, leitest du deine Domains zentral über den Proxy Manager weiter.

  • Port 80 nimmt normale HTTP-Anfragen entgegen.
  • Port 443 ist für HTTPS zuständig.
  • Port 81 öffnet die Admin-Oberfläche von NGINX Proxy Manager.

Gerade im Homelab, auf einem VPS oder bei kleinen Selfhosting-Setups ist das eine sehr angenehme Lösung. Du musst trotzdem wissen, was du tust. Aber du musst nicht jeden Abend mit Nginx-Direktiven kuscheln. Auch schön.

🧩 Voraussetzungen

Bevor es losgeht, brauchst du eine funktionierende Docker-Umgebung inklusive Docker Compose. Außerdem sollten die Ports 80, 81 und 443 auf dem Host frei sein.

Wenn du Docker noch nicht installiert hast, findest du hier eine Schritt-für-Schritt-Anleitung, wie du das auf Ubuntu mit einem Script erledigst:

Sobald Docker läuft, kann es direkt weitergehen.

⚙️ NGINX Proxy Manager Docker Compose vorbereiten

Ich nutze hier eine schlanke Variante mit SQLite. Für viele private Setups und kleinere Installationen reicht das völlig aus. Wenn du sehr viele Einträge, Benutzer oder eine größere Umgebung betreibst, kannst du NGINX Proxy Manager auch mit MariaDB oder PostgreSQL betreiben. Für den Start ist SQLite aber angenehm einfach.

Verzeichnis und Netzwerk anlegen

Ich lege für solche Stacks gerne ein eigenes Verzeichnis und ein eigenes Docker-Netzwerk an. Das macht es später einfacher, weitere Container an den Proxy Manager anzubinden.

mkdir -p /opt/nginx-proxy-manager
cd /opt/nginx-proxy-manager

docker network create npm.dockernetwork.local

Wenn das Netzwerk bereits existiert, bekommst du natürlich eine entsprechende Meldung. Dann ist alles gut und du kannst weitermachen.

docker-compose.yml erstellen

Jetzt erstellst du die Datei docker-compose.yml. Das folgende Beispiel nutzt das offizielle Image jc21/nginx-proxy-manager und setzt direkt einen initialen Admin-Benutzer.

Wichtig: Das Kennwort im Beispiel ist nur ein Beispiel. Bitte ändere es vor dem Start.

services:
  npm-app:
    image: jc21/nginx-proxy-manager:2.15.1
    container_name: npm-app
    hostname: npm-app
    restart: unless-stopped
    environment:
      TZ: Europe/Berlin
      DISABLE_IPV6: "true"
      INITIAL_ADMIN_EMAIL: admin@example.com
      INITIAL_ADMIN_PASSWORD: Cq8tQx4mV7nB2sLp
    ports:
      - "80:80"
      - "81:81"
      - "443:443"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    networks:
      - npm.dockernetwork.local

networks:
  npm.dockernetwork.local:
    external: true

Die beiden Volumes sind wichtig. Unter ./data landen unter anderem die Datenbank und Nginx-Konfigurationen. Unter ./letsencrypt werden die Zertifikate gespeichert.

Die Variablen INITIAL_ADMIN_EMAIL und INITIAL_ADMIN_PASSWORD sind bei aktuellen Versionen praktisch, weil damit beim ersten Start automatisch ein Admin-Benutzer angelegt wird. Ohne diese Werte erscheint beim ersten Aufruf der Oberfläche ein Setup-Assistent.

Container starten

Danach startest du den Stack:

docker compose pull
docker compose up -d

Nach ein paar Sekunden kannst du prüfen, ob der Container läuft:

docker compose ps
docker compose logs -f

In meinem Test wurde beim ersten Start die SQLite-Datenbank angelegt, ein JWT-Schlüsselpaar erzeugt und der Admin-Benutzer aus den Umgebungsvariablen erstellt. Danach lauschte die Oberfläche sauber auf Port 81.

🔐 Erster Login

Die Admin-Oberfläche erreichst du anschließend im Browser über:

http://deine-server-ip:81

Wenn du das Compose-Beispiel oben unverändert übernommen hast, meldest du dich mit diesen Daten an:

  • E-Mail: admin@example.com
  • Kennwort: Cq8tQx4mV7nB2sLp

Bitte ändere die Zugangsdaten direkt nach dem Login. Für einen produktiven Server würde ich außerdem Port 81 nicht offen ins Internet stellen. Entweder nur per VPN erreichbar machen, per Firewall einschränken oder später selbst über einen eigenen Proxy Host absichern.

🌐 Ersten Proxy Host anlegen

Jetzt kommt der eigentliche Punkt: Du möchtest einen Dienst über eine Domain erreichbar machen. Dafür brauchst du zuerst einen DNS-Eintrag, der auf deinen Server zeigt. Meist ist das ein A-Record für IPv4 und optional ein AAAA-Record für IPv6.

In NGINX Proxy Manager gehst du dann auf Hosts und Proxy Hosts. Dort legst du einen neuen Eintrag an.

  • Domain Names: deine Domain, zum Beispiel app.example.com
  • Scheme: meistens http, wenn der Dienst intern unverschlüsselt läuft
  • Forward Hostname / IP: die interne IP oder der Containername
  • Forward Port: der interne Port des Dienstes
  • Block Common Exploits: kann man in vielen Fällen aktivieren
  • Websockets Support: aktivieren, wenn die Anwendung WebSockets nutzt

Wenn dein Dienst ebenfalls in Docker läuft und im gleichen Docker-Netzwerk hängt, kannst du als Forward Host einfach den Containernamen verwenden. Genau das habe ich im Test gemacht: Ein kleiner Nginx-Testcontainer hing im gleichen Netzwerk und NGINX Proxy Manager hat ihn direkt per Containername erreicht.

Container ohne extra Portfreigabe anbinden

Ein großer Vorteil: Deine eigentliche Anwendung muss nicht zwingend einen Port auf dem Host veröffentlichen. Es reicht, wenn sie im gleichen Docker-Netzwerk wie NGINX Proxy Manager liegt.

services:
  deine-app:
    image: nginx:alpine
    container_name: deine-app
    restart: unless-stopped
    networks:
      - npm.dockernetwork.local

networks:
  npm.dockernetwork.local:
    external: true

Im Proxy Host trägst du dann als Ziel deine-app und Port 80 ein. Nach außen sind weiterhin nur 80 und 443 vom Proxy Manager relevant.

🔒 SSL mit Let’s Encrypt

Für HTTPS wechselst du im Proxy Host auf den Reiter SSL. Dort kannst du ein neues Let’s-Encrypt-Zertifikat anfordern. Dafür müssen die Domain und die öffentliche Erreichbarkeit stimmen.

  • Die Domain muss auf deinen Server zeigen.
  • Port 80 muss von außen erreichbar sein.
  • Port 443 sollte ebenfalls auf den Server zeigen.
  • Eine vorgeschaltete Firewall darf die Anfrage nicht blockieren.

Wenn das passt, setzt du den Haken bei Force SSL. Optional kannst du auch HTTP/2 und HSTS aktivieren. Bei HSTS solltest du aber wissen, was du tust, weil Browser sich die HTTPS-Pflicht merken. Das ist gut, solange alles stimmt. Wenn nicht, wird es schnell pädagogisch wertvoll.

🧯 Typische Stolperfallen

Die Installation selbst ist einfach. Die Probleme liegen meistens drum herum: Ports, DNS, Firewall oder Docker-Netzwerke. Hier sind die Punkte, die ich zuerst prüfen würde.

Ports sind bereits belegt

Wenn der Container nicht startet, sind häufig Port 80, 81 oder 443 schon belegt. Prüfen kannst du das zum Beispiel so:

ss -tulpen | grep -E ':80|:81|:443'

Auf einem Server sollte es nur einen Dienst geben, der direkt auf 80 und 443 lauscht. In diesem Setup ist das NGINX Proxy Manager.

Zertifikat wird nicht ausgestellt

Wenn Let’s Encrypt scheitert, prüfe zuerst DNS und Erreichbarkeit. Zeigt die Domain wirklich auf die richtige IP? Kommt Port 80 von außen beim Server an? Läuft vielleicht noch ein anderer Reverse Proxy davor?

Ein schneller Test von außerhalb hilft oft mehr als zehn Vermutungen von innen.

Admin-Port offen im Internet

Port 81 ist bequem, aber nicht unbedingt etwas, das jeder im Internet sehen muss. Ich würde den Zugriff einschränken. Per Firewall, VPN oder später über einen eigenen Host mit zusätzlicher Absicherung.

Docker-Container wird nicht erreicht

Wenn du als Forward Host einen Containernamen nutzt, müssen beide Container im gleichen Docker-Netzwerk hängen. Das kannst du so prüfen:

docker network inspect npm.dockernetwork.local

Wenn dein Zielcontainer dort nicht auftaucht, kann NGINX Proxy Manager ihn auch nicht per Namen finden.

✅ Fazit

NGINX Proxy Manager ist eines dieser Tools, die einem im Alltag erstaunlich viel Kleinkram abnehmen. Du bekommst eine Oberfläche, Let’s Encrypt, Proxy Hosts und eine saubere zentrale Stelle für deine Webdienste.

Für mich passt das besonders gut auf kleine VPS-Systeme, Homelab-Server und Docker-Hosts, auf denen mehrere Dienste laufen. Die Installation ist schnell erledigt. Wichtig ist nur, dass du Ports, DNS und Firewall sauber im Griff hast.

Dann ist der Rest angenehm unspektakulär. Und genau so mag ich Infrastruktur.

👥 Techniverse Community

Lust auf Austausch rund um Matrix, Selfhosting und andere smarte IT-Lösungen?
In der Techniverse Community triffst du Gleichgesinnte, kannst Fragen stellen oder einfach nerdigen Talk genießen. 🚀

👉 Jetzt der Gruppe auf Matrix beitreten
~ Direkte Raumadresse: #community:techniverse.net

👉 Für lockere Gespräche abseits der Kernthemen komm in den Talkraum
~ Direkte Raumadresse: #talk:techniverse.net

Wir freuen uns, wenn du dabei bist!

Vielen Dank fürs Teilen!