# Authentication `AUTH_MODE` selects how users sign in. The container refuses to start without a working configuration – there is no unauthenticated mode. | Mode | Use when | |---|---| | `local` | one shared admin account is enough | | `oidc` | you have an identity provider (Authentik, Keycloak, Authelia, Zitadel, …) | | `local,oidc` | SSO with a local fallback account | | `proxy` | your reverse proxy already authenticates (forward auth, basic auth, IP allow list) | Every change (ban/unban) additionally needs the per-session CSRF token and a matching `Origin` header, and every action is written to the audit log with the user name. ## Local user ```bash docker compose run --rm -it fail2ban-webui hash-password ``` ```ini AUTH_MODE=local AUTH_USER=admin AUTH_PASSWORD_HASH='scrypt:32768:8:1$…' ``` - Passwords need at least 12 characters; the hash is scrypt (Werkzeug). - After `LOGIN_MAX_ATTEMPTS` (5) failures a client IP is locked for `LOGIN_LOCK_MINUTES` (15). - Failed logins are logged as `LOGIN_FAILED user=… ip=…` – see [operations.md](operations.md#protecting-the-login-with-fail2ban) to let fail2ban ban them at the proxy. - Set `TRUSTED_PROXY_HOPS=1` behind a reverse proxy, otherwise all clients appear with the proxy's address and share one lockout counter. ## OpenID Connect Requirements: `PUBLIC_URL` is set to the external `https://` URL, and the provider allows the redirect URI **`/auth/callback`**. The UI uses the authorization code flow with PKCE (`S256`) and a confidential client. User name: `OIDC_USERNAME_CLAIM` (default `preferred_username`); groups: `OIDC_GROUPS_CLAIM` (default `groups`). **Always restrict who may sign in** with `OIDC_ALLOWED_GROUPS` and/or `OIDC_ALLOWED_USERS` – or with an access policy in the provider. Without either, every account that the provider lets use this client can ban IPs (a warning is logged at start). ### Authentik 1. **Applications → Providers → Create → OAuth2/OpenID Provider** - Name: `fail2ban-webui` - Authorization flow: `default-provider-authorization-explicit-consent` (or implicit) - Client type: **Confidential** – note *Client ID* and *Client Secret* - Redirect URIs: `strict` · `https://fail2ban.example.org/auth/callback` - Signing key: any certificate (e.g. `authentik Self-signed Certificate`) - Advanced protocol settings → Scopes: `openid`, `email`, `profile` (the default *profile* mapping contains the `groups` claim) 2. **Applications → Applications → Create** - Name: `fail2ban-webui`, Slug: `fail2ban-webui`, Provider: the one from step 1 3. **Directory → Groups → Create** `fail2ban-admins` and add the users. 4. Optional, recommended: in the application under **Policy / Group / User Bindings** bind the group `fail2ban-admins`, so nobody else even reaches the consent screen. 5. `.env`: ```ini PUBLIC_URL=https://fail2ban.example.org AUTH_MODE=oidc OIDC_ISSUER=https://auth.example.org/application/o/fail2ban-webui/ OIDC_CLIENT_ID=… OIDC_CLIENT_SECRET='…' OIDC_ALLOWED_GROUPS=fail2ban-admins OIDC_BUTTON_LABEL=Authentik ``` 6. `docker compose up -d`, open `PUBLIC_URL`, click **Sign in with Authentik**. The issuer URL is shown in Authentik on the provider page (*OpenID Configuration Issuer*). ### Other providers | Provider | `OIDC_ISSUER` | Groups | |---|---|---| | Keycloak | `https://kc.example.org/realms/` | add a *Group Membership* mapper with claim name `groups`, "Full group path" off | | Authelia | `https://auth.example.org` | `groups` scope; set `OIDC_SCOPES=openid email profile groups` | | Zitadel | `https://.zitadel.cloud` | roles instead of groups – use `OIDC_ALLOWED_USERS` or a project role check in Zitadel | ### Sign out "Sign out" ends the session in the web UI. The session at the provider stays active, so the next "Sign in with …" usually logs in again without a password. ## Reverse-proxy mode The proxy does the authentication; the UI only checks where requests come from and, optionally, which user the proxy reports. ```ini AUTH_MODE=proxy TRUSTED_PROXY_HOPS=1 # only accept requests from the proxy (address as seen by the container) AUTH_PROXY_ALLOWED_IPS=172.23.51.1/32 # optional: user name for the audit log, set by the proxy AUTH_PROXY_HEADER=X-authentik-username # optional: logout URL of the proxy/IdP AUTH_PROXY_LOGOUT_URL=https://fail2ban.example.org/outpost.goauthentik.io/sign_out ``` - `AUTH_PROXY_ALLOWED_IPS` is checked against the **direct** peer of the container, not against `X-Forwarded-For`. If the proxy runs on the same Docker host and reaches the container via the published port, that is the network gateway (`172.23.51.1` in the example compose file); check with `docker compose logs` after a request. - With `AUTH_PROXY_HEADER` set, requests without the header are rejected (401). Make sure the proxy **removes** that header from client requests – forward-auth integrations (Authentik, Authelia) do that. - Without `AUTH_PROXY_HEADER` the audit log shows the user `proxy`. Examples for Nginx Proxy Manager, Traefik and Caddy are in [reverse-proxy.md](reverse-proxy.md).