Rewrite the documentation part 1

This commit is contained in:
2026-02-14 00:14:43 +01:00
parent 85a286e3be
commit c18f753fdb
8 changed files with 543 additions and 1175 deletions

29
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,29 @@
# Contributing
Thanks for contributing. This project is security-adjacent; changes should be deliberate and easy to review.
## Basic workflow
1. Fork the repository and create a feature branch:
```bash
git checkout -b feature/<name>
```
2. Make changes with well described commits. (Run formatting and basic checks.)
3. Open a pull request:
* Describe what changed and why
* Include screenshots for UI changes
* Include migration notes if you changed configuration/DB behavior
## Coding and review expectations
* Prefer readable code over "clever code".
* Keep public-facing behavior documented (docs or inline help).
* Do not introduce new external network calls by default; make them opt-in where possible.
* For changes affecting auth or callback handling, include a short threat-model note in the PR description.
## Reporting security issues
If you believe you found a security issue, please do not open a public issue. Use a private disclosure channel appropriate for the project (for example, contact Swissmakers GmbH via website) and provide reproduction steps and impact assessment.

1258
README.md

File diff suppressed because it is too large Load Diff

62
docs/api.md Normal file
View File

@@ -0,0 +1,62 @@
# API reference (summary)
This is a short index for operators. The UI primarily uses these endpoints. Paths and details may evolve; treat this as a practical reference.
## Authentication
- When OIDC is enabled, most `/api/*` endpoints require an authenticated session.
- Callback endpoints are authenticated using `X-Callback-Secret`.
## Common headers
- `X-F2B-Server: <server-id>`
Used by the UI to select the target server in multi-server setups (where applicable).
## Endpoints
Server management
- `GET /api/servers`
- `POST /api/servers`
- `DELETE /api/servers/:id`
- `POST /api/servers/:id/test`
Jails and configuration
- `GET /api/summary`
- `GET /api/jails/manage`
- `POST /api/jails/manage`
- `GET /api/jails/:jail/config`
- `POST /api/jails/:jail/config`
- `POST /api/jails/:jail/unban/:ip`
- `POST /api/jails/:jail/ban/:ip`
Events and analytics
- `GET /api/events/bans`
- `GET /api/events/bans/stats`
- `GET /api/events/bans/insights`
Settings
- `GET /api/settings`
- `POST /api/settings`
- `POST /api/settings/test-email`
Filter debugging
- `GET /api/filters`
- `POST /api/filters/test`
Service control
- `POST /api/fail2ban/restart`
Callbacks (Fail2Ban actions)
- `POST /api/ban`
- `POST /api/unban`
Callbacks require:
- Header: `X-Callback-Secret: <secret>`
- JSON body fields (typical): `serverId`, `ip`, `jail`, `hostname`, `failures`, `logs`
Authentication routes (OIDC)
- `GET /auth/login`
- `GET /auth/callback`
- `GET /auth/logout`
- `GET /auth/status`
- `GET /auth/user`

32
docs/architecture.md Normal file
View File

@@ -0,0 +1,32 @@
# Architecture overview
Fail2Ban UI consists of :
- a Go HTTP API (Gin)
- a single-template web frontend (with static assets)
- an embedded SQLite database for state and event history
- optional integrations (Email, GeoIP/Whois, firewalls)
## Data flows
1) User -> UI -> API
- Browser communicates with the backend via HTTP and WebSocket.
- When OIDC is enabled, most UI routes require authentication.
2) Fail2Ban host -> UI callbacks
- A custom Fail2Ban action posts ban/unban events to the UI.
- The UI validates the callback secret, enriches (optional), stores, and broadcasts events.
3) UI -> Fail2Ban host (management operations)
- Local: uses the Fail2Ban socket and local filesystem.
- SSH: runs `fail2ban-client` and manages files via SSH.
- Agent (preview): HTTP-based control plane (limited, in progress).
## Components (high level)
- REST API: server management, jail/filter config read/write, ban/unban actions, settings
- WebSocket hub: streams ban/unban events and (optional) debug console logs
- Storage: server definitions, settings, ban history, permanent block records
Additional resources:
- Container deployment guide: `deployment/container/README.md`
- systemd setup guide: `deployment/systemd/README.md`

94
docs/configuration.md Normal file
View File

@@ -0,0 +1,94 @@
# Configuration reference
This document describes common runtime settings. Some values are stored in the database via the UI; environment variables take precedence where noted.
## Network settings
- `PORT`
TCP port for the HTTP server (default: 8080).
- `BIND_ADDRESS`
Bind address for the HTTP server (default: `0.0.0.0`). Use `127.0.0.1` if you only publish through a reverse proxy on the same host.
Example:
```bash
-e PORT=3080 -e BIND_ADDRESS=127.0.0.1
````
## Callback URL and secret (Fail2Ban -> UI)
Fail2Ban UI receives ban/unban callbacks at:
* `POST /api/ban`
* `POST /api/unban`
The callback action on each managed Fail2Ban host must be able to reach the UI callback URL.
* `CALLBACK_URL`
The external URL that Fail2Ban hosts use for callbacks.
Default behavior typically matches `http://127.0.0.1:<PORT>` (works for same-host deployments).
* `CALLBACK_SECRET`
Shared secret for authenticating callbacks. If not set, the UI generates one on first start.
Recommended: set a fixed secret in production and keep it private.
Example (container bridge / remote hosts):
```bash
-e CALLBACK_URL=http://10.88.0.1:3080 \
-e CALLBACK_SECRET='replace-with-a-random-secret'
```
Callbacks must include:
* Header `X-Callback-Secret: <secret>`
## Privacy-related settings
* `DISABLE_EXTERNAL_IP_LOOKUP=true`
Disables any external lookup used to display the hosts public IP address in the UI.
* `UPDATE_CHECK=false`
Disables checking GitHub for a newer release.
## Fail2Ban config migration
* `JAIL_AUTOMIGRATION=true`
Experimental: attempts to migrate a monolithic `jail.local` into `jail.d/`.
Recommended: migrate manually on production systems.
## Email template selection
* `emailStyle=classic`
Switches back alert emails from the modern template to the classic template.
## OIDC authentication
OIDC can protect the UI with an external identity provider.
Required:
* `OIDC_ENABLED=true`
* `OIDC_PROVIDER=keycloak|authentik|pocketid`
* `OIDC_ISSUER_URL=...`
* `OIDC_CLIENT_ID=...`
* `OIDC_CLIENT_SECRET=...`
* `OIDC_REDIRECT_URL=https://<ui-host>/auth/callback`
Optional (common):
* `OIDC_SCOPES=openid,profile,email`
* `OIDC_SESSION_SECRET=<32+ bytes recommended>` (random is generated if omitted)
* `OIDC_SESSION_MAX_AGE=3600`
* `OIDC_USERNAME_CLAIM=preferred_username`
* `OIDC_SKIP_VERIFY=false` (development only)
* `OIDC_SKIP_LOGINPAGE=false`
Provider notes:
* Keycloak: ensure your client allows the redirect URI (`/auth/callback`) and post-logout redirect (`/auth/login`).
* Authentik/Pocket-ID: follow their OIDC client configuration and match the redirect URI exactly.
Additional resources:
* OIDC dev environment: `development/oidc/README.md`

83
docs/installation.md Normal file
View File

@@ -0,0 +1,83 @@
# Installation
This document provides a short installation path and points to the full deployment guides in the repository.
Spoiler: They need to be reworked as well we already did with the main files here..
## Supported platforms
Fail2Ban UI targets Linux hosts. Typical environments include RHEL/Rocky/Alma, Debian/Ubuntu, and container environments in general.
## Container deployment
Additional resources:
- Full guide: `deployment/container/README.md`
- SELinux policies: `deployment/container/SELinux/`
### Option A: Pre-built image
Local connector example (Fail2Ban runs on the same host):
```bash
podman pull swissmakers/fail2ban-ui:latest
podman run -d --name fail2ban-ui --network=host \
-v /opt/fail2ban-ui:/config:Z \
-v /etc/fail2ban:/etc/fail2ban:Z \
-v /var/run/fail2ban:/var/run/fail2ban \
-v /var/log:/var/log:ro \
swissmakers/fail2ban-ui:latest
````
Notes:
* `/config` stores the SQLite DB, settings, and SSH keys used by the UI.
* `/var/log` is used for log path tests and should be mounted read-only to the container.
### Option B: Docker Compose
Use one of the examples and adapt to your environment:
```bash
cp docker-compose.example.yml docker-compose.yml
# or
cp docker-compose-allinone.example.yml docker-compose.yml
podman compose up -d
```
You can also start and test the full dev-stacks from the development folders, it you only want to try it out.
### Option C: Build the image yourself
```bash
git clone https://github.com/swissmakers/fail2ban-ui.git
cd fail2ban-ui
podman build -t fail2ban-ui:dev .
podman run -d --name fail2ban-ui --network=host \
-v /opt/fail2ban-ui:/config:Z \
-v /etc/fail2ban:/etc/fail2ban:Z \
-v /var/run/fail2ban:/var/run/fail2ban \
-v /var/log:/var/log:ro \
localhost/fail2ban-ui:dev
```
## systemd deployment (standalone)
Additional resources:
* Full guide: `deployment/systemd/README.md`
High-level procedure:
```bash
git clone https://github.com/swissmakers/fail2ban-ui.git /opt/fail2ban-ui
cd /opt/fail2ban-ui
# Build static CSS assets
./build-tailwind.sh
# Build the go-binery
go build -o fail2ban-ui ./cmd/server/main.go
```
Then follow `deployment/systemd/README.md` to install the unit file and configure permissions.

54
docs/security.md Normal file
View File

@@ -0,0 +1,54 @@
# Security guidance
This project can perform security-sensitive operations (bans, configuration changes). Deploy it as you would deploy every other administrative interface.
## Recommended deployment posture
- Do not expose the UI directly to the Internet.
- Prefer one of:
- VPN-only access
- Reverse proxy with strict allowlists
- OIDC enabled (in addition to network controls)
If you must publish it, put it behind TLS and an authentication layer, and restrict source IPs.
## Callback endpoint protection
The fail2ban callback endpoints (`/api/ban`, `/api/unban`) are only reachable with a correct `CALLBACK_SECRET`. This secret must be atleast 20 characters long. If not specified a secure secret, will be automatically genereated on first start. It can be further protected by:
- Use even a stronger `CALLBACK_SECRET` than our default (32 characters)
- Make network restrictions (only allow known Fail2Ban hosts to reach the callback endpoint)
Rotate the secret if you suspect leakage.
## SSH connector hardening
For SSH-managed hosts:
- Use a dedicated service account (not a human user).
- Require key-based auth.
- Restrict sudo to the minimum set of commands required to operate Fail2Ban (typically `fail2ban-client` and optionally `systemctl restart fail2ban`).
- Use filesystem ACLs for `/etc/fail2ban` rather than broad permissions to allow full modification capabilities for the specific user.
## Least privilege and file access
Local connector deployments typically require access to:
- `/var/run/fail2ban/fail2ban.sock`
- `/etc/fail2ban/`
- selected log paths (read-only, mounted to same place inside the container, where they are on the host.)
Avoid running with more privileges than necessary. If you run in a container, use the repository deployment guide and SELinux policies.
## SELinux
If SELinux is enabled, use the policies provided in (according to your specific setup they are not enough):
- `deployment/container/SELinux/`
Do not disable SELinux as a shortcut. Fix always labeling and policy issues instead. -> Everytime you read "to disable SELinux" you can close that guide :)
## Audit and operational practices
- Back up `/config` (DB + settings) regularly.
- Treat the database as sensitive operational data.
- Keep the host and container runtime patched.
- Review Fail2Ban actions deployed to managed hosts as part of change control.

106
docs/troubleshooting.md Normal file
View File

@@ -0,0 +1,106 @@
# Troubleshooting
## UI not reachable
Check:
- Container/service is running
- Host firewall allows the configured port
- Reverse proxy forwards correctly (if used)
- Firewalld port allowed?
Examples:
```bash
podman ps
podman logs fail2ban-ui
# systemd:
systemctl status fail2ban-ui
journalctl -u fail2ban-ui -f
# firewalld:
firewall-cmd --list-all
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload
````
## Local connector fails
Check:
* Fail2Ban is running and socket exists
* Container has the socket mounted
* Permissions allow access to the socket
* SELinux problems
Examples:
```bash
systemctl status fail2ban
ls -la /var/run/fail2ban/fail2ban.sock
fail2ban-client status
# check the socked in the container:
podman exec -it fail2ban-ui ls -la /var/run/fail2ban/fail2ban.sock
# SELinux check for alerts (needs "setroubleshoot" linux package):
sealert -a /var/log/audit/audit.log
```
## SSH connector fails
Check:
* Key-based SSH works outside the UI
* Service account exists and has required sudo / facl permissions
* ACLs also allow modifications under `/etc/fail2ban`
Examples:
```bash
ssh -i ~/.ssh/<key> <user>@<host>
sudo -l -U <user>
getfacl /etc/fail2ban
# Connect manually from the fail2ban-UI connector to the remote host: (this example uses the "development/ssh_and_local" dev stack)
sudo podman exec -it fail2ban-ui ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -i /config/.ssh/id_rsa -p 2222 testuser@127.0.0.1
```
## Bans fail due to firewall backend (nftables / firewalld)
Symptoms often mention `iptables (nf_tables)` or action startup errors.
Fix:
* Use Fail2Ban banactions matching your host firewall backend:
* firewalld (use on Rocky / Red Hat / Almalinux): `firewallcmd-rich-rules`, `firewallcmd-allports`
* nftables: `nftables-multiport`, `nftables-allports`
* legacy iptables: `iptables-multiport`, `iptables-allports`
## OIDC login problems
Check:
* Issuer URL is correct and reachable
* Redirect URI matches exactly: `https://<host>/auth/callback`
* Provider client configuration includes post-logout redirect to `https://<host>/auth/login`
Logs:
```bash
podman logs fail2ban-ui
# Also enable debug logging over env or over the webUI
```
## Database issues
Check:
* `/config` is writable by the container/service user
* SQLite file permissions are correct
Example:
```bash
ls -la /opt/fail2ban-ui
sqlite3 /opt/fail2ban-ui/fail2ban-ui.db "PRAGMA integrity_check;"