🧪 Tech-Lab & How-To Base von Sebastian Teßmann • Zu den Produktivservices: tessmann-digital.de

📚 Archiv

Supply Chain Security: Docker-Updates absichern mit Trivy und Watchtower CVE-2026-98432: Warum ein Kernel-Update allein nicht reicht (und echtes System-Hardening) Home Assistant vs. Alexa: Das echte Smart Home (inkl. Pi-Setup, HACS & FRITZ!Box) Zero-Day abgewehrt: Die Anatomie der PHP-Lücke (CVE-2026-109618) und der ultimative Docker-Schutz Zero-Bloat Hosting: Nginx Proxy Manager, Apache & Fail2ban sicher unter Docker vereinen Checkmk Community Edition auf Debian 13: Der ultimative Guide (Installation, Distributed Monitoring, Custom Plugins & Gotify) Debian 13 vs. Windows Server im Enterprise-Einsatz: Performance, Härtung & Top 20 CLI-Befehle Cyberkrieg gegen den Mittelstand: Unsere Migration auf Proxmox, OPNsense & Zero-Trust Open Source vs. Payware: Der ehrliche Vergleich für KMU & IT-Infrastrukturen Bye-bye VMware: Mein Weg über Hyper-V zu Proxmox VE Tutorial: High-Performance Cloud mit Seafile auf Debian 13 & Proxmox VE Tutorial: Portainer EE auf CE downgraden & sicherer Host-Umzug Tutorial: CorePlan via Docker deployen (HTTPS out-of-the-box) Tutorial: Eigenes Docker Image bauen (Apache, PHP, Auto-SSL & HTTP zu HTTPS Redirect) Proxmox Unified Console (PUC): Das All-in-One Dashboard für PVE, PBS & PMG Eigener Bitcoin Solo Pool: Full Node (bitcoind), public-pool Backend & individuelles PHP-Dashboard im Docker-Stack OPNsense: HAProxy als Reverse Proxy mit Let's Encrypt SSL-Offloading & SNI / ACL-Routing Mobiles Arbeiten & Kanzlei-Zugriff: WireGuard VPN auf der FRITZ!Box, Windows & iPhone inkl. NAS-SMB-Mount Tschüss Windows, hallo Pinguin: Der ehrliche Leitfaden für den Linux-Umstieg (und warum CachyOS mein Gaming rettete) Eigener Bitcoin Solo-Mining-Pool: Public-Pool & Pruned Full Node im Docker-Homelab Gaming auf Linux: Kompletter Umstieg von Windows zu CachyOS (Kernel, Steam, Heroic & MangoHud) Docker Container absichern: Rootless, Read-Only Filesystems & Linux Capabilities Portainer CE auf Docker: Schritt-für-Schritt Setup mit persistenten Volumes & Hardening Docker Engine & Compose V2 auf Debian/Ubuntu: Saubere Installation via Official Repository E-Mail Deliverability: SPF, DKIM & DMARC richtig konfigurieren (Schritt-für-Schritt) Proxmox VE & OPNsense: IPv6 /64 Subnetting (/80 WAN Transit & /96 LAN Segmentierung) OPNsense auf Proxmox VE: Vollständiges Setup von ISO-Download bis Hardening & DNSmasq Proxmox VE auf Debian 12 (Bookworm) installieren & Routed Network (vmbr0/vmbr1) einrichten

Zero-Bloat Hosting: Nginx Proxy Manager, Apache & Fail2ban sicher unter Docker vereinen

Nginx Proxy Manager, Apache und Fail2ban Docker Setup

In der modernen IT-Infrastruktur gilt ein ungeschriebenes Gesetz: Exponiere niemals Dienste direkt ins Internet, wenn es nicht zwingend notwendig ist. Wer jeden einzelnen Webserver, jede API und jedes Tool einzeln mit dem Netz verbindet, verliert nicht nur den Überblick über Zertifikate, sondern öffnet Angreifern Tür und Tor.

Die Lösung für dieses Problem ist ein Reverse Proxy. In diesem Artikel bauen wir eine absolute "Zero-Bloat"-Architektur auf einer reinen Debian-13-Basis auf. Wir nutzen den Nginx Proxy Manager (NPM) als zentrales, verschlüsseltes Eingangstor, schirmen einen dahinterliegenden Apache-Webserver komplett vom öffentlichen Netz ab und härten das gesamte System mit Fail2ban auf dem Host-Betriebssystem.


1. Die Vorbereitung: DNS und Portweiterleitung

Bevor wir auf der Kommandozeile starten, muss die Infrastruktur auf Netzwerkebene vorbereitet werden. Der Server soll später unter einer echten Domain (z. B. app.deine-domain.de) erreichbar sein.

  • DNS-Eintrag: Lege bei deinem Domain-Provider einen A-Record für deine Subdomain an, der auf die öffentliche IP-Adresse deines Servers oder Routers zeigt.
  • Portweiterleitung (Firewall/Router): Damit der NPM von außen erreichbar ist und Let's Encrypt Zertifikate ausstellen kann, müssen exakt zwei Ports an die interne IP-Adresse deines Docker-Hosts (Debian 13) weitergeleitet werden:
    • Port 80 (TCP) → HTTP (Zwingend für die ACME-Challenge von Let's Encrypt)
    • Port 443 (TCP) → HTTPS (Der verschlüsselte Traffic)

Mehr wird nach außen nicht geöffnet. Auch Port 81 (das NPM Admin-Interface) bleibt aus Sicherheitsgründen idealerweise nur über ein internes VPN oder einen SSH-Tunnel erreichbar.


2. Die Architektur: Docker-Compose mit isoliertem Netzwerk

Der größte Sicherheitsvorteil von Docker sind isolierte Netzwerke (Bridge Networks). Unser Ziel: Der Nginx Proxy Manager und der Apache-Container laufen im selben virtuellen Netzwerk. Der Apache-Container veröffentlicht dabei keine eigenen Ports auf den Host! Er kommuniziert ausschließlich intern mit dem NPM.

Erstelle ein Verzeichnis (z. B. /opt/docker-hosting) und darin folgende docker-compose.yml:

version: '3.8'

services:
  # Nginx Proxy Manager
  npm:
    image: jc21/nginx-proxy-manager:latest
    container_name: npm_manager
    restart: always
    ports:
      - "80:80"
      - "443:443"
      - "127.0.0.1:81:81" # Admin-Interface nur lokal (localhost) erreichbar
    environment:
      DB_SQLITE_FILE: "/data/database.sqlite"
    volumes:
      - ./npm/data:/data
      - ./npm/letsencrypt:/etc/letsencrypt
    networks:
      - internal_web

  # Apache Webserver (Die eigentliche Applikation)
  apache_app:
    image: php:8.2-apache
    container_name: web_apache
    restart: always
    # KEIN "ports" Block! Dieser Container ist von außen unsichtbar.
    volumes:
      - ./apache/www:/var/www/html
      - ./apache/logs:/var/log/apache2
    networks:
      - internal_web

networks:
  internal_web:
    name: internal_web_network
    driver: bridge
        

Starte das Setup mit docker-compose up -d. NPM und Apache laufen nun. Da wir das NPM-Interface an 127.0.0.1:81 gebunden haben, loggen wir uns per SSH-Port-Forwarding sicher ein:
ssh -L 8081:localhost:81 root@dein-server-ip
Danach kannst du das Interface lokal in deinem Browser unter http://localhost:8081 aufrufen.


3. Nginx Proxy Manager: Ersteinrichtung und SSL (Let's Encrypt)

Die Standard-Anmeldedaten für NPM lauten admin@example.com und changeme. Ändere diese sofort nach dem ersten Login!

Nun binden wir unseren unsichtbaren Apache-Container an unsere Domain an und verpassen ihm ein SSL-Zertifikat:

  1. Klicke auf Hosts → Proxy Hosts → Add Proxy Host.
  2. Details Tab:
    • Domain Names: app.deine-domain.de
    • Scheme: http
    • Forward Hostname / IP: web_apache (Genial: Durch das Docker-Netzwerk können wir einfach den Container-Namen statt einer IP nutzen!)
    • Forward Port: 80
    • Aktiviere Block Common Exploits.
  3. SSL Tab:
    • Wähle im Dropdown Request a new SSL Certificate.
    • Aktiviere Force SSL (leitet alle HTTP-Anfragen automatisch auf HTTPS um).
    • Akzeptiere die Let's Encrypt Bedingungen und klicke auf Save.

Fertig! Der NPM generiert nun das Zertifikat. Ruft ein Nutzer https://app.deine-domain.de auf, entschlüsselt NPM den Traffic und leitet ihn intern unverschlüsselt an den Apache weiter. Der Apache muss sich nie wieder mit Zertifikaten herumschlagen.


4. Die Meisterklasse: Fail2ban auf dem Host (inkl. Docker-Bypass-Fix)

Docker ist fantastisch, hat aber ein massives Problem mit traditionellen Firewalls. Docker nutzt iptables-Regeln in der PREROUTING-Chain. Das bedeutet: Wenn Fail2ban eine bösartige IP standardmäßig in der INPUT-Chain blockiert, interessiert das Docker überhaupt nicht – der Traffic wird trotzdem an den Container weitergeleitet.

Die Lösung? Wir weisen Fail2ban an, die IPs in die spezielle DOCKER-USER Chain zu schreiben. Diese wird ausgeführt, bevor das Port-Forwarding greift.

Schritt 1: Fail2ban auf Debian 13 installieren

apt install fail2ban -y

Schritt 2: Die NPM Filter-Regel erstellen
Wir erstellen eine Regex, die nach fehlerhaften Login-Versuchen im NPM sucht. Erstelle die Datei /etc/fail2ban/filter.d/npm-docker.conf:

[Definition]
failregex = ^.*\[error\].* <HOST> - - \[.*\] ".*" (401|403|404|444) .*$
ignoreregex =
        

Schritt 3: Die Fail2ban Jail konfigurieren
Erstelle (oder bearbeite) die Datei /etc/fail2ban/jail.local. Hier konfigurieren wir den entscheidenden Fix für die DOCKER-USER Chain:

[DEFAULT]
# Der entscheidende Befehl: Nutze die DOCKER-USER Chain für Blockaden!
banaction = iptables-allports[name=%(__name__)s, chain=DOCKER-USER]

[npm-docker]
enabled = true
filter = npm-docker
# Pfad zu deinen NPM-Logs aus der docker-compose.yml (Volume-Mapping beachten)
logpath = /opt/docker-hosting/npm/data/logs/default-host_*.log
          /opt/docker-hosting/npm/data/logs/proxy-host-*.log
maxretry = 4
findtime = 600
bantime = 3600
        

Info: Da der NPM vor dem Apache hängt, sieht der Apache-Container meist nur die interne IP des Proxy-Managers. Daher ist es deutlich effektiver, die Access- und Error-Logs des NPM (proxy-host-logs) direkt auf dem Host via Fail2ban zu überwachen, da hier noch die echte, externe IP-Adresse des Angreifers vorliegt.

Schritt 4: Fail2ban neustarten

systemctl restart fail2ban

Wenn nun ein Bot versucht, deine Webanwendungen mit Scans zu bombardieren (z. B. fehlerhafte Logins, 404-Scans nach wp-admin), liest Fail2ban das Logfile des NPM aus und blockt die IP-Adresse hart auf der Host-Firewall, noch bevor das Paket überhaupt den Docker-Daemon erreicht.


Fazit

Mit dieser Architektur hast du ein extrem performantes und sicheres Setup. Der Nginx Proxy Manager übernimmt zentral die Verschlüsselung und das Routing, dein Apache-Server arbeitet unbelastet und geschützt in einem isolierten Netzwerk, und Fail2ban wehrt Brute-Force-Angriffe zuverlässig ab, ohne von Dockers Netzwerk-Routing ausgehebelt zu werden. Wahre digitale Souveränität ohne unnötigen Software-Ballast!

Ihre sichere IT-Infrastruktur aus einer Hand

Suchen Sie einen verlässlichen Partner für das Hosting und die Absicherung Ihrer Unternehmensanwendungen? Ob Proxmox, Docker oder maßgeschneiderte Sicherheitskonzepte – wir unterstützen Sie beim Aufbau einer souveränen, DSGVO-konformen IT.

Jetzt Tessmann Digital kontaktieren →