A Minecraft proxy puts one address in front of several servers. Players connect to mc.example.com, land in a lobby, and move between a survival world, a creative world and a minigame server with /server survival or by walking into a portal - without ever disconnecting, retyping an address or seeing a loading screen that says "connecting to server". Velocity is the proxy to use. It is fast, actively maintained, and its modern forwarding mode is the only one that is secure by default.
This is the whole setup: what the proxy does and does not do, the velocity.toml that matters, the forwarding secret and why every network breaks on it once, what to change on each backend, and how permissions and chat get shared when each backend is a separate Minecraft server with its own idea of who you are.
What a proxy is for, and when you do not need one#
A proxy is a Minecraft-protocol reverse proxy. It terminates the player's connection, authenticates them once, and then opens its own connection to whichever backend they should be on, relaying packets in both directions. Switching servers is the proxy closing one backend connection and opening another while holding the player's connection open.
What that buys you:
- One address and one port for a network of any size, so players never learn more than
mc.example.com. - Instant switching between worlds that are separate server processes, each with its own memory, its own plugins and its own tick.
- Independent scaling. The minigame server can restart without anybody leaving the network, and a laggy survival world does not slow the lobby.
- Larger total player counts than one process can tick, because the work is spread across several JVMs.
- A single place to run network-wide things: cross-server chat, a queue, Bedrock translation, protocol translation for older clients.
What it does not buy you. A proxy does not make one server faster - a 40-player survival world is exactly as heavy behind a proxy as it is in front of one. It does not share inventories, homes, balances or advancements; each backend keeps its own player data unless you add something that syncs it. And it does not translate versions: the client and the backend it is talking to must still be the same Minecraft version, which is what ViaVersion on the proxy is for.
The honest test for whether you need one: if you have a single world and fewer than about forty players, you do not. Fix the tick first with the Paper optimisation guide. A proxy is for when you want several distinct experiences under one name, or when one process genuinely cannot carry the players.
Velocity, BungeeCord and Waterfall#
Three names come up, and only one of them is a current answer.
Velocity is a from-scratch proxy with its own plugin API, built for throughput and for security. Modern forwarding, its default recommendation, passes the player's real identity to the backend inside a signed payload, so a backend can refuse anything that did not come through the proxy. Velocity 3 needs Java 17 or newer.
BungeeCord is the original, still maintained, and still very widely deployed. Its forwarding mode is unauthenticated: the backend simply trusts whatever identity the connection claims, which is why every BungeeCord network needs a firewall or the BungeeGuard plugin in front of its backends. Velocity can speak this mode when it has to, as legacy or bungeeguard.
Waterfall was PaperMC's BungeeCord fork. It is no longer maintained, and PaperMC's own advice is to move to Velocity. Do not start a new network on it.
Plugins do not move between these. A BungeeCord plugin will not run on Velocity, and neither will a Bukkit or Paper plugin - the proxy is not a Minecraft server and has no worlds, blocks or entities to offer a plugin API for. Most established network plugins ship both a BungeeCord and a Velocity build.
Installing Velocity and the config that matters#
Velocity is a jar. Download it from the PaperMC downloads page, put it in an empty directory, and run it once to generate the config:
$ java -Xms512M -Xmx512M -XX:+UseG1GC -XX:MaxGCPauseMillis=100 \ -jar velocity.jarHalf a gigabyte of heap carries a few hundred players comfortably. A proxy holds no world and almost no state; what it spends is CPU on packet compression and encryption, so a core matters more than memory. Size the proxy small and the backends properly.
The generated velocity.toml is well commented. These are the lines to change:
bind = "0.0.0.0:25565"motd = "<gradient:#5A9BD5:#FFFFFF>The Longhouse Network</gradient>"show-max-players = 200online-mode = trueforce-key-authentication = trueplayer-info-forwarding-mode = "modern"forwarding-secret-file = "forwarding.secret"kick-existing-players = falseping-passthrough = "disabled"[servers]lobby = "10.0.0.11:25566"survival = "10.0.0.12:25567"minigames = "10.0.0.13:25568"try = ["lobby"][forced-hosts]"survival.example.com" = ["survival"]"minigames.example.com" = ["minigames"][advanced]compression-threshold = 256failover-on-unexpected-server-disconnect = truelog-player-connections = true[query]enabled = falseport = 25577Notes on the ones that catch people:
online-mode = truebelongs on the proxy, and only on the proxy. This is the single authentication point for the whole network. Backends run with it off, because they are not reachable by players directly.player-info-forwarding-mode = "modern"is the setting this whole post is about. It requires Paper 1.13 or newer on the backend. For 1.12.2 and older backends you need"legacy"or"bungeeguard"instead, with the extra care those modes demand.try = ["lobby"]is the ordered list of servers a player is sent to on connect. Put a second entry in it and the proxy falls through when the first is down.[forced-hosts]routes by the hostname the player typed, sosurvival.example.comdrops them straight into survival with no lobby stop. Each entry needs its own DNS record pointing at the same proxy.ping-passthrough = "disabled"means the server list entry shows the proxy's own MOTD and player count. Set it to"description"or"all"if you would rather show a backend's.kick-existing-players = falsemeans a second login with the same account is refused. Setting it totruekicks the older session instead, which is what you want if players regularly get stuck as ghosts after a network hiccup.- Velocity's
motduses MiniMessage formatting, not the legacy section codes you use inserver.properties. Gradients and hex colours work here and do not work there.
Modern forwarding and the secret file#
Modern forwarding is what makes the network safe without a firewall. When the proxy connects to a backend, it sends the player's real UUID, name, skin properties and address inside a payload signed with a shared secret. A backend configured for modern forwarding refuses any connection that does not carry a valid payload, which means a player who discovers a backend's address and port cannot join it directly.
The secret lives in a file next to velocity.toml, named by forwarding-secret-file. Velocity generates one on first start. Read it, and put the same string on every backend.
$ cat forwarding.secretkC7pQ2mZ9vXb4TfROn Paper backends, the secret goes in config/paper-global.yml:
proxies: velocity: enabled: true online-mode: true secret: 'kC7pQ2mZ9vXb4TfR'Set online-mode here to match the proxy's own online-mode, which should be true. This tells Paper whether the identities arriving through the proxy were actually verified with Mojang.
Modern forwarding needs Paper, or Fabric and Forge with the appropriate proxy-compatibility mod. Plain Spigot cannot do it. If your backend is not Paper, either move it to Paper or accept legacy forwarding with BungeeGuard and a firewall.
What to change on each backend#
Every backend is an ordinary Minecraft server with four edits.
server-port=25566online-mode=falseenforce-secure-profile=falsenetwork-compression-threshold=-1view-distance=6online-mode=false is correct here and only here. The proxy did the authentication; the backend takes the identity from the signed forwarding payload. This is the one legitimate use of the setting, and it is safe precisely because Paper's Velocity support rejects connections without a valid payload. If you set online-mode=false without enabling Velocity forwarding on the backend, you have an open server that anyone can join as anyone.
enforce-secure-profile=false stops the backend demanding a signed chat profile it cannot verify itself.
network-compression-threshold=-1 disables compression between the proxy and the backend. This is worth doing when they are on the same machine or the same local network, because the proxy already compresses the traffic going out to players and compressing twice just burns CPU. If the backends are across the internet from the proxy, leave it at 256.
Give each backend a different port, and give the lobby a much smaller footprint than the survival world: view-distance=5, simulation-distance=4, gamemode=adventure, spawn-protection large enough to cover the build, and 1-2 GB of memory. A lobby with nothing to simulate does not need what a survival world needs.
Permissions, chat and player data across servers#
This is the part that surprises people who expected a proxy to make several servers behave like one. It does not. Each backend has its own world/playerdata, its own ops.json, its own plugin databases. Log in to survival and you are a different person from the one who was in the lobby a second ago, as far as those files are concerned.
What you actually share, and how:
- Permissions. Run LuckPerms on every backend, point all of them at the same database instead of local files, and enable its messaging so a change propagates without restarts. This is the standard solution and it works well. The LuckPerms guide covers groups, inheritance and the contexts that let a rank mean something different per server. On RE:NODE, a database slot is included on game plans - the panel generates the host, user and password - and if you would rather run the network's database separately, database hosting offers PostgreSQL, which LuckPerms supports directly.
- Chat. A cross-server chat plugin on the proxy, or on every backend with a shared channel. Without one, each backend's chat is an island.
- Player inventories and balances. Only with a plugin that explicitly syncs them, and every such plugin has an item-duplication failure mode when a server crashes mid-transfer. The safer design is to not share inventories at all: give the lobby nothing, give each gamemode its own economy, and accept that survival gear stays in survival. EssentialsX and a shared economy covers the database-backed option when you do need one.
- Whitelists. With modern forwarding the real UUID reaches each backend, so per-backend
whitelist.jsonworks normally. A network-wide whitelist is easier to manage from the proxy with a plugin.
Velocity's own commands are short, and each has a permission node so you can hand them out through LuckPerms:
| Command | Permission | What it does |
|---|---|---|
/server | velocity.command.server | List servers, or move yourself |
/server <name> | velocity.command.server | Move to a named backend |
/glist | velocity.command.glist | Players per backend |
/send <player> <server> | velocity.command.send | Move someone else |
/velocity reload | velocity.command.reload | Re-read velocity.toml |
/velocity info | velocity.command.info | Version and build |
/velocity dump | velocity.command.info | Upload an anonymised config dump |
/velocity reload picks up added and removed servers without dropping connected players, which makes adding a fourth backend a non-event.
Ports, addresses and the public face#
| What | Port | Exposed to |
|---|---|---|
| Velocity | 25565 TCP | The internet |
| Lobby backend | 25566 TCP | The proxy |
| Survival backend | 25567 TCP | The proxy |
| Minigames backend | 25568 TCP | The proxy |
| Velocity query | 25577 UDP | Status sites, optional |
Point an A record at the proxy, then add an SRV record so players type mc.example.com with no port at all. SRV records for Minecraft has the exact record and the common mistakes; subdomains for servers covers the per-backend hostnames that [forced-hosts] needs. Backends need no public DNS at all, and giving them memorable hostnames only helps people find them.
A network on a panel host is one paid server per process, which is worth saying plainly: a proxy plus three backends is four servers. The proxy is the cheapest of them because it needs so little memory. RE:NODE's Minecraft plans start at 2 GB with one port allocation each, and more ports can be added on the Network tab; the panel's per-server SFTP credentials and file editor are what you will use to push the same forwarding.secret to each backend, and the Schedules tab can restart the minigames server nightly without anybody noticing, because the proxy keeps everyone connected.
For Bedrock players, Geyser and Floodgate run on the proxy rather than on each backend, which is one of the better arguments for putting a proxy in front of even a single server - see Geyser and Bedrock crossplay.
What breaks, and what the error looks like#
`Your server did not send a forwarding request to the proxy. Is it set up correctly?` in the Velocity console. The backend is not configured for modern forwarding: proxies.velocity.enabled is still false, or the backend is not Paper, or it was not restarted after the change.
Players are kicked immediately with a forwarding or decoder error. The secret does not match. Compare the two strings character for character, and check for a trailing newline in the file or a space picked up by the copy.
`Unable to connect you to survival` shown to the player, with a connection-refused exception in the proxy log. The backend is down, on a different port, or bound to an address the proxy cannot reach. Test with the backend's address and port from the proxy's own shell before blaming forwarding.
Direct connection to a backend succeeds. Stop and fix this before you announce anything. It means forwarding is off or misconfigured on that backend, and with online-mode=false anyone can join it as any player - including an operator.
Everybody appears as a new player with no inventory. UUIDs are arriving in offline-mode form, which means forwarding is not actually working even if players can connect. This is what legacy forwarding without BungeeGuard looks like, and it is why the mode matters.
`You are already connected to this proxy!` A ghost session from a dropped connection. kick-existing-players = true in velocity.toml makes the new login win.
Version mismatch on one backend after an upgrade. Velocity relays protocol, it does not translate it. A 1.21 client cannot join a 1.20 backend through a proxy any more than it can directly. Either keep every backend on the same version or put ViaVersion on the proxy. Minecraft version upgrades covers doing it in the right order, which on a network is proxy plugins first, lobby next, everything else after.
Plugin messaging stops working. Anything using the BungeeCord plugin channel needs bungee-plugin-message-channel = true in the [advanced] section, which is the default. Plugins that used it for commands rather than data are the usual casualties.
FAQ#
Do I need a proxy for two servers?
Only if you want players to move between them without disconnecting, or you want both behind one address. Two separate addresses cost nothing and break nothing. The proxy earns its place when switching has to be seamless or when a lobby is part of the experience.
Does a proxy reduce lag?
No. Every packet takes one extra hop, so latency goes up slightly. What a proxy does is let you split work across several processes, so each one has a whole tick budget to itself. If one world is lagging, the proxy will not help it.
Can I run Velocity on the same machine as a backend?
Yes, and it is a normal setup. Give the proxy its own small container or process, bind the backend to a port the proxy can reach, and set network-compression-threshold=-1 on the backend since the traffic never leaves the machine.
Is online-mode=false on the backends safe?
Only with forwarding configured and verified. With modern forwarding enabled on a Paper backend, connections that do not carry a valid signed payload from your proxy are rejected, so the backend is not open. Without it, an offline-mode backend with a public port is the most dangerous configuration in Minecraft hosting.
How do I share inventories between servers?
With a plugin that explicitly syncs them to a shared database, and with the knowledge that every such plugin can duplicate items if a server dies at the wrong moment. Many well-run networks deliberately do not share inventories, giving each gamemode its own, which removes the failure mode entirely.
Should I use BungeeCord instead?
Not for a new network. Velocity is faster, its modern forwarding is secure without extra plugins, and it is the proxy PaperMC points people at now that Waterfall is finished. The only reason to choose BungeeCord is a plugin you cannot do without that has no Velocity build.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.