minsec

Configuration

One TOML file, plus drop-ins. Everything below has a working default.

Configuration is /etc/minsec/minsec.toml, merged with every /etc/minsec/conf.d/*.toml in filename order. minsec enable and minsec disable write drop-ins, so hand edits to the main file survive them.

The complete reference is minsec.toml(5); this page is the shape of it.

The whole thing, annotated

[defaults]
bantime  = "1h"                  # first ban length
findtime = "10m"                 # window failures are counted in
maxretry = 5                     # failures within findtime that trigger a ban
backend  = "nft"                 # nft | null | exec

# Repeat offenders get longer bans: 1h, 2h, 4h … capped at a week. The
# escalation level for an address is forgotten after `memory` of quiet.
escalate = { factor = 2, max = "1w", memory = "30d" }

# Never banned. Loopback and local addresses are implied.
allow = ["203.0.113.0/24", "198.51.100.10"]

# IPv6 is tracked and banned per /64, because an attacker with a /64 has
# effectively unlimited single addresses.
ipv6_prefix = 64

[filters.sshd]
enabled  = true
maxretry = 3                     # override just this filter

[filters.wordpress]
enabled = true
files   = ["/var/log/httpd/*_access_log"]

Any key under [defaults] can be overridden per filter under [filters.<name>].

Durations

Bare seconds, or integer/unit pairs with units s, m, h, d, w: 30, 10m, 1h30m, 2d, 1w.

Reloading

The daemon does not live-reload. After any change:

sudo minsec check && sudo systemctl restart minsec

check is offline and safe to run at any time. Active bans live in the kernel with their own timeouts, so a restart does not release anyone.

Inspecting the merged result

minsec inspect            # short human summary
minsec inspect --json     # the complete, versioned inspection document

inspect --json is the right thing for a UI or a configuration-management check to read — it reports the merged configuration, which files and filters were discovered, and the effective per-filter policy.

Escalation, concretely

With factor = 2 and bantime = "1h", an address banned repeatedly gets 1h, then 2h, 4h, 8h, up to max. The counter for an address decays after memory without a new ban. This is the single highest-value knob for a server under sustained credential stuffing: the first offence stays cheap to get wrong, and the tenth is expensive for the attacker.

Allowlisting

[defaults]
allow = ["203.0.113.0/24"]

The allowlist is enforced before any ban, including manual ones — minsec ban on an overlapping network is refused rather than silently ignored. It does not affect the crowd blocklist sets; if you also want an address exempt from the crowd feed, see multiplayer mode.

Next