n8n's login page has no built-in rate limiting or account lockout.
n8n's login page has no built-in rate limiting or account lockout. An attacker can attempt unlimited password guesses against the admin account. Use fail2ban or equivalent tooling to detect and block brute force attempts.
Real-world example: An n8n instance with a weak admin password is exposed to the internet. An attacker runs a credential stuffing attack using a leaked password database and gains access in under an hour.
# /etc/fail2ban/jail.d/n8n.conf
[n8n]
enabled = true
port = 443
filter = n8n-auth
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 3600
action = iptables-multiport[name=n8n, port="443", protocol=tcp]
```text
```bash
# /etc/fail2ban/filter.d/n8n-auth.conf
[Definition]
# Match failed login attempts (n8n returns 401 on the login API endpoint)
failregex = ^<HOST> .* "POST /rest/login HTTP/.*" 401
ignoreregex =
```text
Nginx must log in the correct format for fail2ban to parse:
```nginx
# Ensure Nginx logs the real client IP
log_format n8n_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
server {
access_log /var/log/nginx/access.log n8n_log;
# ...
}
```text
```bash
# Test the fail2ban configuration
sudo fail2ban-client status n8n
# Verify the regex matches your log format
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/n8n-auth.conf
```text
After 5 failed login attempts within 5 minutes, the attacker's IP is blocked for 1 hour at the firewall level.
**Related:** [Use Docker Compose with Health Checks for n8n and PostgreSQL](../self-hosting-operations/01-use-docker-compose-with-health-checks-for-n8n-and-postgresql.md) | [Use Path Parameters in Webhook URLs for Dynamic Routing](../webhook-mastery/01-use-path-parameters-in-webhook-urls-for-dynamic-routing.md)
I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.