Files
fail2ban-webui/docs/configuration.md
T
schiwagoaandClaude Opus 5.5 2e3f79236c 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>
2026-10-25 15:38:17 +01:00

6.1 KiB
Raw Blame History

Configuration

The web UI is configured with environment variables (.env, loaded via env_file:) and the host list config/hosts.yaml. A complete, commented template is examples/.env.example. Changes need docker compose up -d (which recreates the container).

Values containing $ (password hashes, some secrets) must be wrapped in single quotes in .env, otherwise Docker Compose expands them.

Hosts – config/hosts.yaml

hosts:
  - name: web01               # shown in the UI: letters, digits, . _ -
    address: web01.example.org  # DNS name or IP, reachable from the container
    port: 22                  # optional, default 22
    user: f2bweb              # optional, default SSH_USER

After adding a host run keyscan again, then restart:

docker compose run --rm -it fail2ban-webui keyscan
docker compose run --rm fail2ban-webui check
docker compose up -d --force-recreate

F2B_HOSTS=name=address,name2=address2 (port 22, user SSH_USER) is still accepted for compatibility; entries from both are combined.

General

Variable Default Meaning
PUBLIC_URL – external URL, e.g. https://fail2ban.example.org. Required for OIDC; with https:// session cookies get the Secure flag
DEFAULT_LANG en language until a user picks one in the dropdown (en, de, …)
TRUSTED_PROXY_HOPS 0 number of reverse proxies whose X-Forwarded-For/-Proto headers are trusted. Behind one proxy: 1. Wrong values make the audit log and the login lockout use the wrong client IP
SESSION_HOURS 12 session lifetime
SESSION_COOKIE_SECURE from PUBLIC_URL force the Secure cookie flag on/off
SECRET_KEY generated key that signs session cookies; by default created once in data/secret_key
TZ Europe/Vienna (compose) time zone of the log and audit timestamps
CONFIG_FILE /config/hosts.yaml path of the host list inside the container
DATA_DIR /data data directory inside the container

Authentication

See authentication.md for the complete setup.

Variable Default Meaning
AUTH_MODE local local, oidc, local,oidc or proxy
AUTH_USER admin local user name
AUTH_PASSWORD_HASH – scrypt hash from hash-password (single quotes!)
AUTH_PASSWORD_HASH_FILE – alternative: file containing the hash (e.g. a Docker secret)
LOGIN_MAX_ATTEMPTS 5 failed logins per client IP before the lockout
LOGIN_LOCK_MINUTES 15 duration of the lockout window
OIDC_ISSUER – issuer URL; the discovery document is read from <issuer>/.well-known/openid-configuration
OIDC_DISCOVERY_URL – full discovery URL instead of OIDC_ISSUER
OIDC_CLIENT_ID / OIDC_CLIENT_SECRET – client credentials
OIDC_SCOPES openid email profile requested scopes
OIDC_USERNAME_CLAIM preferred_username claim shown as user name (falls back to email, then sub)
OIDC_GROUPS_CLAIM groups claim with the group list
OIDC_ALLOWED_GROUPS – only members of these groups may sign in (comma separated)
OIDC_ALLOWED_USERS – only these user names may sign in
OIDC_BUTTON_LABEL SSO text on the login button ("Sign in with …")
AUTH_PROXY_ALLOWED_IPS – proxy mode: only accept requests from these addresses/networks
AUTH_PROXY_HEADER – proxy mode: header with the user name, e.g. X-authentik-username
AUTH_PROXY_LOGOUT_URL – proxy mode: target of the "Sign out" button

Agents (SSH)

Variable Default Meaning
SSH_USER f2bweb default user for hosts without user:
SSH_KEY /data/ssh/id_ed25519 private key
KNOWN_HOSTS /data/ssh/known_hosts pinned host keys (written by keyscan)
SSH_TIMEOUT 40 seconds per agent call
CACHE_SECONDS 15 how long the ban list is cached between page refreshes
MANUAL_JAIL manual-block jail name shown in the UI hint – the agent decides the real jail (/etc/f2b-webctl.conf)
AUDIT_LOG /data/audit.log audit log (JSON lines)

The SSH client ignores the system ssh_config, uses only the configured key, never asks questions and refuses unknown host keys.

GeoIP

Variable Default Meaning
GEOIP_AUTO_DOWNLOAD 0 1: download the free DB-IP Lite city database (CC BY 4.0) and refresh it monthly
GEOIP_DB /data/geoip/dbip-city-lite.mmdb path of the database – any MaxMind-format city database works (e.g. GeoLite2 City)

With a city database the UI also shows the origin map (country-only databases have no coordinates). The map is bundled with the app (Natural Earth, public domain) – no external tile server is contacted. Without a database the "Origin" column stays empty and the map is hidden.

Loki and Grafana

With Loki the UI gets a History button per IP showing the matching log lines of the last days; with Grafana every ban gets a link to Explore.

Variable Default Meaning
LOKI_URL – e.g. http://loki:3100; empty = history disabled
LOKI_SELECTOR {job=~".+"} LogQL stream selector for the search, e.g. {job=~"fail2ban|sshd|nginx"}
LOKI_DAYS 7 how far back to search
LOKI_LIMIT 50 maximum lines
LOKI_USER / LOKI_PASSWORD – basic auth
LOKI_TENANT – X-Scope-OrgID for multi-tenant Loki
GRAFANA_URL – e.g. https://grafana.example.org
GRAFANA_DASHBOARD – path of a dashboard for the header link, e.g. /d/abc123/security
GRAFANA_LOKI_UID loki UID of the Loki data source in Grafana (for Explore links)

Example – exclude the UI's own access log from the search:

LOKI_SELECTOR={job=~"fail2ban|ufw|nginx|sshd", domain!="fail2ban.example.org"}

Agent settings

Protected addresses and the manual jail are configured on each host in /etc/f2b-webctl.conf – see agent.md.