Initial version of fail2ban-webui

Web interface to view, ban and unban fail2ban IPs on several hosts via
SSH, generalised from the private f2b-web tool.

- Web UI (Flask/Waitress): hosts.yaml, local/OIDC/proxy authentication,
  English/German UI, origin map, optional Loki/Grafana/GeoIP, CLI helpers
- Agent f2b-webctl with install.sh/uninstall.sh (dedicated user + sudo,
  from= restriction, protected networks, manual jail)
- Hardened Docker image, examples, documentation, smoke test, testbed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
schiwagoaandClaude Opus 5.5 committed 2026-10-25 15:38:17 +01:00
commit 2e3f79236c
44 files changed
+4280

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
# fail2ban-webui
A small, self-hosted web interface to **view, ban and unban fail2ban IPs on several hosts** –
bare metal, VMs, LXC containers or Docker hosts.
- One page for all hosts: current bans per jail, origin (GeoIP) with a world map, search and filters
- Ban an IP permanently on any selection of hosts, unban per jail or everywhere
- Audit log of every action (who, when, from where)
- Optional: log history per IP from **Loki**, links into **Grafana**
- Sign-in with a local user, **OpenID Connect** (e.g. Authentik) or your reverse proxy
- English and German UI, more languages via one JSON file
- Runs as a hardened container (read-only, no capabilities, non-root), `amd64` and `arm64`
```
Browser ──HTTPS──▶ reverse proxy ──▶ fail2ban-webui (Docker)
│ SSH, one restricted key
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
host A (bare) LXC container Docker host
f2b-webctl f2b-webctl f2b-webctl
fail2ban fail2ban fail2ban
```
The web UI never gets a shell on your hosts. Every host runs a tiny agent,
[`f2b-webctl`](agent/f2b-webctl), as SSH *forced command*. It only knows
`list`, `ban <ip>`, `unban <jail> <ip>`, `unban-all <ip>` and `version`, refuses to ban
private networks, the host's own addresses or anything on its protected list, and logs
every action to syslog. Access to the fail2ban socket would be equivalent to root –
the agent is the security boundary, not the web UI.
## Quick start
```bash
mkdir -p /opt/fail2ban-webui/{config,data} && cd /opt/fail2ban-webui
curl -fsSLo docker-compose.yaml https://git.retronerd.at/schiwagoa/fail2ban-webui/raw/branch/main/examples/docker-compose.yaml
curl -fsSLo .env https://git.retronerd.at/schiwagoa/fail2ban-webui/raw/branch/main/examples/.env.example
curl -fsSLo config/hosts.yaml https://git.retronerd.at/schiwagoa/fail2ban-webui/raw/branch/main/examples/hosts.yaml.example
chown -R 10050:10050 data
docker compose run --rm -it fail2ban-webui hash-password # paste the line into .env
docker compose run --rm fail2ban-webui keygen # public key for the agents
# on every fail2ban host: install the agent (docs/agent.md), then:
docker compose run --rm -it fail2ban-webui keyscan
docker compose run --rm fail2ban-webui check
docker compose up -d
```
The UI listens on `127.0.0.1:8080` – put a reverse proxy with TLS in front of it.
## Documentation
| | |
|---|---|
| [Installation](docs/installation.md) | web UI step by step, from `mkdir` to the first login |
| [Agent](docs/agent.md) | installing `f2b-webctl` on bare metal, LXC and Docker hosts |
| [Configuration](docs/configuration.md) | every setting in `.env` and `hosts.yaml` |
| [Authentication](docs/authentication.md) | local login, OpenID Connect (Authentik), reverse-proxy auth |
| [Reverse proxy](docs/reverse-proxy.md) | Nginx Proxy Manager, Caddy, Traefik, nginx |
| [Operations](docs/operations.md) | logs, updates, backups, troubleshooting |
| [Development](docs/development.md) | local testbed, tests, adding a language |
| [Security](SECURITY.md) | security model and reporting vulnerabilities |
## Requirements
- Web UI: Docker with Compose v2, `amd64` or `arm64`
- Every fail2ban host: fail2ban ≥ 0.11 (start/end times need `--with-time`), `python3`,
`sshd`, `sudo` (or a root key), `bash`
## License
[MIT](LICENSE). IP geolocation by [DB-IP Lite](https://db-ip.com) (CC BY 4.0), downloaded
only when `GEOIP_AUTO_DOWNLOAD=1`. World map from [Natural Earth](https://www.naturalearthdata.com)
(public domain), bundled with the app.
---
<p align="center">
🏰 <a href="https://retronerd.at">Website</a> ·
🐘 <a href="https://social.retronerd.at/@schiwagoa">Mastodon</a> ·
🔒 <a href="https://retronerd.at/datenschutzerklaerung/">Datenschutz</a> ·
💬 <a href="https://helpdesk.retronerd.at/open.php">Support</a>
</p>
<p align="center">
<img src="https://dl.retronerd.at/Bilder/cat-footer.png" alt="" width="100%">
</p>
<p align="center">© Thomas Werner Schwaighofer · retronerd.AT · <a href="LICENSE">MIT Lizenz</a></p>