Zertifikate für den Hausgebrauch

Im vorherigen Beitrag habe ich Pi-Hole in hoch verfügbarer Form installiert und meinen DHCP-Server vom Magenta Router in den Ruhestand geschickt. In diesem Beitrag kommt nun Nginx Proxy Manager (NPM) dran. Der aufmerksame Leser dieser Seite wird bemerkt haben, dass ich ansonsten gerne Caddy verwende. Caddy ist zwar ein wirklich einfach zu benutzender Reverse Proxy, aber für den kompletten Komfort muss man zumindest Port 80 aufmachen. Damit habe ich bei einem VPS nicht so große Probleme, aber beim Heimnetz möchte ich dann doch alles gesperrt lassen. Daher werde ich DNS-01 mit Wildcard Zertifikat verwenden und das hat bei mir mit Caddy einfach nicht funktionieren wollen, mit NPM jedoch schon.

Ich habe zuerst versucht NPM mit einem Proxmox Community Skript zu installieren aber das hat nur zu Problemen geführt und ich bin dann erst recht wieder bei Docker Container gelandet, wer will kann gleich dorthin springen, ansonsten hier der Versuch mit dem Community Skript.

Nginx Proxy Manager als LXC

Mithilfe von Proxmox Community Scripts folgenden Befehl in der Proxmox Host Shell ausführen:

bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/nginxproxymanager.sh)"

Der Code vom Skript.

Passwort und Container ID setzen, sowie Hostnamen. Dann Speichergröße (4GB), CPU-Kerne (2 Kerne) und RAM (1GB) festlegen. Als Network Bridge verwende ich die Host-Bridge:

Statische IP-Adresse setzen:

Und Gateway:

APT-Cache wird nicht benötigt und wenn man kein IPv6 verwendet kann man es auch deaktivieren (auch wenn es in Zukunft relevanter werden wird und irgendwann wird man wohl eher IPv4 deaktivieren). Die MTU-Size kann man leer lassen.

Search Domain, entweder auf Host belassen oder manuell festlegen:

Selbes gilt für den DNS-Server. MAC-Adresse kann man auch automatisch generieren lassen und VLAN, sofern man es in Verwendung hat, was bei einem Heimserver-Setup vielleicht nicht unbedingt der Fall sein muss. Die Tags habe ich ausgeschaltet dafür aber gleich den Public SSH-Schlüssel hinterlegt:

Root-Zugriff nur erlauben, wenn man einen SSH-Schlüssel hinterlegt hat:

Für den Nginx Proxy Manager braucht man keine FUSE-Unterstützung, kann man also auf nein lassen:

Ich verwende immer den Verbose Mode, damit man auch sieht was sich tut während der Installation:

Bestätigen und auch das Konfig-File speichern:

Hier etwas eigenartig:

Die alte Version sollte man keinesfalls installieren, das Model o3 meint dazu (Quelle):

Das hat mich jetzt ausreichend frustriert, so dass ich mir diesen Ansatz spare und doch wieder Docker Container verwenden werde.

Nginx Prox Manager mit Docker Compose in unprivilegierten LXC installieren

Dafür klone ich mein Docker-LXC-Template:

passwd
adduser npm-user
groupadd docker
usermod -aG docker npm-user
apt update
apt upgrade
chown -R npm-user:npm-user /opt
su npm-user
cd /opt
nano docker-compose.yml

Hier ist die Dokumentation und das docker-compose.yml-File:

services:
  npm:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginx-proxy-manager
    restart: unless-stopped
    ports:
      # These ports are in format <host-port>:<container-port>
      - '80:80' # Public HTTP Port
      - '443:443' # Public HTTPS Port
      - '81:81' # Admin Web Port
      # Add any other Stream port you want to expose
      # - '21:21' # FTP
 
    # environment:
      # Uncomment this if you want to change the location of
      # the SQLite DB file within the container
      # DB_SQLITE_FILE: "/data/database.sqlite"
 
      # Uncomment this if IPv6 is not enabled on your host
      # DISABLE_IPV6: 'true'
 
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
docker compose up -d

Seite mit Port 81 aufrufen:

Und mit admin@example.com und Passwort changeme anmelden und gleich ändern.

Wildcard Zertifikat erstellen

Einen guten Überblick bietet dieser Beitrag, aber statt DuckDNS verbinden wir uns direkt mit dem API-Zugang vom Hostinganbieter. Bei mir ist das Netcup und da ist es wichtig, dass man bei der SSL-Zertifikatserstellung 900 Sekunden Wartezeit eingibt, denn mit der Standardzeit geht es sich nicht aus und NPM spuckt dann nur Fehler aus.

Dann warten und einen Kaffee holen:

Nach etwa einiger Wartezeit (bei Netcup sind 900 Sekunden) erscheint das erfolgreiche Zertifikat in NPM:

Das Wildcard-Zertifikat ist aktiv und gültig bis April 2026.

Zertifikat verwenden

Jetzt kann man das Zertifikat für beliebige Services unter eigener Subdomain, wie Proxmox UI, Pi-Hole, Gitea, Home Assistant, Jellyfin, und was auch immer man möchte, verwenden.

Damit das Werkl auch läuft müssen die Subdomains in Pi-Hole als Local DNS Records angelegt werden, damit sie intern zur richtigen IP-Adresse auflösen. Das geht im Pi-Hole WebUI unter Local DNS und dann DNS Records:

A-Records für direkte IP-Zuordnung und damit auch SSH:

pihole1.h.domain.com  →  192.168.1.10
npm.h.domain.com      →  192.168.1.11
pve.h.domain.com      →  192.168.1.12

CNAME-Records brauchen wir als Alias auf einen anderen Hostnamen:

pve-ui.h.domain.com    →  npm.h.domain.com
dashboard.h.domain.com   →  npm.h.domain.com

Damit lösen alle Subdomains intern auf und NPM leitet sie per Reverse Proxy an die entsprechenden Services weiter. Die Zweigleisigkeit mit pve.h.domain.com und pve-ui.h.domain.com braucht es, damit sowohl Browser Zugriff als auch SSH mit dem Domainnamen.

Der Test: HTTPS funktioniert!

Browser öffnen, eine Subdomain aufrufen und die sichere Seite samt eigenen Zertifikat bewundern:

Das Schloss-Symbol zeigt: Verbindung ist sicher, Zertifikat von Let’s Encrypt verifiziert.

Fazit

Mit Nginx Proxy Manager und DNS-01 Challenge funktioniert das Wildcard-Zertifikat einwandfrei, ganz ohne Port 80/443 nach außen öffnen zu müssen.

Jetzt haben wir ein Wildcard-Zertifikat für alle Subdomains auf einmal. Wenn ein neuer Service dazukommt, zwei Einträge in Pi-Hole und dann einen in NPM und schon hat man eine schöne private Domain ohne Browser-Warnungen. Das wird übrigens auch für Pull-Backups unter TrueNAS benötigt.

Es war nicht ganz einfach alles aufzusetzen und ich habe auch in Summe 1-2 Jahre gebraucht, bis ich auf diese Lösung gekommen bin. Mit dieser Anleitung sollte es aber für Interessierte einfacher sein auch zu einem funktionalen Setup zu kommen!

Im nächsten Beitrag geht es weiter mit Crowdsec für zusätzliche Sicherheit am Reverse Proxy.