Compatibility
Minecraft: Java Edition
Platforms
Tags
Creators
Details
Running a server means dealing with griefers, cheaters, toxic players and the occasional ban evader. You need a punishment system that keeps up, works across every platform you're running, and doesn't need babysitting. FluxBans handles bans, mutes, kicks and warnings across Spigot, Paper, Folia, BungeeCord, Velocity and NeoForge from a single shared database. It ships with an embedded web dashboard, a full ban appeals system, Discord webhooks and a REST API — no paid tier, no feature gates, no abandoned repo.
Platform support
| Platform | JAR | Supported versions |
|---|---|---|
| Spigot / Paper | FluxBans-Bukkit.jar |
1.8.8 to 1.21.x |
| Folia | FluxBans-Folia.jar |
Latest stable |
| BungeeCord | FluxBans-BungeeCord.jar |
Latest stable |
| Velocity | FluxBans-Velocity.jar |
3.x |
| NeoForge | FluxBans-Forge.jar |
1.21.1 |
Every JAR is self-contained. Point them all at the same database and they stay in sync automatically. Ban someone on BungeeCord and they're blocked on every backend before they can reconnect.
How it compares
| Feature | FluxBans | LiteBans | LibertyBans | AdvancedBan | BanManager | CMI |
|---|---|---|---|---|---|---|
| Price | Free | $15 | Free | Free | Free | $15 |
| Actively maintained | Yes | Yes | Yes | No | Yes | Yes |
| Spigot / Paper | Yes | Yes | Yes | Yes | Yes | Yes |
| BungeeCord | Yes | Yes | Yes | No | Yes | No |
| Velocity | Yes | Yes | Yes | No | Yes | No |
| Folia | Yes | No | No | No | No | No |
| NeoForge | Yes | No | No | No | No | No |
| Embedded web dashboard | Yes | Yes | No | No | No | No |
| Built-in appeals system | Yes | No | No | No | No | No |
| Discord webhooks | Yes | Yes | No | No | No | Yes |
| Generic HTTP webhooks | Yes | No | No | No | No | No |
| REST API | Yes | No | No | No | No | No |
| IP / CIDR banning | Yes | Yes | Yes | No | Yes | Yes |
| Auto escalating warnings | Yes | No | No | Yes | No | Yes |
| LuckPerms weight exemptions | Yes | No | No | No | No | No |
| ProtectCord support | Yes | No | No | No | No | No |
| Config hot reload | Yes | No | No | No | No | Yes |
| SQLite support | Yes | Yes | Yes | No | Yes | No |
| MySQL / MariaDB support | Yes | Yes | Yes | No | Yes | Yes |
| PostgreSQL support | Yes | Yes | Yes | No | No | No |
| Import from other plugins | Yes | No | Yes | No | No | No |
Bans
Banning blocks a player from rejoining for the duration you set. The check happens at connection time so they never get past the login screen.
/ban <player> [reason] [-s]
/tempban <player> <duration> [reason] [-s]
/banip <player|ip> [reason] [-s]
/unban <player|uuid>
/unbanip <ip>
Temp bans take durations like 7d, 12h, 30m or combinations like 1d12h. You can ban by username, UUID, IP address or an entire CIDR subnet. The -s flag makes the ban silent — see the silent mode section below.
| Permission | Description |
|---|---|
fluxbans.ban |
Use /ban |
fluxbans.ban.temp |
Use /tempban |
fluxbans.ban.ip |
Use /banip and /unbanip |
fluxbans.ban.silent |
Add the -s flag to ban commands |
fluxbans.unban |
Use /unban |
fluxbans.exempt.ban |
This player cannot be banned |
Mutes
Muting prevents a player from sending chat messages and using any command you list under mute.blocked-commands in config.yml. The check runs on every chat event and blocked command so it can't be bypassed by using an alias.
/mute <player> [reason] [-s]
/tempmute <player> <duration> [reason] [-s]
/unmute <player>
| Permission | Description |
|---|---|
fluxbans.mute |
Use /mute |
fluxbans.mute.temp |
Use /tempmute |
fluxbans.mute.silent |
Add the -s flag to mute commands |
fluxbans.unmute |
Use /unmute |
fluxbans.exempt.mute |
This player cannot be muted |
Kicks
Kicks disconnect the player immediately. They can reconnect straight away unless they're also banned.
/kick <player> [reason] [-s]
| Permission | Description |
|---|---|
fluxbans.kick |
Use /kick |
fluxbans.kick.silent |
Add the -s flag |
fluxbans.exempt.kick |
This player cannot be kicked |
Warnings
Warnings accumulate and trigger automatic punishments when a player hits the thresholds you set in config.yml. By default that's a 1 hour mute at 3 warnings, a 1 day ban at 5, and a permanent ban at 10. You can change all of that to whatever your server policy is.
/warn <player> [reason] [-s]
/unwarn <id>
| Permission | Description |
|---|---|
fluxbans.warn |
Use /warn |
fluxbans.warn.remove |
Use /unwarn to remove a specific warning |
fluxbans.warn.silent |
Add the -s flag |
fluxbans.exempt.warn |
This player cannot be warned |
Silent mode
Add -s to any punishment command and the broadcast that normally goes to all players is suppressed. Only staff members online with fluxbans.notify will see it in their chat. Useful when you don't want to tip off a ban evader's friends by announcing the ban publicly.
Preset reasons
Define shortcuts in reasons.yml so your staff don't have to type the same thing every time:
/ban Steve #hacking
/mute Dave #chat-spam
The # prefix triggers a preset lookup. Durations can be locked per preset so staff can't accidentally give someone a lighter punishment than your policy requires.
Information commands
/check <player> — pulls up a full snapshot of a player's current status: active ban, active mute, warning count, IP address and any linked alt accounts.
/history <player> — shows every punishment ever issued to a player, including expired and removed ones, with who issued them and when.
/alts <player> — shows every account that has ever connected from the same IP addresses as the target.
/dupeip <ip> — the reverse of alts. Give it an IP and see everyone who has used it.
/banlist [page] and /mutelist [page] — lists all currently active bans or mutes in chat, paginated.
| Permission | Description |
|---|---|
fluxbans.check |
Use /check |
fluxbans.history |
Use /history |
fluxbans.alts |
Use /alts |
fluxbans.dupeip |
Use /dupeip |
fluxbans.banlist |
Use /banlist |
fluxbans.mutelist |
Use /mutelist |
fluxbans.seeip |
See full IP addresses in /check output |
Exemptions and LuckPerms
Any player with fluxbans.exempt.<type> cannot be punished by staff who don't outrank them. When LuckPerms is installed, FluxBans uses weight-based exemption — a moderator with weight 50 can't ban a player with weight 100 even if they have fluxbans.ban. Senior staff always override junior staff. Works without LuckPerms too, it just falls back to permission-only checks.
Web dashboard
The dashboard is embedded directly in the JAR using NanoHTTPD. Nothing to install, no separate process. It starts when the plugin loads and is accessible at http://your-server-ip:8080 (configurable in web.yml).
Anyone can see the ban list, mute list and player history. Search and paginate through records, click through to a player profile showing their alt accounts, join history and everything ever issued against them.
Staff with the admin token can review and approve or deny appeals, manually lift punishments, write notes, and browse the full action log — all from the same panel.
Developers can use the REST API at /api/v1/ to pull data as JSON for their own integrations:
GET /api/v1/bans Paginated list of active bans
GET /api/v1/mutes Paginated list of active mutes
GET /api/v1/player/:uuid Full punishment history for a player
GET /api/v1/stats Server-wide moderation statistics
HTTPS is supported if you provide a keystore in web.yml. Bind address, port, theme, branding and rate limits are all configurable.
Appeals system
Players appeal directly from the web. No Discord account, no forum, no third party service.
- Player visits
/appealon your web panel - They enter their username and write their appeal (50 to 5,000 characters)
- FluxBans generates a unique private link — something like
/appeal/a3f9c2e1— so they can check back on the status - A Discord webhook fires so your staff team knows straight away
- Staff go to
/admin, read the appeal, and click Approve or Deny with an optional written response - If approved, the punishment is removed from the database immediately. Player can rejoin, no command needed
- A second webhook fires confirming the outcome and the player's link updates to show the result
Rate limited to 3 submissions per hour per IP. Players with an open appeal can't submit another until it's resolved.
Webhooks
webhooks:
# Discord webhook with rich embeds
- url: "https://discord.com/api/webhooks/YOUR_ID/YOUR_TOKEN"
type: discord
enabled: true
events:
- ban
- unban
- mute
- unmute
- kick
- warn
- appeal_new
- appeal_resolved
skip-silent: true
colors:
ban: 15158332
unban: 3066993
mute: 15105570
unmute: 3447003
kick: 10181046
warn: 16776960
appeal_new: 3447003
appeal_resolved: 3066993
# Generic HTTP webhook with optional HMAC-SHA256 signing
- url: "https://your-site.com/api/fluxbans-webhook"
type: generic
enabled: true
events:
- appeal_new
- appeal_resolved
secret: "your-hmac-secret"
Generic webhooks POST a JSON payload. If you set a secret, every request is signed with X-FluxBans-Signature: sha256=<hex> so your endpoint can verify it came from FluxBans.
Database support
| Backend | Notes |
|---|---|
| SQLite | Bundled, zero setup |
| MySQL | Recommended for networks |
| MariaDB | Full support |
| PostgreSQL | Full support |
All backends use HikariCP connection pooling. The schema creates and migrates itself on startup.
Integrations
ProtectCord — enable with protectcord.enabled: true in config.yml and FluxBans will read the real player IP from ProtectCord metadata so IP bans work correctly through the proxy layer.
LuckPerms — auto-detected. Enables weight-based staff exemptions when present.
Vault — auto-detected. Pulls staff display names and prefixes into web UI records when present.
Migrating from another plugin
/fluxbans import litebans
/fluxbans import advancedban
/fluxbans import banmanager
Reads your existing database and maps everything across. Use --dry-run first to preview what will be imported before it touches anything.
Full default configuration
config.yml
# ─────────────────────────────────────────────────────────────
# FluxBans — Main Configuration
# Documentation: https://github.com/fluxbans/FluxBans/wiki
# ─────────────────────────────────────────────────────────────
# ── Database ──────────────────────────────────────────────────
database:
# Backend type: sqlite | mysql | mariadb | postgresql
type: sqlite
# SQLite — file path relative to the plugin data folder
file: fluxbans.db
# MySQL / MariaDB / PostgreSQL connection settings
host: localhost
port: 3306
name: fluxbans
username: root
password: ""
# Optional additional JDBC properties (key: value)
properties: {}
# ── General ───────────────────────────────────────────────────
general:
# Server name shown in punishment records and the web UI
server-name: "Survival"
# Log all punishments to the console
log-to-console: true
# Broadcast a punishment to all online staff (fluxbans.notify permission)
broadcast-to-staff: true
# Broadcast a punishment to all online players
broadcast-globally: true
# How many entries to show per page in /history, /banlist etc.
page-size: 10
# Sync interval (seconds) — how often to fetch cross-server punishment
# updates when using a shared MySQL/MariaDB/PostgreSQL database.
# Set to 0 to disable (only needed for multi-server setups).
sync-interval: 30
# Hide IP addresses from /check output for players without fluxbans.seeip
hide-ips: true
# Enable IP banning in addition to UUID banning
ip-banning: true
# If true, banning a player by name also bans their current IP
ban-ip-on-ban: false
# ── Exemption ─────────────────────────────────────────────────
exemptions:
# Prevent staff from punishing players with a higher LuckPerms weight
use-luckperms-weight: true
# ── ProtectCord ───────────────────────────────────────────────
protectcord:
# Set to true when using ProtectCord on your BungeeCord / Velocity proxy.
# FluxBans will use the real forwarded IP instead of the proxy IP.
enabled: false
# ── Mute ──────────────────────────────────────────────────────
mute:
# Commands blocked while a player is muted.
blocked-commands:
- /say
- /me
- /msg
- /tell
- /w
- /r
- /reply
- /pm
- /dm
- /whisper
# ── Warnings ──────────────────────────────────────────────────
warnings:
# Auto-punish a player when they reach certain warning thresholds.
auto-punish:
- count: 3
action: mute
duration: "1h"
reason: "Accumulated {count} warnings"
- count: 5
action: ban
duration: "1d"
reason: "Accumulated {count} warnings"
- count: 10
action: ban
duration: "perm"
reason: "Accumulated {count} warnings — permanent ban"
# ── Date/time display format ──────────────────────────────────
date-format: "dd MMM yyyy HH:mm:ss"
timezone: "UTC"
messages.yml
# ─────────────────────────────────────────────────────────────
# FluxBans — Messages Configuration
# Colour codes: &0-9 &a-f &k-o &r
# Hex colours (1.16+): &#RRGGBB
# Placeholders vary by context — see the wiki for a full list.
# ─────────────────────────────────────────────────────────────
prefix: "&8[&cFluxBans&8] &r"
# ── Bans ──────────────────────────────────────────────────────
ban:
default-reason: "You have been banned."
temp-default-reason: "Temporarily banned."
ip-default-reason: "IP banned."
kick-message: |
&c&lYou are banned from this server.
&7Reason: &f{reason}
&7Duration: &f{duration}
&7Expires: &f{expires}
&7Appeal at: &b{appeal-url}
&7Ban ID: &f#{id}
broadcast: "&c{operator} &7banned &c{player} &7» &f{reason} &7[{duration}]"
broadcast-silent: "&c{operator} &7silently banned &c{player} &7» &f{reason} &7[{duration}]"
notify: "{prefix}&7{operator} banned &c{player} &7» {reason} [{duration}]"
ip-broadcast: "&c{operator} &7IP-banned &c{player} ({ip}) &7» &f{reason} &7[{duration}]"
banned: "{prefix}&aSuccessfully banned &c{player}&a."
already-banned: "{prefix}&c{player} &7is already banned."
unbanned: "{prefix}&aSuccessfully unbanned &c{player}&a."
not-banned: "{prefix}&c{player} &7is not banned."
# ── Mutes ─────────────────────────────────────────────────────
mute:
default-reason: "Muted."
temp-default-reason: "Temporarily muted."
broadcast: "&c{operator} &7muted &c{player} &7» &f{reason} &7[{duration}]"
broadcast-silent: "&c{operator} &7silently muted &c{player} &7» &f{reason} &7[{duration}]"
notify: "{prefix}&7{operator} muted &c{player} &7» {reason} [{duration}]"
muted: "{prefix}&aSuccessfully muted &c{player}&a."
already-muted: "{prefix}&c{player} &7is already muted."
unmuted: "{prefix}&aSuccessfully unmuted &c{player}&a."
not-muted: "{prefix}&c{player} &7is not muted."
chat-blocked: |
{prefix}&cYou are muted.
&7Reason: &f{reason}
&7Expires: &f{expires}
# ── Kicks ─────────────────────────────────────────────────────
kick:
default-reason: "Kicked."
kick-message: |
&c&lYou were kicked from the server.
&7Reason: &f{reason}
&7By: &f{operator}
broadcast: "&c{operator} &7kicked &c{player} &7» &f{reason}"
broadcast-silent: "&c{operator} &7silently kicked &c{player} &7» &f{reason}"
notify: "{prefix}&7{operator} kicked &c{player} &7» {reason}"
kicked: "{prefix}&aKicked &c{player}&a."
# ── Warnings ──────────────────────────────────────────────────
warn:
default-reason: "Warned."
broadcast: "&e{operator} &7warned &e{player} &7» &f{reason}"
broadcast-silent: "&e{operator} &7silently warned &e{player} &7» &f{reason}"
notify: "{prefix}&7{operator} warned &e{player} &7» {reason}"
warned: "{prefix}&aWarned &e{player}&a."
unwarned: "{prefix}&aRemoved warning #{id} from &e{player}&a."
not-warned: "{prefix}&cWarning #{id} not found."
received: |
{prefix}&eYou have been warned by &c{operator}&e.
&7Reason: &f{reason}
&7Total active warnings: &c{count}
# ── History ───────────────────────────────────────────────────
history:
header: "{prefix}&7Punishment history for &c{player} &7(page {page}/{pages}):"
entry: " &8» &7[&c{type}&7] &f{reason} &7by &f{operator} &7on &f{date}"
no-history: "{prefix}&7No punishment history found for &c{player}&7."
# ── Check ─────────────────────────────────────────────────────
check:
header: "{prefix}&7Status for &c{player}&7:"
banned: " &7Ban: &cYes &7(#{id}) — {reason} — expires {expires}"
not-banned: " &7Ban: &aNone"
muted: " &7Mute: &eYes &7(#{id}) — {reason} — expires {expires}"
not-muted: " &7Mute: &aNone"
warnings: " &7Warnings: &e{count} active"
ip: " &7IP: &f{ip}"
# ── Banlist / Mutelist ────────────────────────────────────────
banlist:
header: "{prefix}&7Active bans &7(page {page}/{pages}, total: {count}):"
entry: " &8» &c{player} &7by &f{operator} &7— {reason} &7[{duration}]"
empty: "{prefix}&7No active bans."
mutelist:
header: "{prefix}&7Active mutes &7(page {page}/{pages}, total: {count}):"
entry: " &8» &e{player} &7by &f{operator} &7— {reason} &7[{duration}]"
empty: "{prefix}&7No active mutes."
# ── Alts ─────────────────────────────────────────────────────
alts:
header: "{prefix}&7Alt accounts sharing IP with &c{player}&7:"
entry: " &8» &c{name} &7(last seen: {date})"
none: "{prefix}&7No alt accounts found for &c{player}&7."
shared-ip: " &7Shared IP: &f{ip}"
# ── General errors ────────────────────────────────────────────
error:
no-permission: "{prefix}&cYou do not have permission to do that."
player-not-found: "{prefix}&cPlayer &f{player} &cnot found."
console-only: "{prefix}&cThis command can only be run from the console."
player-only: "{prefix}&cThis command can only be run by a player."
invalid-duration: "{prefix}&cInvalid duration: &f{input}&c."
player-exempt: "{prefix}&c{player} &7is exempt from this punishment."
self-punish: "{prefix}&cYou cannot punish yourself."
database-error: "{prefix}&cA database error occurred. Please check the console."
usage: "{prefix}&cUsage: &f{usage}"
unknown-command: "{prefix}&cUnknown command. Type &f/fluxbans help &cfor a list."
# ── FluxBans admin ────────────────────────────────────────────
admin:
reloaded: "{prefix}&aConfiguration reloaded successfully."
import-start: "{prefix}&7Starting import from &c{plugin}&7..."
import-done: "{prefix}&aImport complete. &7Imported &c{count} &7records."
import-failed: "{prefix}&cImport failed: &f{error}"
# ── Web appeal URL ────────────────────────────────────────────
appeal-url: "http://example.com:8080/appeal"
reasons.yml
# ─────────────────────────────────────────────────────────────
# FluxBans — Preset Reasons
#
# Staff can use these with: /ban <player> #hacking
# The # prefix triggers a preset reason lookup.
#
# Fields:
# display — reason text sent to the player and logged in DB
# duration — optional locked duration (staff cannot override)
# type — optional: ban | mute | kick | warn
# ─────────────────────────────────────────────────────────────
hacking:
display: "Hacking / Cheating"
duration: "30d"
type: ban
xray:
display: "X-Ray / Resource pack abuse"
duration: "14d"
type: ban
chat-spam:
display: "Chat spam"
duration: "1h"
type: mute
advertising:
display: "Advertising other servers"
duration: "7d"
type: mute
hate-speech:
display: "Hate speech / Discrimination"
duration: "30d"
type: mute
griefing:
display: "Griefing"
duration: "7d"
type: ban
bug-abuse:
display: "Bug / Exploit abuse"
duration: "7d"
type: ban
inappropriate:
display: "Inappropriate behaviour"
type: warn
ban-evasion:
display: "Ban evasion"
duration: "perm"
type: ban
web.yml
# ─────────────────────────────────────────────────────────────
# FluxBans — Web Server Configuration
# ─────────────────────────────────────────────────────────────
web:
enabled: true
# IP to bind to. Use 0.0.0.0 for all interfaces.
bind: "0.0.0.0"
port: 8080
# Base URL used to generate links shown to players in kick messages.
base-url: "http://example.com:8080"
# ── SSL / HTTPS ──────────────────────────────────────────────
ssl:
enabled: false
keystore-path: "ssl/keystore.jks"
keystore-password: "changeme"
port: 8443
# ── Admin panel ───────────────────────────────────────────────
admin:
# Change this to something secure before going live.
token: "CHANGE_THIS_SECRET_TOKEN"
session-timeout: 60
# Restrict admin panel access to specific IPs (empty = allow all)
allowed-ips: []
# ── Rate limiting ─────────────────────────────────────────────
rate-limit:
appeals-per-hour: 3
searches-per-minute: 30
# ── Theme and branding ────────────────────────────────────────
theme:
mode: dark # "dark" or "light"
server-name: "My Minecraft Server"
accent-color: "e74c3c"
server-description: ""
server-ip: ""
logo-url: ""
discord-url: ""
website-url: ""
# ── Privacy ──────────────────────────────────────────────────
privacy:
anonymise-ips: true
public-appeal-form: true
entries-per-page: 20
# ── SEO ──────────────────────────────────────────────────────
seo:
description: "View active bans, mutes, and submit appeals for our Minecraft server."
keywords: "minecraft ban list, mute list, ban appeal, punishment history"
allow-indexing: true
og-image: ""
twitter-site: ""
webhooks.yml
# ─────────────────────────────────────────────────────────────
# FluxBans — Webhook Configuration
#
# Supported types: discord | generic
#
# Available events:
# ban, unban, mute, unmute, kick, warn,
# appeal_new, appeal_resolved
# ─────────────────────────────────────────────────────────────
webhooks:
- url: "https://discord.com/api/webhooks/YOUR_ID/YOUR_TOKEN"
type: discord
enabled: false
events:
- ban
- unban
- mute
- unmute
- kick
- warn
- appeal_new
- appeal_resolved
# If true, silent punishments will NOT fire this webhook
skip-silent: true
colors:
ban: 15158332 # red
unban: 3066993 # green
mute: 15105570 # orange
unmute: 3447003 # blue
kick: 10181046 # purple
warn: 16776960 # yellow
appeal_new: 3447003 # blue
appeal_resolved: 3066993
- url: "https://your-site.com/api/fluxbans-webhook"
type: generic
enabled: false
events:
- appeal_new
- appeal_resolved
# Optional — signs each request with X-FluxBans-Signature: sha256=<hex>
secret: ""
/fluxbans command
The main admin command. Requires fluxbans.admin.
/fluxbans reload Reloads all config files without restarting
/fluxbans import <plugin> Imports data from another plugin's database
/fluxbans debug Prints version, database status and active connections
Requirements
Java 8 or newer. SQLite is bundled so there's no database server needed for a single server setup. ProtectCord, LuckPerms and Vault are all optional and get picked up automatically if they're present.
Live stats
FluxBans collects anonymous usage statistics via bStats. You can opt out in plugins/bStats/config.yml.


