Velocity network
On a network behind a Velocity proxy, AdminControl applies punishments across all servers: a banned player cannot join the network, and a kick or ban given on one server takes the player off the whole network. Supported: Velocity 3.5 and 4.x.
What you need
- Velocity 3.5 and 4.x (tested on 3.5.1 and 4.3.0). Velocity 3.5 runs on Java 21 or newer, Velocity 4.x needs Java 25.
- A MySQL or MariaDB database shared by the proxy and every server behind it (see Database). SQLite cannot be shared: a server on SQLite keeps its punishments to itself.
- Modern player info forwarding between the proxy and the servers (below).
Install
Put the same
AdminControl.jarin the proxy'splugins/folder. One jar works on Paper, Purpur, Folia, Spigot, Velocity and BungeeCord (see BungeeCord network for that proxy).Start the proxy once. It creates
plugins/admincontrol/config.ymland tries the database in it (localhost, no password): until you set yours, the log saysCould not open the shared databaseand punishments are not checked on the proxy.In
plugins/admincontrol/config.ymlon the proxy, enter the database every server uses. When the proxy and the database are on different machines, connect them over a private network or a tunnel, or setssl-cato the database's CA certificate:use-sslalone encrypts the connection but does not check the database's certificate.# en or pl: the ban screen and the replies of /ac on the proxy. language: en # A name for this proxy in the logs. server-name: proxy database: type: mysql mysql: host: db.example.com port: 3306 database: admincontrol user: admincontrol password: "a-long-random-password" pool-size: 4 use-ssl: trueEvery server behind the proxy runs AdminControl with
database.type: mysqland the same database.Restart the proxy and run
/ac versionon its console: it showsDatabase: mysql, readywhen the proxy reaches the database. Withdatabase.type: sqliteAdminControl does not start on the proxy and says why in the log.
The proxy has no panel: the panel of any server shows the whole network (see Network panel).
Modern forwarding
Without forwarding, the servers see every player at the proxy's address (127.0.0.1): IP bans and "other accounts
from the same address" stop working, and AdminControl refuses IP bans of such players so it does not lock everyone
out. Turn on modern forwarding with a secret:
- Velocity,
velocity.toml:player-info-forwarding-mode = "modern"; the secret is inforwarding.secret. - Each server,
config/paper-global.yml: underproxies.velocitysetenabled: true,online-mode: trueandsecretto the same secret. Inserver.propertiessetonline-mode=false.
Keep the secret private and do not let players reach the servers' ports directly, only through the proxy.
Spigot servers have no modern forwarding; they take the BungeeCord form (bungeecord: true in each server's
spigot.yml). Velocity has BungeeGuard built in:
- In
velocity.tomlsetplayer-info-forwarding-mode = "bungeeguard"; Velocity sends the secret fromforwarding.secretas the token. - Install BungeeGuard on each Spigot server and put the same secret in its
allowed-tokens.
player-info-forwarding-mode = "legacy" has no secret at all: use it only when the servers' ports are closed to
everything but the proxy. A server in BungeeCord mode without BungeeGuard is flagged in the panel with
Unsecured forwarding (see BungeeCord network, "Securing the servers").
Behind a load balancer or a DDoS shield (TCPShield and the like) the proxy sees the shield's address unless it is
told the real one. Turn on haproxy-protocol = true in velocity.toml only when the shield sends the PROXY
protocol, and then let only the shield reach the proxy's port: anyone who can reach it directly can claim any
address, dodge IP bans or get someone else's address banned. Without either, every player has the shield's address
and one IP ban takes the whole network off.
What happens where
| Punishment | On the proxy | On the servers |
|---|---|---|
| Ban, IP ban | Checked when a player joins the network; a new ban takes the player off the network. An IP ban also disconnects everyone else from that address. | Checked on join, as without a proxy. |
| Kick | Takes the player off the network. | Kicks the player, as without a proxy. |
| Mute | Not enforced (signed chat cannot be cancelled safely on the proxy). | Enforced on every server. |
| Warning | Nothing. | The player is told on the server they are on. |
A punishment given on one server or on the proxy reaches the others within about 2 seconds. Lifting a punishment reaches them the same way. A kick read only after the log could not be read for over a minute (the database or that server was away) is left out, as the player may have come back since.
If the database is down or the check takes longer than 3 seconds, the proxy decides with the bans it keeps in
memory, the same as a server does (see Database, "When the database is down"): a banned player is
refused, anyone else gets in, and the log says checked against the in-memory list. Only when that list was never
read does the proxy let the player in and log letting them in. The server the player joins checks the ban as well.
Commands on the proxy
The same commands as on the servers, run on the proxy console or by a player anywhere on the network:
| Command | What it does | Who |
|---|---|---|
/ac help |
List of commands. | admincontrol.command |
/ac version |
Plugin version, license, database and how far the punishment log has been read. | admincontrol.command |
/ac ban <player> <reason> |
Permanent ban. | punishment rights |
/ac tempban <player> <time> <reason> |
Timed ban. | punishment rights |
/ac ipban <player> <reason> |
Permanent IP ban. | punishment rights |
/ac tempipban <player> <time> <reason> |
Timed IP ban. | punishment rights |
/ac mute <player> <reason> |
Permanent mute. | punishment rights |
/ac tempmute <player> <time> <reason> |
Timed mute. | punishment rights |
/ac warn <player> <reason> |
Warning. | punishment rights |
/ac kick <player> <reason> |
Kick from the network. | punishment rights |
/ac unban <player> [reason] |
Lift a ban (also an IP ban). | punishment rights |
/ac unmute <player> [reason] |
Lift a mute. | punishment rights |
/ac unwarn <player> [reason] |
Lift the newest warning. | punishment rights |
/ac punish <player> <template> [reason] |
Punish with a template: the player's next escalation step. | punishment rights |
/ac history <player> |
A player's 10 latest punishments. | punishment rights |
/ac rollback and /ac restore (CoreProtect, admincontrol.rollback) are not proxy commands: CoreProtect runs on
the servers, so a player's /ac rollback goes on to the server they are on, and the proxy console does not run them.
/ac ban <player> -r <time> on the proxy answers that CoreProtect is not available there; use the panel or a
server's console.
Punishment rights are the same as on the servers: the proxy console may do everything; a player needs
admincontrol.punish and a linked panel account, and their panel role sets what they may do.
The proxy runs a player's /ac command only when the player has these permissions on the proxy. Velocity has no
operators, so give admincontrol.command and admincontrol.punish with a permissions plugin on the proxy (for
example LuckPerms for Velocity). Everything else a player types under /ac (/ac link, /ac report,
/ac reload, or a punishment without proxy permissions) goes on to the server the player is on, which checks its
own permissions as before. The proxy console runs only the commands above. Players are found by name among those online on the network and
those the servers have seen.
Known limitations
- A mute blocks chat and the
mute-blocked-commandson the servers only. Commands and chat that a plugin on the proxy handles (a/msgor global chat plugin on Velocity) are not blocked for muted players. - Tab completion of
/acon the network lists only the proxy commands;/ac linkand/ac reportstill work when typed in full. - Settings, announcements, reports, the chat and the console are per server, as described in Database.