Skip to content
Current coupon:10% offUse it in your order

A server network with Velocity: lobby, survival and minigames on one address

How to connect several Minecraft servers with a Velocity proxy: installation, velocity.toml line by line, modern forwarding, Paper and Fabric setup, securing backends and fixing errors.

  • expert
  • ~40 min
  • Updated 2 Oct 2026

Velocity is a proxy that lets players connect to one address and then move between servers with the /server command – for example from the lobby to survival or to minigames. We'll show how to install and configure Velocity, connect it to your servers with secure modern forwarding, and lock down the servers behind the proxy so nobody can reach them directly.

What you'll need

  • At least two Minecraft servers: Paper or Purpur (version 1.13 or newer), or Fabric, Forge or NeoForge with a forwarding mod
  • Somewhere to run the proxy: a VPS with Ubuntu 24.04 or Debian 13 (connecting over SSH); we're preparing a separate Minecraft Proxy product
  • Access to the Files and Server properties tabs for each server
  • About 40 minutes

When you need a proxy#

You wantDo you need a proxy?
One server for friends or a communityNo
A lobby + one or more game servers on one addressYes
Different game modes (survival, creative, minigames) with switching without disconnectingYes
Shared chat, permissions or bans across serversYes (with plugins on the proxy)
Bedrock players across the whole networkYes, Geyser then runs only on the proxy

The proxy doesn't run the game itself, it only forwards connections. It's light on resources: 1–⁠2 GB of memory is enough for dozens of players.

How the network works#

text
Player ──► mc.example.cz:25565  (Velocity, authenticates the player)
              │
              ├──► lobby     (Paper, online-mode=false, accepts only the proxy)
              ├──► survival  (Paper, online-mode=false, accepts only the proxy)
              └──► minihry   (Paper, online-mode=false, accepts only the proxy)
  1. The player connects to the proxy's address. The proxy checks with Microsoft that they have a genuine account (online-mode = true).
  2. The proxy sends them to the first server in the try list (the lobby).
  3. Along with the connection, the proxy passes the server the player's name, UUID, skin and real IP address (player info forwarding). It signs the data with a secret key that only the proxy and your servers know.
  4. The servers behind the proxy (backends) don't authenticate anything themselves (online-mode=false) and only trust a proxy with a valid key. Anyone who connects directly gets the message This server requires you to connect with Velocity.

Proxy, servers and domain#

  • Proxy: Velocity 4.x requires Java 25. Run it on a VPS (VPS Performance, VPS Budget). Only Velocity plugins belong on the proxy – Paper plugins don't work on it.
  • Backends: regular Minecraft servers. They can run at StormHost as separate services (each with its own address and port), or on the same VPS as the proxy.
  • Domain (optional): players type mc.example.cz instead of an IP (Server address and domain).

The Minecraft Proxy product

We're preparing a standalone proxy as a service. It will have a Proxy flag preset for Velocity in the Startup tab. Until then, use a VPS – the steps are below.

Installing Velocity on a VPS#

This works on both Ubuntu 24.04 and Debian 13. Run the commands as root.

  1. Install Java 25 and curl:

    bash
    apt update
    apt install openjdk-25-jre-headless curl
    • apt update – downloads the current package list.
    • apt install openjdk-25-jre-headless – installs the Java 25 runtime without graphics libraries (a server doesn't need them).
    • curl – a program for downloading files from the internet (if you already have it, nothing happens).
  2. Check the version:

    bash
    java -version

    The first line of the output must contain 25.

  3. Create a user and a folder for the proxy:

    bash
    useradd --system --create-home --home-dir /opt/velocity --shell /usr/sbin/nologin velocity
    • useradd --system – creates a system user without a password (the proxy won't run as root).
    • --create-home --home-dir /opt/velocity – creates the /opt/velocity folder where the proxy will live.
    • --shell /usr/sbin/nologin – nobody can log in as this user.
    • velocity – the user name.
  4. On papermc.io/downloads/velocity (opens in a new window), copy the link to the latest stable version and download it:

    bash
    cd /opt/velocity
    curl -o velocity.jar "<DOWNLOAD_URL>"
    chown velocity:velocity velocity.jar
    • cd /opt/velocity – goes to the proxy folder.
    • curl -o velocity.jar – downloads the file and saves it as velocity.jar.
    • <DOWNLOAD_URL> – the link you copied from the page. Replace the whole thing including the angle brackets, keep the quotes.
    • chown velocity:velocity – makes the velocity user the file's owner.
  5. Start the proxy for the first time so it creates its configuration:

    bash
    runuser -u velocity -- env MALLOC_ARENA_MAX=2 java -Xms1G -Xmx1G -XX:MaxDirectMemorySize=512M -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:+UnlockExperimentalVMOptions -XX:+ParallelRefProcEnabled -XX:+AlwaysPreTouch -jar velocity.jar
    • runuser -u velocity -- – runs the command after -- as the velocity user.
    • env MALLOC_ARENA_MAX=2 – limits the allocator's memory arenas so the proxy doesn't use extra memory for nothing.
    • -Xms1G -Xmx1G – gives the proxy 1 GB of heap (all at once, so it doesn't need to grow it while running). For a bigger network, raise it to 2G. The proxy needs plenty of memory outside the heap for networking too, so don't give it more than half the memory you have for it.
    • -XX:MaxDirectMemorySize=512M – a cap for network buffers. Without it, they can grow up to the size of the heap.
    • -XX:+UseG1GC … -XX:+AlwaysPreTouch – flags recommended by the Velocity documentation (the G1 garbage collector tuned for a proxy).
    • -jar velocity.jar – starts the proxy.

    The Startup script generator builds the command for a different memory size.

    After startup you'll see a Done (…)! line. Type end and press Enter, and the proxy shuts down. The folder now contains velocity.toml and forwarding.secret.

  6. To keep the proxy running permanently and have it start on its own after a VPS reboot, create a systemd service for it following Run an app 24/7 on a VPS. In the unit file, set User=velocity, WorkingDirectory=/opt/velocity, Environment=MALLOC_ARENA_MAX=2, and in ExecStart put the command from step 5 without runuser -u velocity -- env MALLOC_ARENA_MAX=2 and with the full path to Java, so it starts with /usr/bin/java -Xms1G ….

  7. Allow the proxy port in the VPS firewall: TCP 25565 (and Geyser's UDP port if you'll use it). See Firewall in the customer area and UFW.

velocity.toml#

Open /opt/velocity/velocity.toml (for example nano /opt/velocity/velocity.toml). Here's an example with settings for a network of three servers (leave the rest of the file as is):

/opt/velocity/velocity.tomlTOML
bind = "0.0.0.0:25565"
motd = "<gold><bold>StormCraft</bold></gold> <gray>| lobby, survival, minihry"
show-max-players = 100
online-mode = true
force-key-authentication = true
player-info-forwarding-mode = "modern"
forwarding-secret-file = "forwarding.secret"

[servers]
lobby = "203.0.113.10:30066"
survival = "203.0.113.11:30067"
minihry = "203.0.113.12:30068"

try = [
    "lobby"
]

[forced-hosts]
"survival.example.cz" = [
    "survival"
]
SettingWhat it doesRecommended valueWhen to change
config-versionThe file format version.Don't changeNever – Velocity manages it itself.
bindThe IP address and port the proxy listens on."0.0.0.0:25565"A different port if you don't want to or can't use 25565.
motdThe description in the server list. MiniMessage format (<gold>, <bold>, <#09add3>), not § codes.Your descriptionAny time.
show-max-playersHow many slots the server list shows. Velocity doesn't limit the player count; it's only a display value.E.g. 100Depending on the size of the network.
online-modeThe proxy authenticates player accounts with Microsoft.trueNever on a public server.
force-key-authenticationRequires players to have a chat signing key.truefalse when Geyser runs on the proxy (Bedrock players can't chat otherwise).
prevent-client-proxy-connectionsKicks a player whose internet provider doesn't match what the authentication server sees. Weak protection against VPNs.falseLeave it.
player-info-forwarding-modeHow the proxy passes player data: none (nothing, players get offline UUIDs), legacy (BungeeCord format, insecure), bungeeguard (legacy with a key), modern (signed Velocity format, version 1.13+)."modern"legacy/bungeeguard only for servers on 1.12 and older.
forwarding-secret-fileThe file with the secret forwarding key."forwarding.secret"Don't change it.
announce-forgeThe proxy announces itself as a Forge server in the server list.falsetrue for a network of modded servers.
kick-existing-playersWhen the same account logs in a second time, the first session is kicked (Vanilla behavior).falsetrue if your players expect it.
[servers]The list of backends as name = "IP:port". Players see the name in /server.Your servers' addressesWhen you add or move a server.
tryThe order of servers the proxy tries to send players to after they join or get kicked from a server.["lobby"]Add a fallback server for players to land on when the lobby isn't running.
[forced-hosts]Sends players straight to a specific server based on the address they typed (anyone who types survival.example.cz ends up directly on the survival server).As neededWhen you want a separate subdomain for each server. The domain must point to the proxy.

Three items in the [advanced] and [query] sections are worth a look:

Section and settingWhat it doesRecommended valueWhen to change
[advanced] › login-ratelimitThe minimum gap (ms) between connections from one IP.3000Don't change it; it protects against flooding.
[advanced] › failover-on-unexpected-server-disconnectWhen a backend crashes, sends players to another server instead of disconnecting them.trueLeave it.
[query] › enabledAnswers Query (GameSpy4) requests.falseWhen a statistics website needs it.

Velocity 3 and 4

In version 4, instead of the ping-passthrough = "DISABLED" line there's a separate [ping-passthrough] section with the version, players, description, favicon and modinfo switches. They decide what the proxy takes over from the backend in the server list. By default everything is off and the motd from velocity.toml applies.

The forwarding secret#

On its first start, Velocity creates a forwarding.secret file with a random 12-⁠character key. We recommend replacing it with a longer one:

  1. Generate a random password of 32 or more characters (letters and digits) in the password generator.
  2. Put it as the only line in /opt/velocity/forwarding.secret (for example with nano).
  3. You'll then enter the same key on all backends.

The key is like an admin password

Anyone who knows forwarding.secret and a backend's address can connect to it as any player, including you. Don't send it to anyone, don't put it in public repositories, and if you suspect a leak, replace it on the proxy and on all backends.

Backend setup (Paper and Purpur)#

For every server behind the proxy:

  1. In the Server properties tab, in the Players group, turn off Account authentication (online-mode=false) and click Save.

    The customer area shows a warning that anyone can join. Behind a proxy with modern forwarding that's correct – the proxy does the authentication and the server only accepts players with a valid key.

  2. In the Files tab, open spigot.yml and check that settings.bungeecord is false:

    spigot.ymlYAML
    settings:
      bungeecord: false
    • bungeecord – turns on forwarding in BungeeCord (legacy) format. It must be off for modern forwarding.
  3. Open config/paper-global.yml and set the following in the proxies section:

    config/paper-global.ymlYAML
    proxies:
      velocity:
        enabled: true
        online-mode: true
        secret: "<SECRET>"

    Replace <SECRET> with the contents of the forwarding.secret file from the proxy. Replace the whole thing including the angle brackets, keep the quotes.

  4. Restart the server.

What the settings in paper-global.yml mean:

SettingWhat it doesRecommended valueWhen to change
proxies.velocity.enabledThe server accepts modern forwarding from Velocity and rejects direct connections.trueOnly when removing the proxy.
proxies.velocity.online-modeMust match online-mode in velocity.toml. Decides which UUIDs players get.trueNever, if the proxy authenticates players.
proxies.velocity.secretThe same key as in forwarding.secret on the proxy.Contents of forwarding.secretWhen you replace the key.

On Paper 1.18.2 and older, these settings are in paper.yml under the names settings.velocity-support.enabled, settings.velocity-support.online-mode and settings.velocity-support.secret.

Fabric, Forge and NeoForge#

LoaderWhat to installWhere to enter the key
FabricThe FabricProxy-Lite mod (from Modrinth, requires Fabric API)config/FabricProxy-Lite.toml, the secret = "<SECRET>" entry
Forge, NeoForgeThe ProxyCompatibleForge modThe mod's configuration file in the config folder (as described on the mod's Modrinth page)

FabricProxy-Lite settings:

SettingWhat it doesRecommended valueWhen to change
secretThe key from forwarding.secret.Contents of forwarding.secretWhen you replace the key.
hackOnlineModeAllows connections through the proxy even with online-mode on on the backend.true (default)Leave it.
hackEarlySendSends player data earlier. LuckPerms requires it, as do some other mods.true if you use LuckPermsOtherwise the default false.
hackMessageChainFixes players getting kicked with an invalid chat signature message after switching servers.falsetrue when players get kicked over the chat signature after /server.

Securing the backends#

A backend with online-mode=false and no working forwarding would let anyone in under any name. Depending on where your servers run:

  • Backends at StormHost (separate services): we set the address and port automatically (server-ip can't be changed), so the servers are reachable from the internet. Modern forwarding is what protects them: with proxies.velocity.enabled: true, the server rejects anyone who doesn't come through the proxy with a valid key. So never use legacy or none.
  • Backends on the same VPS as the proxy: in each backend's server.properties, set server-ip=127.0.0.1, and in velocity.toml use the addresses 127.0.0.1:<PORT>. The servers are then not reachable from outside at all. In the VPS firewall, allow only the proxy port.
  • Backends on another VPS: in the backend's firewall, allow the server port only from the proxy's IP address (Firewall in the customer area).

Switching servers and plugins on the proxy#

CommandWhat it doesPermission
/serverShows which server you're on and offers the others.velocity.command.server (everyone has it by default)
/server survivalSwitches to the survival server.The same
/glistThe player count on the proxy; with all, a breakdown by server.velocity.command.glist (nobody by default)
/send <NICK> <SERVER>Moves a player to another server.velocity.command.send
velocity reloadReloads velocity.toml (in the proxy console).velocity.command.reload
shutdownShuts down the proxy (console only).–

Plugins on the proxy (in the /opt/velocity/plugins folder, Velocity versions):

  • LuckPerms – permissions for proxy commands. For permissions on the servers, LuckPerms must also be on every backend and all instances must use the same MySQL/MariaDB database (MySQL for plugins). On each backend, set a different server in the LuckPerms configuration (for example lobby, survival) so you can grant permissions per server, and set messaging-service: sql so changes take effect on all servers right away. Details are in the LuckPerms guide.
  • Geyser and Floodgate – Bedrock players; install them only on the proxy (guide).
  • spark – proxy profiling, the sparkv command.

Verify it works#

  1. Start the proxy and the backends. The proxy console shows Listening on …:25565 and Done (…)!.
  2. Connect to the proxy address in the game. You'll land on the lobby server.
  3. Type /server survival – it switches you without disconnecting.
  4. In the backend console, check the line with your connection: it must contain your real IP address, not the proxy's. Then forwarding works. In the default Streamer mode, the customer area console hides IP addresses – for this check, click Show details at the top.
  5. Try connecting directly to the backend's address. You must get This server requires you to connect with Velocity.

Troubleshooting#

Your server did not send a forwarding request to the proxy. Make sure the server is configured for Velocity forwarding.#

The backend doesn't have modern forwarding turned on. Check proxies.velocity.enabled: true in config/paper-global.yml (FabricProxy-Lite on Fabric) and that you restarted the server after the change.

Unable to verify player details#

The key on the backend doesn't match forwarding.secret on the proxy. Copy it again (without extra spaces or blank lines) and restart the backend.

This server requires you to connect with Velocity.#

You're connecting directly to the backend – that's correct, the server is protected. If you see this message even when connecting through the proxy, the proxy's player-info-forwarding-mode is set to something other than modern.

Unable to connect you to lobby. Please try again later.#

The proxy couldn't reach the backend: the server isn't running, the address or port in [servers] doesn't match the address in that server's Network tab, or a firewall is blocking the connection.

There are no available servers to connect you to. Try again later or contact an admin.#

None of the servers in the try list are available. Start the lobby or add a fallback server to try.

Players have an empty inventory and different permissions after moving to the proxy#

The players got different UUIDs. The cause is player-info-forwarding-mode = "none" (offline UUIDs) or a mismatch between online-mode on the proxy and proxies.velocity.online-mode on the backend. Set modern forwarding and both values to true. Data under the old UUIDs stays in the world and plugin files; make a backup before moving a large network to a proxy.

The proxy won't let Bedrock players in, or they can't chat#

See Crossplay with Bedrock: Geyser must be on the proxy and force-key-authentication must be off in velocity.toml.

Summary

  • Players connect only to the proxy; the proxy authenticates accounts (online-mode = true) and the backends have online-mode=false.
  • Always use player-info-forwarding-mode = "modern", and on the backends proxies.velocity.enabled: true with the same key from forwarding.secret.
  • forwarding.secret is secret; replace it with a long random key.
  • Velocity 4 requires Java 25, and plugins on the proxy must be made for Velocity.
  • Check that a direct connection to a backend ends with This server requires you to connect with Velocity.

Was this guide helpful?

Applies to

  • Velocity 4.x
  • Paper 1.13 and newer
  • Fabric (FabricProxy-Lite)
  • Forge, NeoForge (ProxyCompatibleForge)
  • Ubuntu 24.04
  • Debian 13

Services

Report a mistake in this guide

Search the guides