Corestone

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

  1. Put the same AdminControl.jar in the proxy's plugins/ folder. One jar works on Paper, Purpur, Folia, Spigot, Velocity and BungeeCord (see BungeeCord network for that proxy).

  2. Start the proxy once. It creates plugins/admincontrol/config.yml and tries the database in it (localhost, no password): until you set yours, the log says Could not open the shared database and punishments are not checked on the proxy.

  3. In plugins/admincontrol/config.yml on 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 set ssl-ca to the database's CA certificate: use-ssl alone 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: true
    
  4. Every server behind the proxy runs AdminControl with database.type: mysql and the same database.

  5. Restart the proxy and run /ac version on its console: it shows Database: mysql, ready when the proxy reaches the database. With database.type: sqlite AdminControl 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 in forwarding.secret.
  • Each server, config/paper-global.yml: under proxies.velocity set enabled: true, online-mode: true and secret to the same secret. In server.properties set online-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.toml set player-info-forwarding-mode = "bungeeguard"; Velocity sends the secret from forwarding.secret as 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-commands on the servers only. Commands and chat that a plugin on the proxy handles (a /msg or global chat plugin on Velocity) are not blocked for muted players.
  • Tab completion of /ac on the network lists only the proxy commands; /ac link and /ac report still work when typed in full.
  • Settings, announcements, reports, the chat and the console are per server, as described in Database.