Files
fail2ban-webui/docs/reverse-proxy.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

122 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Reverse proxy
The container serves plain HTTP on port 8080 (published as `127.0.0.1:8080` in the
example). Put a reverse proxy with TLS in front of it and set in `.env`:
```ini
PUBLIC_URL=https://fail2ban.example.org
TRUSTED_PROXY_HOPS=1
```
The proxy must pass `Host` unchanged and set `X-Forwarded-For` and `X-Forwarded-Proto` –
all examples below do. Restricting access to known IP addresses at the proxy is a cheap
extra layer and strongly recommended.
## Nginx Proxy Manager
**Hosts → Proxy Hosts → Add Proxy Host**
| Field | Value |
|---|---|
| Domain Names | `fail2ban.example.org` |
| Scheme / Forward Hostname / Port | `http` · IP of the Docker host (or `127.0.0.1` if NPM runs with host networking) · `8080` |
| Block Common Exploits | on |
| SSL | request a certificate, *Force SSL*, *HTTP/2*, *HSTS* |
| Access List | optional: an access list with your IP addresses (*Satisfy any* off) |
If NPM runs in another Docker network on the same host, bind the UI port to the host's
LAN address (e.g. `"192.168.1.10:8080:8080"`) or attach the UI to NPM's network and use
`fail2ban-webui:8080` as target.
Response headers belong into **Advanced → Custom Nginx Configuration**; NPM's image
includes the *headers-more* module, which also applies them to proxied responses:
```nginx
more_set_headers "Strict-Transport-Security: max-age=31536000; includeSubDomains";
```
(The app sets CSP, `X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy` and
`Cache-Control` itself.)
## Caddy
```caddy
fail2ban.example.org {
@allowed remote_ip 203.0.113.0/24 2001:db8::/32
handle @allowed {
reverse_proxy 127.0.0.1:8080
}
respond 403
}
```
Caddy sets `X-Forwarded-For`/`-Proto` automatically.
## Traefik (Docker labels)
Attach the container to Traefik's network and add labels instead of publishing the port:
```yaml
services:
fail2ban-webui:
# … as in the example compose file, without "ports:"
labels:
- traefik.enable=true
- traefik.http.routers.f2bwebui.rule=Host(`fail2ban.example.org`)
- traefik.http.routers.f2bwebui.entrypoints=websecure
- traefik.http.routers.f2bwebui.tls.certresolver=letsencrypt
- traefik.http.routers.f2bwebui.middlewares=f2bwebui-ipallow
- traefik.http.middlewares.f2bwebui-ipallow.ipallowlist.sourcerange=203.0.113.0/24
- traefik.http.services.f2bwebui.loadbalancer.server.port=8080
networks:
- fail2ban-webui.dockernetwork.local
- traefik
```
### Traefik with Authentik forward auth (proxy mode)
```yaml
- traefik.http.routers.f2bwebui.middlewares=authentik@docker
```
```ini
AUTH_MODE=proxy
AUTH_PROXY_HEADER=X-authentik-username
AUTH_PROXY_ALLOWED_IPS=<address of Traefik in the shared network>/32
AUTH_PROXY_LOGOUT_URL=https://fail2ban.example.org/outpost.goauthentik.io/sign_out
```
## nginx
```nginx
server {
listen 443 ssl;
http2 on;
server_name fail2ban.example.org;
ssl_certificate /etc/letsencrypt/live/fail2ban.example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fail2ban.example.org/privkey.pem;
allow 203.0.113.0/24;
deny all;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90s; # several slow agents can take a while
}
}
```
## Check
```bash
curl -sI https://fail2ban.example.org/login | grep -iE '^(HTTP|content-security|set-cookie)'
```
Expect `HTTP/2 200`, the `Content-Security-Policy` header and a session cookie with
`Secure; HttpOnly; SameSite=Lax`. A cookie without `Secure` means `PUBLIC_URL` does not
start with `https://`.