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.
/muteallpropagation. 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
/historyand/lookupnever 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 companionTo 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: falseTransports
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 backendserver-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
| Key | Default | What it does |
|---|---|---|
enabled | false | Master switch for the sync layer. |
server-name | "" | This backend’s unique id. Blank falls back to general.server-name in config.yml. |
sync | db-poll | Transport: db-poll (default, tested) or redis (experimental, see above). |
poll-interval | 3 | Seconds between checks for other backends’ actions. Lower is snappier and hits the database more often. |
proxy-gating | false | Set 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
/muteallwas issued elsewhere does not pick up the existing lock until the next/muteall. server-nameuniqueness 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.