Updated Aug 2, 2026
SnBans is a licensed product: request a license on Discord.
SnBans is a network-wide punishment suite: bans, mutes, permanent blacklists and alt scanning. One jar runs on both Paper 1.20.5 or newer (1.21.x included) and Velocity 3.4.0 or newer. Every command carries the same syntax, permissions and messages on both platforms. Punishment data lives in one shared SQL schema, so several servers pointed at the same MySQL share a single punishment record.
/ban, /ipban, /mute, /ipmute and /blacklist, plus
/unban, /unmute and /unblacklist. Bans and mutes each have an explicit IP variant and a
per-type ip-by-default switch, so a plain /ban can cover the address too. A blacklist is
always permanent and always covers the IP, so it takes no duration argument at all./kick and /ipkick disconnect, announce and post
their webhook, and write no row - so a kick never appears in /history, has nothing to undo and
never counts towards a template ladder. /ipkick clears the target's last known address, which
reaches their online alts even when the target is offline. Having no row is also the one
limitation: on a multi-backend Paper install a kick reaches only the server it was run on, while
a Velocity install is network-wide.templates.yml id takes its duration from that
template's ladder. The step is picked from how many punishments of that template the player
already collected, and the last step repeats for every further offence. Offences reverted by a
rollback do not count toward the escalation./alts lists the accounts sharing the target's current IP, and
/snbans match lists every IP two accounts have ever shared. An automatic join scan warns
snbans.notify holders, filtered by the states listed in alts.notify-states. On a shared MySQL
both the account list and the Online marker are network-wide, so an alt connected to another
backend is listed and shown as online rather than offline. alts.hidden keeps named accounts out
of every scan a player sees, in both directions, without touching enforcement.sync.interval-seconds. No plugin messaging channel is
involved, and a server skips its own rows so nothing is announced twice.snbans.silent gated -s / -p flag on every issue and every
revert, a per-type silent-by-default, and a per-event broadcasts.* toggle. A silent
punishment is still reported to snbans.notify holders.attempt-notices reports the punishments players run into rather than the
ones staff hand out - a ban, IP ban or blacklist refusing a login, and a mute cancelling a chat
message or a blocked command. They reach the console and snbans.notify holders only, throttled
per player by attempt-notices.cooldown-seconds, because a banned client reconnects on its own
and a muted player keeps typing. The notice names the account that tried, so an IP ban
reached by an alt shows the alt rather than the account on the row./helpop and /report: the two commands here a player runs, delivered to the
console and to snbans.requests.receive holders on every server of the network and carrying
the server the request was filed on - which on a proxy install is the backend the sender is
standing on rather than the proxy. Throttled per player and per kind by
staff-requests.cooldown-seconds, and a throttled player is told how long is left rather than
left staring at silence.include-silent
toggle. Staff-typed reasons arrive neutralized, so no reason can ping @everyone or restyle your
embed. The shipped file is inert until you fill a URL in./snbans rollback <staff> <time> counts the matches first and prints the
confirm command to run. Nothing is reverted until confirm is appended./snbans wipe <ban|mute|blacklist|all> erases every punishment of a kind that is
still in force, for a season reset or a bad mass-ban. Console only, and a dry run until confirm
is appended, with no configuration key that can skip that step./snbans import litebans ... reads an existing LiteBans database and writes
its bans, mutes and login history into SnBans, so a network switching over keeps its record
instead of starting blank. It is a dry run until confirm is appended, and it refuses to run
twice./history <player> and /staffhistory <staff> page punishment records in
chat, at history.page-size entries per page.The same jar covers two deployments, and the choice is yours:
| Deployment | Database | Notes |
|---|---|---|
| Every Paper backend | One shared MySQL (database.type: mysql) | Punishments and reverts are network-wide. Each backend needs its own server-name. |
| The Velocity proxy alone | SQLite, standalone | Logins, chat and commands are enforced at the proxy. |
Pick exactly one. Installing SnBans on the proxy and on its backends double-announces every punishment, because the backend and the proxy each announce the same event.
Backend installs stay the recommended path for mutes. Clients from 1.19.1 onward with enforced secure chat may not accept a chat message the proxy denies. Blocked commands, bans, IP bans and blacklists are enforced exactly on either deployment.
Give each backend its own server-name. It is what {server} resolves to, it is what network
presence is keyed by, and it is how /helpop and /report reach the staff of the other servers.
Cross-server punishments themselves no longer depend on it - since 1.8.2 the sync poller recognises
its own rows by row id - and SnBans warns when it detects two servers sharing a name, but the three
things above still break between them until each one is renamed.
Two behaviors differ by platform. /snbans debug and the snbans.admin.debug node are Paper only,
with no proxy counterpart. command.aliases is re-sourced on /snbans reload on both, but the proxy
does not resend its command tree to players who are already connected, so a new alias only
tab-completes for them after they reconnect.
SnBans is not Folia-compatible: plugin.yml declares no folia-supported key.
SnBans runs on SnLib alone. One optional soft dependency changes its behavior when present: