# Incremental ban time with bantime.increment

> Make fail2ban ban repeat offenders longer each time with bantime.increment: every option, the formula vs multipliers, maxtime, and how dbpurgeage limits memory.
>
> Source: https://fail2ban.dev/config/bantime-increment/ · Updated 2026-10-25 · Checked against fail2ban 1.1.1
> fail2ban.dev is an independent guide, not the official fail2ban project.

To make fail2ban ban repeat offenders for longer, set **`bantime.increment = true`** in `/etc/fail2ban/jail.local`. The first ban of an IP lasts `bantime`; each later ban of the same IP doubles it (2×, 4×, 8×…) until it reaches `bantime.maxtime`. fail2ban counts previous bans in its SQLite database, so the database must be enabled (it is by default), and `dbpurgeage` decides how long an IP is remembered.

```ini
[DEFAULT]
bantime            = 1h     ; first ban
bantime.increment  = true   ; repeat bans grow: 1h, 2h, 4h, 8h…
bantime.factor     = 1
bantime.maxtime    = 1w     ; never longer than a week
```
[Definition]
dbpurgeage = 30d            ; remember previous bans for a month
```
sudo fail2ban-client reload
```

These options are commented out in the stock `jail.conf`. Set them in `[DEFAULT]` for every jail or inside a single jail.

| Option | Default | Meaning |
|---|---|---|
| `bantime.increment` | off | Turn incremental bans on (`true`). |
| `bantime` | `10m` | The first ban and the base for every increase. |
| `bantime.factor` | `1` | Coefficient in the formula, or multiplier applied to `bantime.multipliers`. |
| `bantime.formula` | `ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor` | Python expression for the next ban time. Ignored when `bantime.multipliers` is set. |
| `bantime.multipliers` | unset | Space-separated multipliers used instead of the formula, e.g. `1 2 4 8 16 32 64`. |
| `bantime.maxtime` | unset (no cap) | Maximum length of an increased ban. |
| `bantime.rndtime` | unset | Adds a random 0…N seconds to each increased ban, so bots can't predict the exact unban time. |
| `bantime.overalljails` | `false` | `true` counts the IP's previous bans in all jails, not only the current one. |

Time values accept the usual format (`1h`, `1d`, `1w`, `5w`); see [time format](/config/bantime-findtime-maxretry/).

## How the next ban time is calculated

When a jail bans an IP, fail2ban looks it up in the database (`bips` table) to find how many times it was banned before. That number is `ban.Count`.

1. **First ban** (no previous ban recorded): the ban lasts exactly `bantime`. No factor, formula or multiplier is applied.
2. **Repeat ban** (`ban.Count` ≥ 1):
   - Without multipliers: `bantime × 2^ban.Count × factor` (the exponent stops growing at 20), and never less than `bantime`.
   - With `bantime.multipliers`: `bantime × factor × multipliers[ban.Count]`. When the count runs past the end of the list, the last multiplier is used.
3. The result is capped at `bantime.maxtime`, if set.
4. A random 0…`bantime.rndtime` seconds is added, if set.

Because the list is indexed by the count of *previous* bans, the first multiplier is never used for a repeat ban. Keep it at `1` so the list reads naturally.

Previously banned IPs are also banned faster. While an IP has ban history, each new failure from it counts more than once (2× after one ban, 3× after two, 5× after three, and so on, up to `maxretry`). A known attacker coming back is often banned on its first or second failure.

## Worked examples

The [bantime calculator](/tools/bantime-calculator/) does these calculations for any values. Here are the common setups.

### Default formula, bantime = 1h, factor = 1, maxtime = 1w

| Ban # | ban.Count | Calculation | Ban length |
|---|---|---|---|
| 1 | — | bantime | 1h |
| 2 | 1 | 1h × 2 | 2h |
| 3 | 2 | 1h × 4 | 4h |
| 4 | 3 | 1h × 8 | 8h |
| 5 | 4 | 1h × 16 | 16h |
| 6 | 5 | 1h × 32 | 1d 8h |
| 7 | 6 | 1h × 64 | 2d 16h |
| 8 | 7 | 1h × 128 | 5d 8h |
| 9+ | 8+ | 1h × 256 → capped | **1w** |

### Same, with factor = 2

`bantime.factor` multiplies every repeat ban, so the growth starts one step ahead:

| Ban # | Ban length (bantime = 1h) |
|---|---|
| 1 | 1h |
| 2 | 4h |
| 3 | 8h |
| 4 | 16h |
| 5 | 1d 8h |
| 6 | 2d 16h |

### Multipliers 1 2 4 8 16 32 64, bantime = 10m

This is the example from `jail.conf`. It grows like the formula, but stops at the last multiplier (64 × 10m = 10h 40m) without needing `maxtime`:

| Ban # | Multiplier | Ban length |
|---|---|---|
| 1 | — | 10m |
| 2 | 2 | 20m |
| 3 | 4 | 40m |
| 4 | 8 | 1h 20m |
| 5 | 16 | 2h 40m |
| 6 | 32 | 5h 20m |
| 7+ | 64 | 10h 40m |

### Aggressive multipliers for a short first ban

The second example in `jail.conf`, intended for `bantime = 1m`:

```ini
bantime.multipliers = 1 5 30 60 300 720 1440 2880
```

## How long fail2ban remembers an IP (dbpurgeage)

This is where most incremental setups quietly fail. Ban history lives in `/var/lib/fail2ban/fail2ban.sqlite3`, and a purge runs every hour. An IP's last ban record is deleted once **`dbpurgeage` plus three times that ban's length** has passed since the ban started. Permanent bans (`-1`) are never purged.

With the stock `dbpurgeage = 1d`:

| Last ban length | IP forgotten after |
|---|---|
| 1h | 1d 3h |
| 8h | 2d |
| 1d | 4d |

So a bot that comes back a week later starts again at ban #1. To remember repeat offenders for longer, raise `dbpurgeage` in `fail2ban.local` (details on the [fail2ban.conf page](/config/fail2ban-conf/)):

```ini
[Definition]
dbpurgeage = 30d
```

```text
$ sudo fail2ban-client get dbpurgeage
Current database purge age is:
`- 86400seconds
```

- **Unbanning by hand** (`fail2ban-client unban <IP>` or `set <jail> unbanip <IP>`) deletes the IP's records from the database, so its next ban counts as the first. See [unban an IP](/unban-ip/).
- **No database.** With `dbfile = :memory:` the history is lost at every restart; with `dbfile = None` incremental bans don't work at all and fail2ban logs `ban time increment is not available as long jail database is not set`.

## bantime.overalljails: count bans across jails

By default an IP banned by `sshd` and later by `postfix-sasl` starts at ban #1 in each jail. With `bantime.overalljails = true`, fail2ban adds up the IP's bans in every jail, so an attacker probing several services escalates faster:

```ini
bantime.increment    = true
bantime.overalljails = true
```

## bantime.increment vs recidive

Both punish repeat offenders; they work differently and combine well.

| Feature | bantime.increment | recidive jail |
|---|---|---|
| Trigger | Same IP banned again by the same jail (or any jail with `overalljails`) | IP banned `maxretry` times within `findtime` across jails, read from fail2ban's log |
| Effect | Longer ban in the original jail, on its ports | Separate ban on **all ports** |
| Needs | The database (default) | fail2ban's own log in a file or the journal |
| Tuning | `factor`, `multipliers`, `maxtime`, `dbpurgeage` | `bantime`, `findtime`, `maxretry` of `[recidive]` |

A common setup is increment in `[DEFAULT]` with a cap of one week, plus recidive for an all-ports ban. Remember that `bantime.maxtime` in `[DEFAULT]` also caps recidive's repeat bans; give `[recidive]` its own `bantime.maxtime` if you want them to exceed it. The [jail.local example](/config/jail-local/) shows the full combination.

## Permanent bans for repeat offenders

To ban an IP forever after a certain number of bans, use multipliers and make the last step huge, or rely on a permanent recidive jail. There's no "-1" multiplier, but a very large one has the same practical effect:

```ini
[sshd]
enabled             = true
bantime             = 1h
bantime.increment   = true
# 1h, 1d, 1w, then about 10 years
bantime.multipliers = 1 24 168 87600
```

## Check that it works

fail2ban logs the increase when it extends a ban. Watch for `Increase Ban` lines in `/var/log/fail2ban.log`:

```bash
```

```bash
```

## FAQ

### How do I enable incremental ban time in fail2ban?

Add `bantime.increment = true` to `[DEFAULT]` (or one jail) in `/etc/fail2ban/jail.local`, optionally with `bantime.factor`, `bantime.maxtime` and `bantime.multipliers`, then run `sudo fail2ban-client reload`. The database must be enabled (`dbfile` in fail2ban.conf, on by default).

### What does bantime.factor do?

It multiplies repeat bans. With the default formula, the second ban is `bantime × 2 × factor`, the third `bantime × 4 × factor`, and so on. `factor = 1` doubles each time; `factor = 2` starts at 4×. The first ban is always the plain `bantime`.

### Why does bantime.increment not work?

The usual causes: it isn't enabled in the jail that bans (check `sudo fail2ban-client -d | grep increment`), the database is disabled (`dbfile = :memory:` or `None`), the IP was forgotten because `dbpurgeage` (default 1 day) expired, or it was unbanned manually, which deletes its history.

### What is the maximum ban time with bantime.increment?

Whatever `bantime.maxtime` is set to. Without it, the default formula keeps doubling until the exponent reaches 20 (about a million times `bantime`), and multipliers stop at the last value in the list. Always set `bantime.maxtime` unless your multipliers already end where you want.

### Does bantime.increment work across jails?

Only with `bantime.overalljails = true`. By default an IP's previous bans are counted per jail. With overalljails, bans from every jail are added together, but the resulting ban still applies only to the jail that triggered it.
