Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

If Fail2ban’s RAM use rose sharply after an attack, the most likely explanation is retained state rather than a single bad IP. A very large ban population, long or permanent ban timers, recidive jails, an oversized journal replay, or firewall objects holding thousands of entries can all consume memory. Fail2ban issue reports describe incidents involving roughly 500,000–1,000,000 banned addresses and another case around 2.4 GB of process memory, but neither figure is a universal limit or memory-per-ban benchmark.

Measure which component is consuming memory first. Then reduce retained state, correct the log backend or firewall action, and reload in a way that does not unexpectedly erase your protection or lock you out.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What can consume the memory?

Fail2ban watches logs, tracks matches, maintains jail state, stores ban information in its SQLite database, and asks a firewall action to enforce each ban. A spike attributed to “Fail2ban” may therefore come from several different places.

The Fail2ban server process

The Python server keeps jail objects, match history and ban state in memory. A large active list or many enabled jails increase that state. Issue #2118 describes extreme usage while maintaining 500K–1M banned IPs and discusses in-memory SQLite journaling; issue #2045 reports approximately 2.4 GB of machine memory associated with Fail2ban. These are historical incident reports, not supported capacity guarantees.

#1 Best Overall

The SQLite database

Fail2ban records persistent ban data in /var/lib/fail2ban/fail2ban.sqlite3 on typical installations. A growing file does not prove that the entire file is resident in RAM, but it is evidence that old state may not be purged as quickly as your policy requires. Database retention is controlled by the jail configuration’s purge settings, commonly the dbpurgeage option.

The firewall or kernel

Actions may create iptables rules, nftables sets, firewalld rich rules, or related kernel objects. A huge rule list or set can consume kernel memory while the Fail2ban process itself remains modest. Conntrack entries, a large systemd journal, and other kernel caches can also make the system appear to have a Fail2ban memory leak.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Measure before changing configuration

Capture a baseline while the incident is visible. Repeat the measurements after several minutes so you can distinguish a one-time allocation from continuous growth.

  1. Measure the process. Run ps -o pid,rss,vsz,cmd -C fail2ban-server. RSS is resident memory in kilobytes; record it with a timestamp. Also run systemctl status fail2ban --no-pager and free -h.
  2. Record global Fail2ban state. Run fail2ban-client status to list jails, then run fail2ban-client status JAILNAME for every enabled jail. Record currently failed and banned counts, total bans, and the log path or backend shown for each jail.
  3. Check the database. Run ls -lh /var/lib/fail2ban/fail2ban.sqlite3. If your distribution stores the database elsewhere, use the path in the active Fail2ban configuration. Record the size before and after the observation period.
  4. Inspect host memory outside Fail2ban. Use slabtop or cat /proc/meminfo to look for kernel growth. If connection tracking is enabled, check conntrack -S and compare the result with normal traffic levels.
  5. Count firewall objects. For iptables, use iptables -L -n -v and iptables -S. For nftables, use nft list ruleset and inspect set element counts. For firewalld, use firewall-cmd --list-all and inspect the underlying nftables or iptables state. A large set or thousands of individual rules can explain memory that is not in the Python process.
  6. Check journal storage. Run journalctl --disk-usage. This reports retained journal volume, not Fail2ban RSS, but it identifies a potentially oversized input source.

Do not infer a universal safe number of bans from one incident. No authoritative Fail2ban documentation establishes a fixed memory ceiling or a reliable bytes-per-ban ratio; hardware, backend, action, jail count and address-family rules all change the result.

Read the service and Fail2ban logs

The Fail2ban troubleshooting guidance recommends starting with the service journal:

journalctl -ru fail2ban

This displays the most recent Fail2ban service messages first, making startup failures, database errors, action failures and repeated reloads easy to spot. The same guidance identifies /var/log/fail2ban.log as an important error source. Search it for messages about database locking, invalid filters, missing commands, action failures, repeated jail starts, or unusually large batches of bans.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Look for timing correlations. A memory jump immediately after a restart may be caused by replaying a large log or journal. A steady increase while ban counts remain flat points toward repeated matching, a backend problem, a database issue, or a leak that should be isolated with a controlled restart and current package version. A normal Fail2ban RSS with high total RAM points you toward firewall sets, conntrack, the journal or another service.

Bound ban retention and jail state

Long retention is useful only when it serves a defined threat model. Review the active values in every jail rather than assuming the values in a sample configuration are in force.

Setting or feature What it controls Risk when excessive Practical review
bantime How long an address remains banned after a ban event Large active lists and long re-enforcement work Use a finite duration appropriate to the service; reserve very long bans for a deliberate policy
findtime The interval in which failures are counted More historical matches retained for each decision Keep it long enough to detect the attack pattern, but not as a substitute for permanent blocking
maxretry Failures allowed within findtime Too low can create a large false-positive ban population Adjust for the protocol and expected authentication mistakes
Recidive or permanent-ban jails Escalate repeat offenders across other jails Duplicate state and very long-lived entries Check whether the recidive jail is needed and whether its input includes the same events as another jail
Enabled jail count Number of independent filters and backends running More match history, timers and firewall actions Disable unused jails and consolidate overlapping filters
dbpurgeage How long old database records are retained before purge Database growth and longer startup work Set retention to the period needed for recovery and reporting, then verify purge behavior after a maintenance cycle

The jail manual documents these time controls, database parameters and backend behavior. Make changes in a local override file such as /etc/fail2ban/jail.local or a distribution-supported jail.d/*.local file so package upgrades do not overwrite them.

Example of a bounded baseline

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
dbp​​urgeage = 1d

Replace the values with ones suitable for your exposure and incident-response requirements. The example is not a universal recommendation, and a typo in an option name will be ignored or rejected depending on the installed version. Verify the effective configuration through fail2ban-client status and the service journal.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Review recidive carefully

A recidive jail reads Fail2ban’s own log and can ban addresses that have already been banned by service-specific jails. This can be useful for persistent scanners, but it also creates a second retention layer. Confirm its logpath, findtime, bantime and maxretry, and make sure it is not processing a duplicated log stream.

Check whether the backend is replaying too much journal data

With backend = systemd, Fail2ban reads the systemd journal rather than a conventional text file. Verify that journalmatch selects only the intended service, for example:

[sshd]
enabled = true
backend = systemd
journalmatch = _SYSTEMD_UNIT=sshd.service

Use the exact unit name present on your host; a broad or incorrect match can make Fail2ban scan unrelated events. Check the journal’s age and size with journalctl --disk-usage. The journalctl manual documents retention controls such as:

journalctl --vacuum-size=500M
journalctl --vacuum-time=14d

Vacuuming removes archived journal files from disk. It does not prove that Fail2ban’s resident memory will immediately fall, because the process may still hold match state and the active journal cursor may still cover a large interval.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fail2ban’s jail manual notes that rotated journals are ignored by default to avoid too many open files. Explicitly enabling rotated-journal processing can be appropriate for a carefully bounded history, but it can also make startup and replay work much larger. If a rotated set is unexpectedly included, narrow the match or return to the default behavior.

Verify that the firewall action actually enforces the bans

A growing ban list is not useful if the action writes rules that do not see the traffic. Inspect the native firewall state, not only Fail2ban’s counters.

iptables

Run iptables -L -n -v to see packet counters and rule order, and iptables -S to see exact chains. Confirm that the Fail2ban chain exists, that the jump to it occurs before an allow rule that would bypass it, and that the address family matches the traffic. If attackers use IPv6, an IPv4-only action will not stop them.

nftables

Run nft list ruleset. Identify the Fail2ban chain and any named set used for addresses, then inspect set size and timeout behavior. A single nftables set is generally easier to scale than thousands of individual rules, but the action must match the host’s actual nftables layout and syntax.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

firewalld

Use firewall-cmd --list-all and inspect the generated nftables or iptables rules. Check whether Fail2ban is adding direct rules, rich rules or a dedicated chain, and verify their priority relative to permanent allow rules.

The Fail2ban troubleshooting guidance specifically calls out conflicts such as allow rules placed ahead of the Fail2ban chain. Correct the ordering or select a netfilter action suitable for the firewall stack installed on the host.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Why Docker bans often appear ineffective

Containerized services commonly receive forwarded traffic rather than traffic destined for the host itself. Docker’s forwarding path uses the FORWARD chain, so a rule inserted only into INPUT may never see the connection. The Fail2ban troubleshooting guidance recommends the DOCKER-USER chain for applying restrictions before Docker’s own forwarding rules.

  1. Determine the published port and container network with docker ps and docker inspect CONTAINER.
  2. Confirm that the service logs consumed by Fail2ban contain the original client address rather than only a proxy or bridge address.
  3. Inspect iptables -L DOCKER-USER -n -v or the equivalent nftables chain and verify packet counters increase when you test a blocked address.
  4. Place the Fail2ban action in the path that handles the forwarded traffic, while preserving established connections and management access.

If a reverse proxy sits in front of the container, the application may log the proxy’s address unless trusted-forwarded-header handling is configured correctly. Banning that address can block every client or fail to block the attacker, so validate the logged source before changing the filter.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Apply the smallest reversible fix

After attribution, change one cause at a time and observe the result.

  1. Reduce excessive retention. Shorten an unnecessarily long bantime, disable a duplicate jail, or adjust a recidive policy. Avoid changing all timers at once; otherwise you cannot tell which change affected memory.
  2. Narrow the input. Correct logpath or journalmatch, and avoid replaying unrelated or rotated logs unless required.
  3. Correct the action. Use the firewall backend appropriate to the host and traffic path. For containers, target forwarding and DOCKER-USER, not only INPUT.
  4. Validate the filter. Test representative log lines with fail2ban-regex before enabling a broad rule. Confirm that expected failures match and routine successful logins do not.
  5. Reload when possible. Use fail2ban-client reload or systemctl reload fail2ban if your package supports a non-disruptive reload, then check each jail’s status and the firewall counters.
  6. Restart deliberately. The project documentation warns that a restart can unban all addresses and then ban them again while logs are reprocessed. Schedule it with an emergency console or allowlisted management path, and expect a temporary change in firewall state.

Clear bans and reset the database safely

Do not delete the database while the daemon is running. First preserve evidence and access.

  1. Save fail2ban-client status, each jail’s status, the process RSS, the database size, and the current firewall ruleset.
  2. Unban only the addresses that must be released with fail2ban-client set JAILNAME unbanip ADDRESS. Some current versions also support fail2ban-client unban --all; check fail2ban-client --help on your installation before using a global command.
  3. Stop Fail2ban with systemctl stop fail2ban. Confirm that no fail2ban-server process remains.
  4. Back up the database: cp -a /var/lib/fail2ban/fail2ban.sqlite3 /var/lib/fail2ban/fail2ban.sqlite3.backup. Adjust the path if your package uses a different location.
  5. If you intentionally want to discard all persistent ban history, remove the database only after the backup: rm /var/lib/fail2ban/fail2ban.sqlite3. This erases history and may cause previously banned addresses to be treated as new.
  6. Start the service with systemctl start fail2ban, then check fail2ban-client status, the service journal and the native firewall rules.

Stopping or restarting an action may remove its rules, but stale firewall objects can remain after a failed action. Compare the pre-change and post-change rulesets and remove only entries you can identify as obsolete. Never flush a production firewall wholesale as a shortcut.

Interpret the result after the change

Observation Likely direction Next check
Fail2ban RSS and database grow with active bans Ban cardinality or retention is the primary pressure Review timers, recidive, jail count and purge age; inspect firewall set size
RSS jumps during startup, then stabilizes Initial log or journal replay Narrow journalmatch, inspect rotated logs and reduce retained history
RSS is normal but total RAM is low Kernel, firewall, conntrack, journal or another process Use slabtop, firewall object counts, conntrack -S and process-wide memory tools
Bans increase but attack traffic continues Wrong chain, rule order, address family or logged source Check packet counters, Docker forwarding, proxy headers and action errors
Memory falls after restart and rises again quickly Recurring replay, unbounded state or a version-specific defect Compare growth rate, logs and package version; isolate with a minimal jail set and report reproducible evidence

When to treat it as a software defect

Escalate beyond configuration tuning when a minimal configuration with a bounded log source and modest ban count still shows monotonic RSS growth, especially if the growth persists after old bans expire and the database is purged. Record the Fail2ban version, Python version, operating system, backend, action, jail files, RSS samples, ban counts, database size, journal size and relevant log messages. Do not present the historical 2.4 GB or 500K–1M incidents as a threshold; use them only as context for why large state deserves investigation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Before filing or applying an upgrade, reproduce the behavior with one jail and a controlled log sample. This separates a filter or backend problem from a host-wide memory issue and gives maintainers actionable evidence.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.