Skip to content

NGINX Proxy-Manager & Portainer

Portainer ist in der Welt der Containerisierung immer beliebter geworden. NGINX ist ebenfalls ein beliebter Webserver.
Leider ist NGINX für unerfahrene Linux-Benutzer etwas komplizierter. Auch die neusten Sicherheitsstandards sind nicht immer nachzuhalten.

NGINX Proxy Manager ist ein Docker-Image, welches die Einrichtungen von Web-Hosts in NGINX erleichtert, sogar ganz abnimmt.
Lediglich den Hostname sowie den Port sollte man wissen. Zertifikate werden mittels LetsEncrypt generiert, was es absolut kostenfrei macht, auch SSL zu verwenden.

NGINX Proxy Manager hat einige Vor- und Nachteile.
Zum einen ist die Einrichtung nun wie gesagt kinderleicht, zum anderen ist es aber nicht mehr möglich, einfache HTML-Seiten ohne weiteres darzustellen.
Wer dennoch statische Seiten anbieten möchte, kann einen static-file-server als Docker Container nutzen. Später dazu mehr.
NGINX lässt sich so nur noch mit Proxies verwenden, sprich mit Docker-Containern die Dienste per HTTP anbieten.

Deshalb ist auch die Kombination mittels Portainer so perfekt, wodurch hier alles ineinander greift.


Vorraussetzungen

  • Docker und Docker-Compose
  • Texteditor in Linux
  • Linux System (Ubuntu oder Debian) 64-Bit oder Raspian

Installation von Portainer

Portainer empfiehlt sich mittels Docker-Compose einzurichten, welches die Wartung später spielend vereinfacht.
Zunächst müssen wir einen Ordner für Portainer erstellen.

cd /opt/
mkdir portainer
cd portainer

Danach wird mittels eines beliebigen Text-Editors die Datei ‚docker-compose.yml‘ angelegt. Ich nutze hier gerne „Nano“. nano docker-compose.yml

Wir fügen dann folgendes in die Datei ein:

version: "3" 
services: 
 portainer: 
   image: portainer/portainer-ce:latest
   volumes: 
      - ./data:/data 
      - /var/run/docker.sock:/var/run/docker.sock 
   restart: unless-stopped 
   networks: 
      - npm 

networks: 
 npm:

Hier weisen wir direkt das Docker-Netzwerk „npm“ an, sowie die Einbindung für das Verzeichnis  „data“ und des Docker-Sockets.
Das Data-Verzeichnis ist die Speicherung für die Systemdaten von Portainer. Den Docker-Socket braucht Portainer um alles von Docker abzurufen, Container zu erstellen usw.

Das Netzwerk „npm“ wird später für den Nginx-Proxy-Manager genutzt.
Es dient dazu, die Dienste durch NPM zu erreichen, ohne dass IPs genutzt werden müssen. Der Name des Dienstes reicht dann vollkommen aus.

Portainer lässt sich mittels ‚docker-compose up -d‘ herunterladen und starten.
Das Netzwerk sollte beim ersten start direkt mit erstellt werden, den Container für Portainer ebenfalls.

Die Einrichtung für Portainer lässt sich nach der Installation von NPM durchführen. Wir vermeiden hier nur die Freigabe des Ports 9000 für Portainer.

 

Installation von NPM

NPM ließe sich zwar auch direkt in Portainer einrichten, so sparen wir uns aber die Freigabe des Ports 9000 und können sicherstellen, dass der Webserver auch startet, falls Portainer gerade nicht will.

Selbes Spiel also auch für NPM.

cd /opt/
mkdir nginx-proxymanager
cd nginx-proxymanager

Danach wieder eine Datei mittels einem Editor erstellen ’nano docker-compose.yml‘:

version: "2.1" 
services: 
 npm-app: 
   image: 'jc21/nginx-proxy-manager:latest' 
   restart: unless-stopped 
   ports: 
     # These ports are in format <host-port>:<container-port> 
     - '85.10.200.190:80:80' # Public HTTP Port 
     - '85.10.200.190:443:443' # Public HTTPS Port 
     - '85.10.200.190:81:81' # Admin Web Port ### Sollte später entfernt werden ###
     # - '21:21' # FTP 
   healthcheck: 
     test: ["CMD", "/bin/check-health"] 
     interval: 10s 
     timeout: 3s 
   environment: 
     DB_MYSQL_HOST: "npm-db" 
     DB_MYSQL_PORT: 3306 
     DB_MYSQL_USER: "npm" 
     DB_MYSQL_PASSWORD: "npm" 
     DB_MYSQL_NAME: "npm" 
     # Uncomment this if IPv6 is not enabled on your host 
     #DISABLE_IPV6: 'true' 
   volumes: 
     - ./data:/data 
     - ./letsencrypt:/etc/letsencrypt 
   depends_on: 
     - npm-db 
   networks: 
     npm: 

 npm-db:    image: 'jc21/mariadb-aria:latest'
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 'npm'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
    volumes:
      - ./mysql:/var/lib/mysql    networks: 
      - npm 

networks: 
 npm: 
  external: true 

Das offizielle Docker-Compose Template für NPM nutzt hier nicht mariadb, sondern mariadb-aria. Leider hat es bei mir einige Fehler verursacht, was auch mit der im Template verwendeten Ordner-Hirachie zusammenhing. Nach einer Neuinstallation ging es allerdings wieder, weshalb ich hier auch nur die offizielle Version anbieten werde.

Hier auch wieder das Netzwerk npm, welches wir nutzen damit nicht alles freigeschaltet wird.
Um den Container zu starten, ist hier auch wieder ‚docker-compose up -d‘ auszuführen.

Um die Einrichtung nun abzuschließen, gehen wir nun zu…

 

Einrichtung von NPM

Um den NGINX-Proxymanager nun einzurichten, geht man auf IP:81, wobei IP durch die IP-Adresse (oder Domain) des eigenen Servers ersetzt werden muss.

Die standardmäßigen Benutzerdaten sind „admin@example.com“ und „changeme“ als Passwort.
Nach dem anmelden werdet ihr gebeten, dass Passwort, die E-Mail Adresse und den Nutzernamen anzupassen.

Aus Sicherheitstechnischen Gründen empfhielt es sich, nicht ‚admin‘ als Benutzername zu verwenden, sondern sowas wie „fridolin“, da ‚admin‘ und ‚root‘ die meist genutzten Nutzernamen sind. Dies erhöht die Dauer eines Bruteforce-Angriffes enorm.

Es ist außerdem ratsam das Passwort noch einmal zu ändern, sobald das Zertifikat für NPM eingerichtet ist. Ohne HTTPS ist es möglich die Benutzerdaten mitzuschneiden.

Nach der Grundeinrichtung gehen wir zu „SSL Certificates“ und erstellen ein neues Zeritifkat für die gewünschte Domain, welche für NPM dienen soll.

Bei den Domain-Names lassen sich natürlich auch direkt mehrere eingeben, ich bevorzuge es allerdings bestimmte Gruppierungen vorzunehmen.
Bei mir ist beispielsweise Portainer und NPM auf einem Zertifikat. Sprich „pt.gaminggeneration.de“ und „npm.gaminggeneration.de“.

Danach muss die E-Mail Adresse des Eigentümers eingegeben werden, welche für LetsEncrypt gilt. An diese werden Ablauf-Benachrichtigungen gesendet.

Wenn das Zertifikat erfolgreich beantragt und hinzugefügt ist, gehen wir zu „Proxy Hosts“ und erstellen einen neuen z.B. wie folgt:

Beim Reiter „SSL“ muss jetzt noch das richtige Zertifikat ausgewählt werden. Außerdem empfiehlt es sich, Force SSL, HTTP/2 Support sowie HSTS Enabled zu aktivieren. Force SSL erzwingt https anstatt http, HTTP2 ist etwas schneller und sicherer als HTTP1.0. HSTS verhindert, dass der Browser ungültige Zertifikate akzeptiert.

 

Sobald der Host aktiviert ist, können wir direkt auf den Host gehen. Wir sollten nun auf die NPM Admin Seite gelangen, an der wir auch gerade den Proxy-Host eingerichtet haben. Hier empfehle ich das Passwort über die HTTPS Seite nochmal zu ändern.

Danach können wir nochmal in die docker-compose.yml von NPM gehen und den Port 81:81 bei „ports“ entfernen.
Dies verhindert, dass die HTTP-Schnittstelle nach außen ohne HTTPS verfügbar ist. NPM sichert sich jetzt quasi selbst ab.

 

Einrichtung Portainer

Portainer muss zunächst mit den selben schritten in NPM eingerichtet werden.
Zunächst legen wir ein Zertifikat an, falls nicht bereits eins erstellt wurde.

Danach einene neuen Proxy-Host.
Bei „Forward Hostname / IP“ kommt hier ‚portainer‚ in das Feld. Der Port ist 9000.
Bitte hier auch HSTS sowie Force SSL aktivieren, um den Sicherheitsstandards zu entsprechen. – mit Portainer sollte man hier nicht spaßen.

Nun können wir Portainer auch über die Domain erreichen, welche wir in den Proxy-Host eingegeben haben.
Die Ersteinrichtung erfolgt jetzt wie von Portainer gewollt über SSL. Hier Benutzernamen und Passwort festlegen und den ersten Container oder Stack einrichten.

 

Jetzt sollte alles vollständig eingerichtet sein.
Wer neue Hosts hinzufügen möchte und diese in NPM einbinden möchte, kann einfach den Namen des „services“ eingeben und den Port.
Eine Freigabe mittels „ports“ ist nicht nötig, da diese nun über NPM „proxied“ werden.

Ein Beispiel mit dem static-file-server folgt im Anschluss.

 

Statische Dateien bereitstellen

Wer gerne statische Dateien anzeigen lassen möchte, einen Download-Bereich einrichten will oder anderweitig Dateien bereitstellen will, kann einen static-file-server in einem Docker-Container nutzen.

Zunächst gehen wir in Portainer auf Stacks. Von dort aus erstellen wir einen neuen Stack und nennen ihn beispielsweise „static-file-server“.
Für das Compose-File sehen wir folgendes vor:

version: "3.1"

networks:
npm:
external: true

services:
static-file-server:
restart: always
image: halverneus/static-file-server:latest
environment:
SHOW_LISTING: false
PORT: 80
DEBUG: true
volumes:
- /opt/static-file-server/:/web
networks:
- npm

Wie hier schon in dem Compose-File angedeutet, müssen wir noch das Verzeichnis „static-file-server“ unter „opt“ anlegen. Sprich mkdir /opt/static-file-server

Wer möchte das Dateiauflistung in Verzeichnissen ohne index.html aktiviert ist, kann die Umgebungsvariable „SHOW_LISTING“ auf ‚true‘ setzen.
Wie man sich bereits denken hätte können, müssen wir den Dienst nun in NPM hinzufügen. Der „IP Forward“ ist hier wieder der Name des services. Sprich ’static-file-server‘, wie im Docker-Compose File zu erkennen. Der Port ist wie aus der Umgebungsvariable zu lesen „80“.

Alle Dateien für den Webserver liegen nun unter /opt/static-file-server. Optional kann hier auch /var/www/html angegeben werden, das ist völlig egal.

Nach der Einbindung in NPM und des „Deployen“ des Stacks sollte der Dienst schon online sein.
Nun können wir also auch mit ’nur Docker‘ statische Dateien zu verfügung stellen. – Gleichzeitig haben wir nun gelernt wie wir neue Stacks in Portainer anlegen und die Dienste in NPM hinzufügen.

 

Vielen Dank fürs Lesen!

Avatar

Hey! - Ich bin Tobias Hopp, 20 Jahre alt und entwickele in meiner Freizeit gerne das ein oder andere Projekt.
Git: https://git.gaminggeneration.de/TobiasH

Sidebar