Skip to Content
PhantomBans is a premium plugin. Get it from the store or join the Discord.
FeaturesNetwork Sync

Network Sync

Keep every backend in a network in step: a ban issued on one server kicks the player off the others within seconds, and announcements show everywhere.

PhantomBans already enforces punishments on every backend that shares the same database: a banned player is denied login wherever they connect, and a muted player is blocked from chat. Network sync closes the remaining gaps so a punishment is felt instantly across the whole network instead of only on the server where it was run.

Network sync is opt-in and off by default. A single-server install needs to do nothing: leave it disabled and PhantomBans behaves exactly as before.

What it adds

With sync enabled on every backend, a punishment issued on one server now does all of this across the whole network, not just locally:

  • Kick on ban. A player online on another backend is kicked the moment they are banned or IP-banned, with the ban screen, instead of staying on until they relog.
  • Network-wide announcements. Ban, mute, unban, and unmute broadcasts show on every backend.
  • /muteall propagation. Locking or unlocking global chat on one server does the same on the others.
  • Fresh history everywhere. A backend drops its cached lookup for a player the instant they are punished elsewhere, so /history and /lookup never lag behind.

Silent punishments stay silent network-wide: a -s ban or mute is only ever shown to staff with phantombans.silent.see, on every backend, and is never publicly broadcast.

Requirements

Network sync requires a shared MySQL or MariaDB database. SQLite is single-server only: if you enable the network layer while on SQLite, the console logs a warning and nothing syncs.

Every backend must run PhantomBans and point at the same MySQL/MariaDB database (database.type: mysql plus credentials in config.yml). The sync layer rides on that shared database: there is no extra service to run.

Configuration

Network settings live in their own file, network.yml, generated on first run with sync disabled.

network: enabled: false # master switch; leave false for a single server server-name: "" # MUST be unique per backend; blank falls back to general.server-name sync: db-poll # transport (database polling) poll-interval: 3 # seconds between checks for other backends' actions proxy-gating: false # set true only when running the proxy companion

To turn sync on, set enabled: true and give each backend a unique server-name, then /pb reload (or restart).

network: enabled: true server-name: "hub" # e.g. hub, survival, creative; different on every backend sync: db-poll poll-interval: 3 proxy-gating: false

Transports

sync selects how backends learn about each other’s actions:

  • db-poll (default): every backend polls the shared database. No extra infrastructure, runs on what you already have. This is the supported, tested path.
  • redis (experimental): publishes events to a Redis channel for near-instant fan-out and lower database load. Needs a Redis server reachable by every backend.

Redis is experimental and untested. It is wired up and selectable, but it has not been verified on a live network. Use db-poll for production. If you select redis, configure it under the redis block in network.yml:

network: sync: redis redis: host: "127.0.0.1" port: 6379 password: "" # blank = no auth channel: "phantombans:sync" # must match on every backend

server-name must be different on every backend. It is how each server tells its own actions apart from the others; if two backends share a name, they will ignore each other’s punishments. Operator-enforced: PhantomBans does not police uniqueness for you.

Settings

KeyDefaultWhat it does
enabledfalseMaster switch for the sync layer.
server-name""This backend’s unique id. Blank falls back to general.server-name in config.yml.
syncdb-pollTransport: db-poll (default, tested) or redis (experimental, see above).
poll-interval3Seconds between checks for other backends’ actions. Lower is snappier and hits the database more often.
proxy-gatingfalseSet true only when running the proxy companion: the backend then defers the ban screen to the proxy. Leave false otherwise.

How it works

Each backend logs its own actions

When a punishment is issued (or a mute-all toggled), the originating backend writes a small event row to a shared vg_sync table, stamped with its server-name.

The others replay it

Every poll-interval seconds, each backend reads new rows, skips the ones it wrote itself, and replays the rest: kicking a banned player who is online, showing the broadcast, propagating a mute-all, and dropping stale history cache.

Consumed rows are pruned

Old, already-processed rows are cleaned out of vg_sync automatically, so the table stays small.

Both the network.yml file and the vg_sync table are created automatically. Existing configs are untouched, so there is nothing to delete or regenerate when you upgrade.

Limits in this release

  • Mute-all state is per backend, in memory. A backend that starts after a /muteall was issued elsewhere does not pick up the existing lock until the next /muteall.
  • server-name uniqueness is on you. PhantomBans trusts the names you set; duplicates silently break sync between those backends.

A redis transport ships as an experimental option (see Transports above). To reject banned players at the proxy edge, add the proxy companion and set proxy-gating: true.

Last updated on