Configuration
Configuration Overview
XBans is configured through config.yml located in plugins/XCore/addons/XBans/. The configuration is organized into logical sections covering each feature.
Most configuration changes can be applied with /xbans reload without a server restart. The exception is database table structure changes, which require a restart.
General Settings
# Enable debug logging
debug: false
# Cooldowns (in ms)
cooldowns:
chat: 2_000
command: 2_000
# Default warn duration
warn-duration: 30d
# Report duration
report-duration: 30d
# Require a reason for sanctions (ban, mute, warn, kick)
require-reason: false
# Max reports per player (prevents report spam)
max-reports-per-player: 5
# Cooldown between reports from same player (in ms)
report-cooldown-ms: 30_000
# Auto-purge inactive sanctions older than X days (0 = disabled)
auto-purge-days: 90
# Anonymous moderator (hides moderator name in broadcasts; Discord still shows real name)
anonymous-moderator: false
# Appeal URL shown on the ban kick screen (empty = no appeal line)
appeal-url: ""
The broadcast-permissions map (see below) controls who sees public sanction broadcasts per sanction type — leave a value empty to broadcast to everyone, or set a permission to restrict the broadcast to those who hold it.
Broadcast Permissions
broadcast-permissions:
ban: ""
mute: ""
kick: ""
warn: "xbans.notify.warn"
report: "xbans.notify.report"
Empty value means "broadcast to all players". Setting a permission restricts who sees the broadcast. Common patterns:
- Public bans, private warns/reports — Default config. Bans, mutes, and kicks are shown to everyone (deterrent effect); warns and reports stay quiet.
- All private — Set every value to
"xbans.notify.staff"for a staff-only experience. - Use
-sper-command — Even with public defaults, individual sanctions can be issued silently with the-sflag.
Jail Configuration
jail:
enabled: true
# Default jail duration (empty = permanent)
default-duration: "1d"
# Radius around jail point where player can move (in blocks, 0 = stuck in place)
move-radius: 5
# Restrictions (true = blocked)
restrictions:
chat: false
commands: true
interact: true
drop-items: true
pvp: true
# Whitelisted commands when jailed (only if commands restriction is true)
allowed-commands:
- "/msg"
- "/r"
# Restore player's previous location on unjail
restore-location: true
# Exempt permission
exempt-permission: "xbans.exempt.jail"
Jail locations themselves are not stored in config.yml — they live in a separate file managed by /jail-create, /jail-delete, and /jail-locations.
When restore-location is true, XBans saves the player's exact position before teleporting them to jail. Upon release, they are teleported back to that saved location. If false, released players stay at the jail location.
Auto-Sanctions
The auto-sanctions system automatically escalates a player to a heavier sanction when they accumulate too many active warnings:
auto-sanctions:
enabled: false
thresholds:
3: "mute 1d"
5: "ban 3d"
10: "ban"
The action format is "<type> [duration]" where the type is one of ban, mute, or jail. Omit the duration for a permanent sanction. The action is automatically applied to the warned player — no {player} placeholder is needed.
For escalations triggered by reports rather than warnings, see auto-report-escalation:
auto-report-escalation:
enabled: false
thresholds:
3: "warn {player} Multiple reports received"
5: "mute {player} 1d Too many reports"
10: "ban {player} 7d Excessive reports"
Unlike auto-sanctions, this section uses raw command strings with the {player} placeholder — so any XBans sanction command (including jail) is valid here.
Regex-based escalation is also available via reason-escalation for upgrading sanctions whose reason matches a pattern (e.g., upgrade any reason containing "hack" to a permanent ban).
Templates & Predefined Reasons
# Predefined reasons (tab-complete suggestions)
reasons:
- "Cheating"
- "Bug exploitation"
- "Sanction evasion"
- "Toxic behavior"
# Predefined durations (tab-complete suggestions)
durations:
- "6h"
- "12h"
- "1d"
- "3d"
- "1w"
- "1M"
# Sanction templates (shortcuts for common sanctions)
# Usage: /ban <player> @template_name
templates:
cheat: "ban 30d Cheating"
hack: "ban Hacking - Permanent"
spam: "mute 1d Spam / Flood"
toxicity: "mute 12h Toxic behavior"
evasion: "ban 60d Sanction evasion"
reasons and durations populate the tab-completer for sanction commands. templates are full-action shortcuts invoked with @name — see the Sanctions page for usage examples.
IPInfo Configuration
ipinfo:
enabled: false
token: ""
# Cache duration for IP lookups (in minutes)
cache-duration: 60
The cache prevents redundant API calls for the same IP address. Players reconnecting within the cache window are checked against the cached result instead of making a new API request.
Blocking rules are configured in the consolidated ip-security section (see below).
IP Security Configuration
All IP-based security rules (VPN, hosting/datacenter, mobile, ISP, and IP range blocking) are consolidated under a single ip-security section:
ip-security:
vpn:
enabled: false
bypass-permission: "xbans.bypass.vpn"
hosting:
enabled: false
bypass-permission: "xbans.bypass.hosting"
mobile:
enabled: false
bypass-permission: "xbans.bypass.mobile"
isp:
enabled: false
blocked-isps: []
ip-range:
enabled: false
blocked-ranges: []
Each sub-section can be independently enabled or disabled. The bypass-permission fields allow specific players to connect even when blocking is active (e.g., staff members using a VPN). ISP and IP range blocking do not require the IPInfo API but benefit from having it enabled for accurate ISP name resolution.
GeoIP Country Blocking
geoip:
enabled: false
# Block mode: "whitelist" (only allow listed countries) or "blacklist" (block listed countries)
mode: "blacklist"
countries:
- "XX"
# Whitelist mode only: refuse a login when the country cannot be resolved. Off means those
# players get in, which is what happens during a join wave if the provider rate limits us.
fail-closed: false
# ip-api | ip-api-pro | proxycheck | ipinfo
provider: "ip-api"
# Key or token for the provider above
api-key: ""
# Keep the country / ISP / VPN line in the warden report when nothing else needs lookups
warden-info: false
Country codes follow ISO 3166-1 alpha-2 (e.g., FR, US, BR).
A lookup can fail or be rate limited. In blacklist mode that means the player gets in, which is the right default. In whitelist mode it means the rule did not run at all — set fail-closed: true to refuse those logins instead. Either way the console says so.
Choosing a provider
| Provider | Transport | Key | Reports |
|---|---|---|---|
ip-api | Plain HTTP | None | Country, ISP, VPN / hosting / mobile |
ip-api-pro | HTTPS | Paid | Same as above |
proxycheck | HTTPS | Free | Country, ASN, VPN / proxy — no mobile flag |
ipinfo | HTTPS | Free | Country and ISP only — VPN and hosting need a paid plan |
The free ip-api tier answers over plain HTTP, and that answer decides who gets banned: anyone able to tamper with the server's outbound traffic decides it for you. Fine for a country filter you treat as advisory, wrong for VPN blocking. Enabling a check the chosen provider cannot answer — VPN blocking on ipinfo, say — is logged at startup rather than silently letting every player through.
When lookups happen
Never for their own sake. An address is resolved only when something reads it: country blocking above, one of the ip-security checks, or alt-detection risk scoring. With all of them off, no request leaves the server — the warden information line alone does not justify a third-party call per address, which is what warden-info is for.
Lookups and caching
An address is resolved once, during the asynchronous pre-login. Everything that runs later — the country and VPN checks, the warden line, the alt-detection fingerprint — reads the cached answer, so no lookup ever blocks the server thread.
- Successful lookups are cached for 6 hours; a proxy or hosting flag can change, so they do not live forever
- Failed lookups are cached for 5 minutes, so an outage of the provider does not cost a timeout on every single login
- Outbound requests are capped at 40 per minute to stay under ip-api's free-tier quota (exceeding it gets the server's own address blocked for an hour)
Without api-key, ip-api's free tier is queried over plain HTTP. Its answer decides who gets blocked for VPN, hosting or country, so anyone able to tamper with your server's outbound traffic can influence that decision. Set an ip-api pro key to move the lookups to HTTPS.
Client & Version Security
client-security:
enabled: false
log-brands: true
show-in-warden: true
blocked-brands: []
# - "wurst"
# - "meteor"
allowed-brands-only: [] # whitelist mode (leave empty to use blocked-brands)
blocked-versions: [] # specific protocol numbers to block
min-protocol-version: 0 # 0 = no minimum
max-protocol-version: 0 # 0 = no maximum
Whitelist vs blacklist: if allowed-brands-only contains entries, it acts as a whitelist and blocked-brands is ignored. Otherwise, blocked-brands acts as a blacklist. Brand matching is case-insensitive partial match.
For protocol version numbers, see wiki.vg/Protocol_version_numbers.
AI Moderation Configuration
The AI moderation has two layers: the core ai-classifier (the Bayesian engine) and chat-ai (the chat-message moderation policy that uses it). Both can be configured independently.
ai-classifier:
enabled: true
min-confidence: 0.5
show-in-warden: true
auto-train-on-action: true
auto-train-on-sanction: true
chat-ai:
enabled: true
min-confidence: 0.4
monitored-categories:
toxicity:
reset-after: "1d"
actions:
1: "warn {player} {reason}"
3: "mute {player} 1h {reason}"
10: "ban {player} 7d {reason}"
spam:
reset-after: "6h"
actions: { ... }
scam:
reset-after: "0"
actions: { ... }
notify-warden: true
log-flagged: true
history-size: 50
report-evidence-action: "none"
report-evidence-min-flagged: 2
The min-confidence setting is critical for balancing false positives and false negatives:
- Lower (0.3-0.5) — More aggressive. Catches more borderline messages but may flag sarcasm or jokes.
- Higher (0.6-0.8) — More lenient. Only catches clearly toxic messages. Fewer false positives.
report-evidence-action is a second-layer feature: when a player is reported, XBans scans their recent messages (up to history-size) and counts AI-flagged ones. If report-evidence-min-flagged is reached, the configured action runs (e.g., "mute {player} 1h Toxic messages detected via report").
Discord Configuration
discord:
enabled: false
webhook-url: ""
notify-on:
- ban
- ban-ip
- mute
- kick
- report
- warn
The notify-on list controls which event types trigger a Discord webhook. Remove an entry to silence that event type. See the Discord Integration page for detailed setup instructions.
Alt-Detection Configuration
alt-detection:
risk-scoring:
enabled: false
shared-ip-score: 30
same-client-brand-score: 15
same-country-score: 5
# Threshold to trigger warden alert
alert-threshold: 30
# Threshold to trigger auto-action
action-threshold: 50
# Auto action when threshold reached: "kick", "ban <duration>", or empty for none
auto-action: ""
# Maximum alts per IP before auto-action (0 = disabled)
max-alts-per-ip: 0
# Action when max alts exceeded: "kick" or "ban <duration>"
max-alts-action: "kick"
shared-ip-detection:
enabled: true
auto-ban-shared-ip: false
whitelist-ranges:
- "127.0.0.*"
Two complementary systems: risk-scoring assigns weighted points to multiple factors and triggers actions when thresholds are reached, while shared-ip-detection handles the simpler case of "this IP was used by a banned player". The whitelist-ranges list prevents false positives on shared infrastructure (NAT, school networks, etc.).