
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-Recordfü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:
- Klicke auf Hosts → Proxy Hosts → Add Proxy Host.
- 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.
- Domain Names:
- 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 →
💬 Feedback & Diskussion 0
Kommentar hinterlassen
Noch keine Kommentare zu diesem Guide vorhanden. Sei der Erste!