> ## Content Index
> Fetch the complete content index at: https://blog.sudowl.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Velocity Minecraft Proxy — Setup From Scratch in 10 Minutes
- URL: https://blog.sudowl.com/velocity-minecraft-proxy-setup-from-scratch/
- Published: 2026-04-28T14:00:00.000Z
- Updated: 2026-10-11T10:16:27.000Z
- Description: Stand up a Velocity proxy on Linux from zero — install, velocity.toml, modern IP forwarding to Paper backends, systemd unit, firewall. The clean install, no BungeeCord baggage.
- Author: Lukas
- Tags: Minecraft, Gameserver, Linux

If you're starting a new Minecraft network in 2026, skip BungeeCord and Waterfall — go straight to Velocity. PaperMC's proxy is the active project, the docs are current, and the IP forwarding is cryptographically signed instead of trust-based.

This is the from-zero install. If you already have BungeeCord/Waterfall and want to migrate, see the [migration guide](/migrate-bungeecord-waterfall-to-velocity/) instead.

**TL;DR:**

```bash
sudo adduser --system --group --home /opt/velocity velocity
cd /opt/velocity
VER=4.2.0   # current stable: https://papermc.io/downloads/velocity
URL=$(curl -s -A "your-name/1.0 (you@example.com)" \
  "https://fill.papermc.io/v3/projects/velocity/versions/$VER/builds/latest" \
  | jq -r '.downloads."server:default".url')
sudo -u velocity wget -O velocity.jar "$URL"
sudo -u velocity java -jar velocity.jar  # creates configs, then Ctrl-C

```

Then edit `velocity.toml`, point at your Paper backends, copy the `forwarding.secret` to each backend's `paper-global.yml`, systemd-enable, done.

## Prerequisites

- Linux box with Java 21 (I run Temurin 21 — see [docker-install on Ubuntu](/docker-install-ubuntu/) for similar repo-based install). For Velocity:  
```bash  
sudo apt install temurin-21-jdk  
```
- Paper backends already running on the same box or LAN-reachable. Bare vanilla / Spigot won't do modern forwarding well.
- A port to expose publicly (default 25565).
- `jq` for the download step (`sudo apt install jq`). PaperMC's download API (v3) wants a real User-Agent with contact info, hence the `-A`. The old `api.papermc.io/v2/.../versions/latest/...` one-liner that floats around tutorials returns 404.

## Install

```bash
sudo adduser --system --group --home /opt/velocity velocity
cd /opt/velocity
VER=4.2.0   # current stable: https://papermc.io/downloads/velocity
URL=$(curl -s -A "your-name/1.0 (you@example.com)" \
  "https://fill.papermc.io/v3/projects/velocity/versions/$VER/builds/latest" \
  | jq -r '.downloads."server:default".url')
sudo -u velocity wget -O velocity.jar "$URL"
sudo -u velocity java -jar velocity.jar

```

First run generates:

- `velocity.toml` — main config
- `forwarding.secret` — random secret for modern IP forwarding
- `plugins/` — empty
- `logs/` — empty

Ctrl-C. We'll write the config from scratch.

## velocity.toml — minimum sane config

```toml
config-version = "2.7"

bind = "0.0.0.0:25565"
motd = "&6&lMy Network &7- &fpick a world"
show-max-players = 100
online-mode = true
prevent-client-proxy-connections = false

player-info-forwarding-mode = "modern"
forwarding-secret-file = "forwarding.secret"

announce-forge = false
announce-proxy-commands = true
log-command-executions = false
log-player-connections = true

[servers]
lobby = "127.0.0.1:25566"
survival = "127.0.0.1:25567"
try = ["lobby"]

[forced-hosts]
"survival.example.com" = ["survival"]

[advanced]
compression-threshold = 256
compression-level = -1
login-ratelimit = 3000
connection-timeout = 5000
read-timeout = 30000
haproxy-protocol = false
tcp-fast-open = false
bungee-plugin-message-channel = true
show-ping-requests = false
failover-on-unexpected-server-disconnect = true
kick-existing-players = false
ping-passthrough = "DISABLED"
sample-players-in-ping = false

[query]
enabled = false
port = 25565
map = "Velocity"
show-plugins = false

```

The lines that actually matter:

- `bind` — public-facing port. The backends should bind to `127.0.0.1` only and never accept external connections.
- `online-mode = true` — proxy authenticates against Mojang. Always true unless you specifically want a cracked server.
- `player-info-forwarding-mode = "modern"` — players' real UUID + IP get cryptographically forwarded to the backend. The backend verifies the signature.
- `[servers]` — name → backend address. The `try` list is the fallback chain on join (lobby first, lobby2 if lobby is down, etc.).
- `[forced-hosts]` — domain-based routing. `survival.example.com` skips the lobby and lands on `survival`.

For a deeper reference of options and equivalents to BungeeCord syntax, see my [BungeeCord config.yml deep-dive](/bungeecord-config-yml-explained/) — the concepts map closely.

## Backends — modern forwarding

Every Paper backend (1.13+) needs to know the forwarding secret. Edit `config/paper-global.yml`:

```yaml
proxies:
  velocity:
    enabled: true
    online-mode: true
    secret: "<contents-of-/opt/velocity/forwarding.secret>"

```

Get the secret:

```bash
cat /opt/velocity/forwarding.secret

```

Paste literally — no extra spaces, no trailing newline.

Each backend's `server.properties` needs `online-mode=false`. Yes, false. The proxy is the authentication tier; backends trust the proxy.

But: if a backend's port is reachable from the internet AND `online-mode=false`, anyone can connect as any username. Bind backends to `127.0.0.1`:

```properties
server-ip=127.0.0.1
server-port=25566

```

And the [UFW rule](/ufw-firewall-rules-ubuntu/) to be sure:

```bash
sudo ufw deny 25566:25600/tcp

```

Restart each backend after editing.

## Systemd unit

`/etc/systemd/system/velocity.service`:

```ini
[Unit]
Description=Velocity Minecraft Proxy
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=velocity
Group=velocity
WorkingDirectory=/opt/velocity
ExecStart=/usr/bin/java -Xms512M -Xmx1G \
  -XX:+UseG1GC -XX:G1HeapRegionSize=4M \
  -XX:+UnlockExperimentalVMOptions -XX:+ParallelRefProcEnabled \
  -XX:+AlwaysPreTouch \
  -jar velocity.jar
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

```

1 GB heap is plenty for 100 concurrent players. Velocity is much lighter than the backends. [systemd unit reference](/systemd-service-unit-file/).

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now velocity
sudo journalctl -u velocity -f

```

Look for `Listening on /0.0.0.0:25565` — that's ready.

## Firewall

```bash
sudo ufw allow 25565/tcp

```

Minecraft is TCP. UDP not needed for Java edition. [UFW rules](/ufw-firewall-rules-ubuntu/).

## Plugins

Drop into `/opt/velocity/plugins/`. Velocity-compatible plugins, not BungeeCord ones — the platform is different.

Standard set for a small network:

- LuckPerms-Velocity — permissions ([setup guide](/luckperms-bungeecord-velocity-setup/))
- Signed-Velocity — signed-message handling for 1.19.1+
- TAB — tab list customization
- Velocity-Bridge or PluginMessageBridge — for cross-server chat or features

Restart after dropping a JAR; Velocity doesn't hot-load plugins.

## Verify everything works

From a Minecraft client:

1. Connect to `<your-public-ip>:25565`. You should land on the lobby.
2. `/server survival` — should switch you to the survival backend.
3. On the survival backend's console: `whois <yourname>`. UUID shown should be your real Mojang UUID, not an offline-mode one starting with predictable digits.
4. Disconnect from the proxy, try connecting directly to `<public-ip>:25566`. Should fail or land on the unhardened backend — if it works, your firewall isn't blocking the backend port.

## Gotchas

- **Forwarding secret mismatch.** The single most common failure. Backend logs say `Unable to authenticate player`. Fix: re-paste the secret exactly. Trailing whitespace counts.
- **Spigot can't do modern forwarding.** Either upgrade backends to Paper, or fall back to `player-info-forwarding-mode = "legacy"` (BungeeCord-compatible, less secure).
- **`velocity.toml` is hand-managed.** Velocity does NOT overwrite the file on shutdown — your config is yours. Restart to apply changes, no `/reload` equivalent.
- **1.8 / 1.12 clients can't authenticate via modern forwarding.** They need `bungeeguard` mode and the BungeeGuard plugin on each backend. If your audience uses old launchers, plan for this.
- **Don't run Velocity on Java 11.** It boots and looks fine, then misbehaves under load. Java 17 is the floor, Java 21 is the recommendation.

## Why Velocity beats the alternatives

- vs **BungeeCord/Waterfall:** modern signed forwarding, lower latency, active development. The [comparison post](/waterfall-vs-bungeecord-minecraft-proxy/) covers this in detail.
- vs **no proxy at all:** lets you have separate worlds (lobby / survival / creative) on different servers without players relaunching. Plus crash isolation — one backend going down doesn't kill the network.
- vs **a hosting panel that bundles everything:** you control the version, the JVM tuning, the plugins. No vendor lock-in.

For a fully fleshed network, follow up with [LuckPerms cross-server permissions](/luckperms-bungeecord-velocity-setup/) and [Paper as the backend](/minecraft-java-server-linux/).

---

### Related posts

- [BungeeCord / Waterfall Setup — Running a Minecraft Server Network](https://blog.diengdoh.com/minecraft-bungeecord-network-setup/?ref=blog.sudowl.com)
- [Minecraft Java Server on Linux — Paper, systemd, and Memory Tuning](https://blog.diengdoh.com/minecraft-java-server-linux/?ref=blog.sudowl.com)
- [PaperMC Download API v3: Why Your "latest" One-Liner Returns 404](https://blog.diengdoh.com/papermc-download-api-v3/?ref=blog.sudowl.com)