- 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>
7.3 KiB
Betrieb
Alle Befehle im Verzeichnis mit der docker-compose.yaml ausführen (z. B. /opt/fail2ban-webui).
Status und Logs
docker compose ps # Up … (healthy)
docker compose logs --tail 100 fail2ban-webui
docker compose logs -f fail2ban-webui | grep -E 'AUDIT|LOGIN|ERROR|WARNING'
docker compose exec fail2ban-webui python -m webui check # jeder Agent erreichbar?
Wichtige Logzeilen:
| Zeile | Bedeutung |
|---|---|
fail2ban-webui 1.0.0 – hosts: … – auth: … – loki: … – geoip: … |
Zusammenfassung beim Start |
AUDIT {…} |
Sperren/Entsperren mit Benutzer, Client-IP, Hosts und Ergebnis |
LOGIN_OK / LOGIN_FAILED / LOGIN_LOCKED / LOGOUT |
Anmeldeereignisse |
OIDC_FAILED / OIDC_DENIED |
SSO-Fehler / Konto nicht zugelassen |
Das Protokoll liegt zusätzlich in data/audit.log (ein JSON-Objekt pro Zeile):
tail -n 20 data/audit.log | python3 -m json.tool --json-lines
Auf den Hosts steht jede Agent-Aktion im Syslog:
journalctl -t f2b-webctl --since today
Update
cp -a .env docker-compose.yaml config /backups/fail2ban-webui_$(date +%F)/ # oder dein Backup-Ort
docker compose pull
docker compose up -d
docker compose ps
docker compose exec fail2ban-webui python -m webui check
Vorher das Changelog lesen – nennt es eine neue Agent-Version, auch die
Agenten aktualisieren (install.sh mit denselben Optionen erneut ausführen, siehe
agent.md). Der Tag 1 bewegt sich nur innerhalb von 1.x;
inkompatible Änderungen bekommen eine neue Hauptversion.
Auch ohne neue Funktionen regelmäßig neu ziehen bzw. bauen: Das Image wird mit aktuellen Debian-Sicherheitsupdates neu gebaut.
Backup
| Was | Warum |
|---|---|
.env |
Einstellungen, Passwort-Hash, OIDC-Secret |
config/hosts.yaml |
Hostliste |
data/ssh/ |
privater Schlüssel und festgelegte Host-Schlüssel – ohne sie braucht jeder Agent den neuen Schlüssel |
data/audit.log |
Protokoll |
data/secret_key |
hält nur Sitzungen gültig; geht er verloren, werden alle abgemeldet |
data/geoip/ wird automatisch neu heruntergeladen.
tar -cpzf /backups/fail2ban-webui_$(date +%F_%H-%M).tar.gz .env docker-compose.yaml config data
sha256sum /backups/fail2ban-webui_*.tar.gz | tail -n1
Das Archiv enthält den privaten SSH-Schlüssel – entsprechend sicher aufbewahren.
Umzug auf einen anderen Host
- Auf dem alten Host
docker compose stop, Archiv wie oben erstellen. - Kopieren, mit
tar -xpzfentpacken (behält Besitzer 10050 und Rechte). - Auf jedem Agenten die neue Adresse in
from=aufnehmen – am einfachsteninstall.sh … --from <neue Adresse>erneut ausführen. docker compose up -d, danachcheck.
SSH-Schlüssel tauschen
docker compose run --rm fail2ban-webui keygen --force
# auf jedem Host:
bash install.sh --key-file new.pub --from … (dieselben Optionen wie zuvor)
Der Installer ersetzt nur Einträge mit demselben Schlüssel; den alten vorher mit
uninstall.sh entfernen oder seine Zeile aus authorized_keys löschen (sie enthält
command="…f2b-webctl").
Login mit fail2ban absichern
Die Oberfläche sperrt einen Client nach 5 Fehlversuchen selbst. Um hartnäckige Angreifer an der Firewall zu sperren, liest fail2ban auf dem Proxy-Host das Container-Log.
/etc/fail2ban/filter.d/fail2ban-webui.conf
[Definition]
# Docker json-file log: {"log":"… WARNING webui: LOGIN_FAILED user=x ip=203.0.113.7\n",…}
# user names never contain spaces (they are sanitised), so only the real " ip=" matches
failregex = LOGIN_FAILED user=\S* ip=<HOST>
LOGIN_LOCKED ip=<HOST>
ignoreregex =
/etc/fail2ban/jail.d/fail2ban-webui.local
[fail2ban-webui]
enabled = true
filter = fail2ban-webui
backend = polling
logpath = /var/lib/docker/containers/*/*-json.log
maxretry = 5
findtime = 1h
bantime = 1d
# the proxy runs in Docker? Then ban in the DOCKER-USER chain:
# banaction = iptables-allports[chain=DOCKER-USER]
fail2ban-client reload
fail2ban-regex /var/lib/docker/containers/*/*-json.log /etc/fail2ban/filter.d/fail2ban-webui.conf
Das funktioniert nur, wenn der Container die echte Client-Adresse sieht (TRUSTED_PROXY_HOPS
richtig gesetzt). Benutzernamen werden mit ersetzten Leer- und Steuerzeichen protokolliert;
ein präparierter Benutzername kann also keine zweite Logzeile einschleusen.
Fehlersuche
| Symptom | Ursache / Lösung |
|---|---|
curl: command not found / git: command not found |
frisches Minimal-System (z. B. LXC-Template) → apt install -y curl git |
failed to set up container networking: Address already in use |
docker compose run … bei laufendem Dienst – die feste IP ist belegt → docker compose exec fail2ban-webui python -m webui <befehl> |
Permission denied (publickey) nur hinter NPM |
Container hängt in zwei Netzen und verbindet mit der Adresse aus dem NPM-Netz → gw_priority: 1 am eigenen Netz, siehe README |
docker: 'compose' is not a docker command |
nur das eigenständige docker-compose vorhanden → apt install -y docker-compose-plugin |
Container beendet sich: … is not writable for UID 10050 |
chown -R 10050:10050 data |
Container beendet sich: AUTH_MODE=local needs AUTH_PASSWORD_HASH |
hash-password ausführen, Zeile mit einfachen Anführungszeichen einfügen |
Container beendet sich: No hosts configured |
config/hosts.yaml fehlt oder ist leer; unter Windows/Docker Desktop: das Laufwerk lässt sich nicht einbinden |
| Anmeldung scheitert immer, nachdem der Hash eingefügt wurde | einfache Anführungszeichen in der .env fehlen – Compose hat die $-Teile verschluckt |
| Alle werden gemeinsam gesperrt / Protokoll zeigt die Proxy-IP | TRUSTED_PROXY_HOPS nicht gesetzt |
Host key verification failed |
Host nicht in known_hosts oder sein Schlüssel hat sich geändert → keyscan, Fingerprints vergleichen |
Permission denied (publickey) |
Schlüssel für diesen Benutzer nicht installiert, falsches user: in hosts.yaml, falsches from= (die Adresse, die der Host sieht!) oder sshd liest diese authorized_keys-Datei nicht |
sudo: a password is required |
sudo-Regel fehlt → install.sh erneut ausführen |
The agent does not run as root |
Forced-Command ohne sudo -n für einen Nicht-root-Benutzer → install.sh erneut ausführen |
Timeout talking to … |
Firewall/Port, oder der Host ist langsam – SSH_TIMEOUT erhöhen |
The jail manual-block does not exist on this host |
mit --no-jail oder einem anderen --manual-jail installiert; MANUAL_JAIL in /etc/f2b-webctl.conf prüfen |
| Sperren haben keine Start-/Endzeit | fail2ban älter als 0.11 (kein --with-time) |
| Gesperrte IP erreicht trotzdem einen Docker-Dienst | Banaction sperrt nur INPUT – siehe Docker-Hosts |
OIDC: redirect_uri passt nicht |
Provider muss genau <PUBLIC_URL>/auth/callback erlauben |
OIDC: mismatching_state |
Sitzungs-Cookie zwischen Weiterleitung und Callback verloren: Host in PUBLIC_URL weicht vom Browser ab, oder https ohne Secure/Proxy-Header |
| OIDC: „Konto … darf diese Anwendung nicht verwenden" | Benutzer nicht in OIDC_ALLOWED_GROUPS; prüfen, ob der Provider den Claim groups mitschickt |