Guides
fail2ban for Home Assistant
Home Assistant logs every failed login with the client's IP, and it can ban addresses by itself. fail2ban adds firewall-level bans on Container and Core installs. On Home Assistant OS you'll rely on the built-in ban instead — here's why and how to set up both.
To protect Home Assistant with fail2ban, make sure the homeassistant.components.http.ban logger writes warnings to home-assistant.log in your config directory, create a filter matching Login attempt or request with invalid authentication from … (<ADDR>), and enable a jail on port 8123 with backend = auto and logpath pointing to that file. This works for Home Assistant Container and Core. On Home Assistant OS, use Home Assistant's built-in IP ban instead.
[Definition]
failregex = ^\s*WARNING \([^)]*\) \[homeassistant\.components\.http\.ban\] Login attempt or request with invalid authentication from \S+ \(<ADDR>\)\.[home-assistant]
enabled = true
backend = auto
filter = home-assistant
logpath = /opt/homeassistant/config/home-assistant.log
port = 8123
maxretry = 5
findtime = 1h
bantime = 1dHome Assistant's own IP ban#
Before adding fail2ban, know what Home Assistant does by itself. Its HTTP server has two settings:
- IP banning (
ip_ban_enabled) — on by default. - Login attempts threshold (
login_attempts_threshold) — off by default (-1). Until you set a number, nobody is ever banned.
In current releases you set both under Settings → System → Network, in the HTTP server section ("Enable IP banning" and the number of failed login attempts, 1–1000). Older releases used YAML:
http:
ip_ban_enabled: true
login_attempts_threshold: 5Banned addresses are written to ip_bans.yaml in the config directory. They never expire on their own; to unban, delete the entry and restart Home Assistant. Home Assistant answers banned clients with 403 Forbidden, so they still reach the application — fail2ban's advantage is that it drops them at the firewall, with expiring and incremental bans. Running both is fine.
Make Home Assistant log failed logins#
Each failed login or request with a bad token produces a warning from the homeassistant.components.http.ban logger:
2026-10-25 18:36:10.481+00:00 WARNING (MainThread) [homeassistant.components.http.ban] Login attempt or request with invalid authentication from 203.0.113.42 (203.0.113.42). Requested URL: '/auth/login_flow/4f1c2d0e9b8a7c6d5e4f3a2b1c0d9e8f'. (Mozilla/5.0 (X11; Linux x86_64; rv:144.0) Gecko/20100101 Firefox/144.0)
2026-10-25 18:36:11.002 WARNING (MainThread) [homeassistant.components.http.ban] Login attempt or request with invalid authentication from host-198-51-100-7.example.net (198.51.100.7). Requested URL: '/api/states'. (curl/8.5.0)The first part after from is a reverse-DNS name when one exists; the address is always the value in parentheses, which is what the filter captures. Recent versions add the UTC offset to the timestamp (.481+00:00), older ones don't — fail2ban's date detection handles both, and our fail2ban-regex test matched both lines above.
The filter is anchored at the start of the message on purpose. The user agent at the end is client-controlled and could contain a fake "Login attempt … from x (192.0.2.1)." text; with the anchor it can't trigger a ban on someone else.
If you lowered the default log level, keep this logger at warning:
logger:
default: warning
logs:
homeassistant.components.http.ban: warningHome Assistant Container and Core write the log to home-assistant.log in the config directory. Check with ls -l /opt/homeassistant/config/home-assistant.log (your config path may differ).
Home Assistant in Docker#
Most Home Assistant Container setups run with network_mode: host:
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
network_mode: host
volumes:
- /opt/homeassistant/config:/config
- /etc/localtime:/etc/localtime:roWith host networking there's no Docker NAT: port 8123 is an ordinary host port, traffic passes the INPUT chain, and the jail at the top of this page works as-is. Only if you publish the port from a bridge network (ports: - "8123:8123") do you need the Docker variant:
[home-assistant]
enabled = true
backend = auto
filter = home-assistant
logpath = /opt/homeassistant/config/home-assistant.log
banaction = iptables-allports
chain = DOCKER-USER
maxretry = 5Why: Docker forwards published ports through FORWARD, which a default ban never touches. Details in fail2ban with Docker containers.
Behind a reverse proxy#
Behind nginx, Nginx Proxy Manager, Caddy or Traefik, Home Assistant sees the proxy's address and logs it — fail2ban would ban the proxy. Enable Trust X-Forwarded-For and add the proxy's address or network to Trusted proxies (Settings → System → Network; in older YAML configs use_x_forwarded_for: true and trusted_proxies: under http:). New log lines must then show public addresses.
When the proxy terminates TLS on 443, the ban must cover the proxy's ports: use port = http,https,8123 or an all-ports action. If the proxy runs in Docker with published ports, ban in DOCKER-USER as in the Nginx Proxy Manager guide. Behind Cloudflare, use edge bans.
Home Assistant OS and the add-on question#
On Home Assistant OS (and Supervised installs) Home Assistant doesn't write home-assistant.log by default — logs go to the system journal — and you can't install packages on the host or change its firewall. There's no official fail2ban add-on, and an add-on container can't reliably manage the host firewall. Your options:
- Use the built-in IP ban with a
login_attempts_threshold(above). This is the practical choice for most HA OS users. - Ban one hop earlier: if a reverse proxy on another machine (a VPS, a Raspberry Pi running nginx, your router) fronts Home Assistant, run fail2ban there on the proxy's logs.
- Ban at Cloudflare's edge if Home Assistant is exposed through Cloudflare or a Cloudflare Tunnel.
The Home Assistant "fail2ban" sensor integration#
Home Assistant also has a legacy fail2ban sensor integration. It doesn't ban anything: it reads /var/log/fail2ban.log (or file_path) and shows the current and total bans of the jails you list as sensors:
sensor:
- platform: fail2ban
jails:
- sshd
- home-assistantIt's only usable where Home Assistant can read fail2ban's log, so in practice on Container installs with the log mounted into the container (for example - /var/log/fail2ban.log:/var/log/fail2ban.log:ro). Home Assistant's docs say it can't be used on Home Assistant OS.
Test it#
sudo fail2ban-regex /opt/homeassistant/config/home-assistant.log /etc/fail2ban/filter.d/home-assistant.conf
sudo fail2ban-client status home-assistantThen log in with a wrong password from a phone on mobile data until /var/log/fail2ban.log shows [home-assistant] Ban. Companion apps and dashboards with an expired token also trigger this warning — put your LAN in ignoreip so a wall tablet can't ban your whole household.
FAQ#
Can fail2ban protect Home Assistant?#
Yes, on Home Assistant Container and Core. Home Assistant logs Login attempt or request with invalid authentication from <host> (<IP>) to home-assistant.log; a fail2ban filter matching that line plus a jail on port 8123 bans attackers at the firewall. On Home Assistant OS use the built-in IP ban instead.
Is there a fail2ban add-on for Home Assistant OS?#
There's no official one. Home Assistant OS doesn't let you install fail2ban on the host or manage its firewall, and it doesn't write home-assistant.log by default. Use the built-in IP ban (login_attempts_threshold), or run fail2ban on a reverse proxy or router in front of Home Assistant.
How do I enable Home Assistant's built-in IP ban?#
Set a failed-login threshold: in current releases under Settings → System → Network (HTTP server), in older releases with login_attempts_threshold: 5 under http: in configuration.yaml. IP banning itself is on by default, but the threshold defaults to off. Bans are stored in ip_bans.yaml and don't expire.
Do I need DOCKER-USER for Home Assistant in Docker?#
Only if the container publishes port 8123 from a bridge network. The common network_mode: host setup has no Docker NAT, so traffic passes the normal INPUT chain and the default fail2ban action blocks it.
Why does fail2ban see my proxy's IP in the Home Assistant log?#
Home Assistant only trusts X-Forwarded-For from proxies you list. Enable "Trust X-Forwarded-For" and add the proxy to "Trusted proxies" (or use_x_forwarded_for and trusted_proxies in older YAML). Then the log, and fail2ban, see the client's real address.
Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.