By the end of this guide you'll have a working Minecraft network: a Velocity proxy sitting in front of several Paper servers, with players landing in a lobby and hopping over to survival or minigames without ever rejoining. This is for anyone running Paper who wants more than a single world, and you'll need basic comfort with editing config files and starting a server from the console.
What a proxy network actually is
On a normal setup, one server holds everything. Your spawn, your survival world, your minigames, all crammed together. That works until it doesn't. Big worlds and lots of plugins make a single server heavy, and a restart kicks everyone off at once.
A proxy network splits the work. Players connect to one address, but behind that address sits a small program called a proxy. The proxy doesn't run a world of its own. It just routes each player to a real backend server. So you might have a tiny lobby server, a beefy survival server, and a minigames server, all running as separate processes. Players move between them instantly, and you can restart minigames without touching survival.
Velocity is the proxy we'll use. It's modern, fast, and the standard choice for Paper networks. BungeeCord still exists, but Velocity handles backpressure better and its security model is cleaner. We run Velocity in front of our own test networks at Bytte and it's been solid.
What you'll need before starting
- Java 17 or newer installed (Velocity 3.3 needs Java 17, and recent builds prefer Java 21).
- At least two Paper servers already set up. We'll use a lobby and a survival server in the examples.
- Each Paper server running on its own port. Velocity will take the public port instead.
- A way to edit text files (nano on Linux, or the file manager in a panel like the one at panel.bytte.cloud).
Step 1: Install Velocity
Make a fresh folder for the proxy. Keep it separate from your Paper servers so nothing gets mixed up.
mkdir velocity
cd velocity
Grab the latest Velocity jar from the official PaperMC downloads page and drop it in that folder. The filename looks something like velocity-3.3.0-SNAPSHOT-XXX.jar. Rename it to velocity.jar so your start command stays simple.
Now start it once so it generates its config files, then let it shut down.
java -Xms512M -Xmx512M -jar velocity.jar
Velocity is light. It doesn't load worlds, so 512 MB to 1 GB of RAM is plenty even for a busy network. After the first run you'll see new files appear:
velocity.toml
forwarding.secret
server-icon.png
plugins/
Stop the proxy with end or Ctrl+C. We need to edit those files before it's useful.
Step 2: Edit velocity.toml
This is the main config. Open it up.
nano velocity.toml
There are four things that matter here. First, the bind address. This is the public port players connect to, so set it to the standard Minecraft port.
bind = "0.0.0.0:25565"
Using 0.0.0.0 means listen on every network interface. Your backend Paper servers should NOT use 25565 anymore. Give them something else like 25566 and 25567.
Next, the player info forwarding mode. This decides how the proxy passes a player's real identity and IP to the backend. Set it to modern.
player-info-forwarding-mode = "modern"
Modern forwarding is the secure option and it only works with Paper. We'll wire up the secret in a moment. Now scroll down to the servers section. This is where you list every backend server by a friendly name and its address.
[servers]
lobby = "127.0.0.1:25566"
survival = "127.0.0.1:25567"
minigames = "127.0.0.1:25568"
try = [
"lobby"
]
The names on the left are yours to choose. Players will use them later to switch servers. The try list controls where new players land. With just lobby in there, everyone starts in the lobby. If the lobby is down, Velocity tries the next entry, so you can add a fallback if you want.
One more block worth knowing about is forced hosts, which lets a specific domain send players straight to a specific server. It's optional, but handy.
[forced-hosts]
"minigames.yournetwork.com" = ["minigames"]
Save and close the file.
Step 3: Configure the forwarding secret
Modern forwarding works by signing the data the proxy sends to each backend. The signature uses a shared secret. Velocity already made one for you in forwarding.secret. Open it and you'll see a random string.
cat forwarding.secret
aB3xK9mPqR7tWvZ2
That string is the key that ties your proxy and your Paper servers together. Treat it like a password. Don't post it in a screenshot, don't commit it to a public repo. You're about to copy it into each backend server, so keep the file handy.
Step 4: Configure each Paper backend server
Each Paper server needs three changes so it trusts the proxy and refuses anyone trying to skip past it.
Turn off online mode
Open server.properties on the backend server and set this:
online-mode=false
This sounds scary, but it's correct here. The proxy handles Mojang authentication, not the backend. The backend just trusts what the proxy tells it. The forwarding secret is what stops random people from connecting directly and pretending to be someone. We'll lock that door in the next step. Without it, online-mode false would be a real risk, so don't skip the secret.
Enable secure forwarding in Paper
Paper keeps its proxy settings in config/paper-global.yml. Open it and find the proxies section.
proxies:
velocity:
enabled: true
online-mode: true
secret: 'aB3xK9mPqR7tWvZ2'
Set enabled to true, leave online-mode as true (this controls whether Paper enforces real accounts after the proxy vouches for them), and paste the exact same secret from your forwarding.secret file. The secret must match character for character on every backend or the connection will be rejected.
Set a different port
Back in server.properties, give this backend its own port so it doesn't fight the proxy.
server-port=25566
Repeat this whole step for every backend. Lobby gets 25566, survival gets 25567, minigames gets 25568, and so on. The secret is identical everywhere. Only the port changes.
Step 5: Start everything in order
Start your backend Paper servers first. Watch each console for a clean startup with no forwarding warnings. Then start the proxy.
java -Xms512M -Xmx512M -jar velocity.jar
When the proxy is up, connect your Minecraft client to the public address (your IP or domain, port 25565). You should land in the lobby. If you do, the network is working and the proxy is routing you correctly.
Step 6: Switching servers in game
Players need a way to move between servers. The simplest method needs no extra plugins at all. Velocity ships with a built in command.
/server survival
Type that and you're sent to the survival backend instantly, no relog. Run /server on its own and Velocity lists every server it knows about. That's enough to test with.
For a real network you'll want something nicer than typing commands. Most servers put a compass or a sign in the lobby that runs the server command for the player. A small plugin on the lobby backend can do this. The idea is the same underneath. The player triggers a connect request, and Velocity moves them. You can also build a clickable menu, but the /server command is the foundation it all sits on.
Step 7: Lock the back door
Your backend servers are running with online-mode false. That means if someone finds the backend's port and IP, they could try to connect straight to it and bypass the proxy. The forwarding secret blocks the worst of this, but you should also stop direct connections at the network level.
If your servers are on the same machine, bind each backend to localhost only. In server.properties:
server-ip=127.0.0.1
Now the backend only listens on the loopback address. The proxy, which is on the same machine, can still reach it. Outside players cannot, because 127.0.0.1 isn't routable from the internet. If your backends are on separate machines, use a firewall instead and only allow the proxy's IP to reach the backend ports.
Troubleshooting
Here are the problems we see most often, and what fixes them.
| Symptom | Likely cause | Fix |
|---|---|---|
| Kicked with "Unable to connect you to the server you were on" | Forwarding secret mismatch | Check the secret in paper-global.yml matches forwarding.secret exactly, with no extra spaces |
| "If you wish to use IP forwarding, please enable it in your BungeeCord config" | Backend expecting Bungee, not Velocity | Use the velocity proxy block in paper-global.yml, not bungeecord true in spigot.yml |
| Players can't connect at all | Backend ports clash or proxy can't reach them | Make sure each backend uses a unique port and the proxy is started after them |
Forwarding errors on join. The number one cause is a secret that doesn't match. Open forwarding.secret and config/paper-global.yml side by side. They have to be identical. A trailing space or a copied newline will break it. Also confirm player-info-forwarding-mode is set to modern in velocity.toml and that Paper's velocity block has enabled: true.
Players land but get bounced back to lobby. This usually means the target backend rejected the forwarding handshake. Check that backend's console at the moment of connection. It will print why it refused, and the message almost always points at the secret or at online-mode being left true in server.properties.
"Can't connect to server" with no detail. The backend probably isn't running, or the address in velocity.toml is wrong. Confirm the port in the [servers] block matches the server-port in that backend's server.properties. Start the backend by hand and watch for errors before blaming the proxy.
Someone connected directly and bypassed the proxy. You forgot Step 7. Bind the backends to 127.0.0.1 or firewall their ports so only the proxy can reach them. Never leave an online-mode false server open to the internet.
Wrong Java version. If Velocity refuses to start and complains about an unsupported class file version, your Java is too old. Run java -version and install 17 or newer. Velocity will not run on Java 11 or 8.
Where to go from here
You've got a real network now. One address, a lobby, and backends you can restart independently. From here the natural next steps are adding a permissions plugin that works across the proxy, setting up a chat or messaging plugin so players in different servers can talk, and putting a nice menu in the lobby instead of the bare /server command. Keep your forwarding secret private, always bind or firewall your backends, and add new servers by dropping them into the [servers] block and giving them the same secret. That's the whole pattern, and it scales as far as your hardware will take it.



