- README: step-by-step installation of web UI and agent on one host, exactly as tested (agent after keygen, all "run" helpers before "up -d", http PUBLIC_URL and TRUSTED_PROXY_HOPS=0 without a proxy) - README: attach to an existing Nginx Proxy Manager in Docker – shared network via docker-compose.override.yaml, no published port, gw_priority so SSH to the agent keeps the source address of the own network (otherwise from= rejects it), TLS settings, test - install.sh --docker: the new manual jail bans in INPUT and DOCKER-USER - Running container: helpers via "docker compose exec … python -m webui" (run fails with "Address already in use"); troubleshooting entries Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.1 KiB
Reverse Proxy
Der Container liefert reines HTTP auf Port 8080 (im Beispiel veröffentlicht als
127.0.0.1:8080). Davor gehört ein Reverse Proxy mit TLS; in der .env dazu setzen:
PUBLIC_URL=https://fail2ban.example.org
TRUSTED_PROXY_HOPS=1
Der Proxy muss Host unverändert weitergeben und X-Forwarded-For sowie X-Forwarded-Proto
setzen – alle Beispiele unten tun das. Den Zugriff am Proxy zusätzlich auf bekannte
IP-Adressen zu beschränken kostet wenig und ist dringend empfohlen.
Nginx Proxy Manager
Läuft NPM als Docker-Container auf demselben Host: die getestete Schritt-für-Schritt-Anleitung
steht im README (gemeinsames
Docker-Netz, kein veröffentlichter Port, gw_priority, Sperren in DOCKER-USER).
Für NPM auf einem anderen Host:
Hosts → Proxy Hosts → Add Proxy Host
| Feld | Wert |
|---|---|
| Domain Names | fail2ban.example.org |
| Scheme / Forward Hostname / Port | http · IP des Docker-Hosts (oder 127.0.0.1, wenn NPM im Host-Netzwerk läuft) · 8080 |
| Block Common Exploits | an |
| SSL | Zertifikat anfordern, Force SSL, HTTP/2, HSTS |
| Access List | optional: eine Access List mit deinen IP-Adressen (Satisfy any aus) |
Läuft NPM auf demselben Host in einem anderen Docker-Netz, den Port der Oberfläche an die
LAN-Adresse des Hosts binden (z. B. "192.168.1.10:8080:8080") oder die Oberfläche an das
Netz von NPM hängen und fail2ban-webui:8080 als Ziel verwenden.
Antwort-Header gehören nach Advanced → Custom Nginx Configuration; das NPM-Image enthält das Modul headers-more, das sie auch auf weitergeleitete Antworten anwendet:
more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains";
(CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy und Cache-Control
setzt die App selbst.)
Caddy
fail2ban.example.org {
@allowed remote_ip 203.0.113.0/24 2001:db8::/32
handle @allowed {
reverse_proxy 127.0.0.1:8080
}
respond 403
}
Caddy setzt X-Forwarded-For/-Proto automatisch.
Traefik (Docker-Labels)
Den Container an das Netz von Traefik hängen und Labels setzen, statt den Port zu veröffentlichen:
services:
fail2ban-webui:
# … as in the example compose file, without "ports:"
labels:
- traefik.enable=true
- traefik.http.routers.f2bwebui.rule=Host(`fail2ban.example.org`)
- traefik.http.routers.f2bwebui.entrypoints=websecure
- traefik.http.routers.f2bwebui.tls.certresolver=letsencrypt
- traefik.http.routers.f2bwebui.middlewares=f2bwebui-ipallow
- traefik.http.middlewares.f2bwebui-ipallow.ipallowlist.sourcerange=203.0.113.0/24
- traefik.http.services.f2bwebui.loadbalancer.server.port=8080
networks:
- fail2ban-webui.dockernetwork.local
- traefik
Traefik mit Authentik Forward Auth (Proxy-Modus)
- traefik.http.routers.f2bwebui.middlewares=authentik@docker
AUTH_MODE=proxy
AUTH_PROXY_HEADER=X-authentik-username
AUTH_PROXY_ALLOWED_IPS=<address of Traefik in the shared network>/32
AUTH_PROXY_LOGOUT_URL=https://fail2ban.example.org/outpost.goauthentik.io/sign_out
nginx
server {
listen 443 ssl;
http2 on;
server_name fail2ban.example.org;
ssl_certificate /etc/letsencrypt/live/fail2ban.example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fail2ban.example.org/privkey.pem;
allow 203.0.113.0/24;
deny all;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; # several slow agents can take a while
}
}
Prüfen
curl -sI https://fail2ban.example.org/login | grep -iE '^(HTTP|content-security|set-cookie)'
Erwartet werden HTTP/2 200, der Header Content-Security-Policy und ein Sitzungs-Cookie
mit Secure; HttpOnly; SameSite=Lax. Fehlt Secure am Cookie, beginnt PUBLIC_URL nicht
mit https://.