> ## 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.

# BungeeCord / Waterfall Setup — Running a Minecraft Server Network
- URL: https://blog.sudowl.com/minecraft-bungeecord-network-setup/
- Published: 2026-04-20T10:00:00.000Z
- Updated: 2026-10-11T10:16:27.000Z
- Description: BungeeCord network on one Linux box: proxy, Paper backends on localhost, IP forwarding, systemd template, DNS. Plus why Waterfall is EOL.
- Author: Lukas
- Tags: Linux, Minecraft, Gameserver

A Minecraft "network" is just one proxy on port 25565 and several normal servers behind it that nobody can reach directly. Players connect to the proxy, land in the lobby, `/server survival` moves them over without a relog. This post builds that end-to-end with BungeeCord: proxy, two Paper backends, IP forwarding, systemd, DNS.

**TL;DR:**

```bash
sudo adduser --system --group --home /opt/mc mc
sudo -u mc mkdir -p /opt/mc/{proxy,lobby,survival}
sudo -u mc wget -O /opt/mc/proxy/BungeeCord.jar \
  https://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/BungeeCord.jar
# backends: server-ip=127.0.0.1, online-mode=false, spigot.yml bungeecord: true
# proxy:    ip_forward: true, online_mode: true
sudo ufw allow 25565/tcp

```

If you're starting a new network today, though, read the next section first.

## The honest part: Waterfall is dead, and Velocity is the better pick

Waterfall — PaperMC's BungeeCord fork — has reached end of life: PaperMC announced it in March 2024 and points everyone to Velocity. Existing Waterfall installs keep running and builds still show up occasionally, but there's no promise of updates for new Minecraft versions or of timely security fixes. If you're on Waterfall right now, that's fine for this week — just don't build anything new on it, and plan the switch.

That leaves two options:

- **BungeeCord** — the original, still maintained by md\_5 / SpigotMC, still gets updates for new Minecraft versions. Legacy IP forwarding only (see below).
- **Velocity** — PaperMC's modern proxy. Signed "modern" forwarding, active development, different config and plugin API.

For a fresh network I'd go Velocity, and I have a full walkthrough: [Velocity from scratch](/velocity-minecraft-proxy-setup-from-scratch/). This post is for people who need BungeeCord — an existing plugin set that only exists for Bungee, very old client versions, or a network you inherited. If you're unsure, the [Waterfall vs BungeeCord comparison](/waterfall-vs-bungeecord-minecraft-proxy/) covers the lineage, and the [migration guide](/migrate-bungeecord-waterfall-to-velocity/) shows what moving to Velocity costs.

Everything below about backends, ports and firewalls applies to Waterfall too — same config, same jar slot.

## Layout

```text
/opt/mc/proxy      BungeeCord   0.0.0.0:25565   (public)
/opt/mc/lobby      Paper        127.0.0.1:25566 (local only)
/opt/mc/survival   Paper        127.0.0.1:25567 (local only)

```

One system user, one directory per server. Backends on the same box as the proxy, bound to localhost. That last part is the whole security model, so I'll repeat it a few times.

## Java

BungeeCord itself is happy on a recent LTS Java, and your Paper backends on current Minecraft need Java 21, so install 21 once and use it for everything:

```bash
sudo apt install -y temurin-21-jre
java -version

```

Repo setup for Temurin is in the [Minecraft Java server post](/minecraft-java-server-linux/).

## The backends

Set up each backend like a normal Paper server — download Paper, run once, accept the EULA. The single-server walkthrough is [Minecraft Java server on Linux](/minecraft-java-server-linux/). Then change three files per backend.

**server.properties:**

```properties
server-ip=127.0.0.1
server-port=25566
online-mode=false

```

Survival gets `25567`. `online-mode=false` because the proxy authenticates players; the backend trusts what the proxy forwards.

**spigot.yml:**

```yaml
settings:
  bungeecord: true

```

This tells the backend to accept the forwarded IP and UUID from the proxy's handshake. Without it, every player shows up as `127.0.0.1` with an offline-mode UUID — bans break, permissions keyed by UUID break.

**config/paper-global.yml:**

```yaml
proxies:
  bungee-cord:
    online-mode: true

```

Tells Paper that the proxy is in online mode, so it uses the real Mojang UUIDs.

## Gotcha: a public backend with online-mode=false

Legacy BungeeCord forwarding is pure trust. The backend believes whatever name and UUID arrive in the handshake. If a backend port is reachable from the internet, anyone can connect directly and claim to be you — including your op account.

`server-ip=127.0.0.1` is the first line of defense. The firewall is the second:

```bash
sudo ufw deny 25566:25600/tcp
ss -tlnp | grep java

```

`ss` should show the backends on `127.0.0.1`, only the proxy on `0.0.0.0`. If backends must live on another machine, firewall them so *only the proxy's IP* can connect, and add BungeeGuard (plugin on proxy + backends) so the handshake carries a secret token.

## The proxy

```bash
cd /opt/mc/proxy
sudo -u mc java -Xms512M -Xmx512M -jar BungeeCord.jar

```

First start writes `config.yml`, then type `end`. Minimum edits:

```yaml
listeners:
- host: 0.0.0.0:25565
  motd: '&6My Network'
  max_players: 100
  priorities:
  - lobby
  forced_hosts:
    survival.example.com: survival
  ping_passthrough: false
  tab_list: GLOBAL_PING
servers:
  lobby:
    address: 127.0.0.1:25566
    restricted: false
  survival:
    address: 127.0.0.1:25567
    restricted: false
ip_forward: true
online_mode: true
network_compression_threshold: 256

```

The lines that matter:

- `ip_forward: true` — the other half of `bungeecord: true` on the backends. Both or neither.
- `online_mode: true` — the proxy is where Mojang authentication happens.
- `priorities` — where players land on join, with fallback.
- Delete the default `servers` entry if it's still in there pointing at `localhost:25565` — that's the proxy's own port.

Every key in that file, including the undocumented ones: [BungeeCord config.yml explained](/bungeecord-config-yml-explained/).

## systemd: one template for all servers

Instead of three unit files, one template. `/etc/systemd/system/mc@.service`:

```ini
[Unit]
Description=Minecraft %i
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=mc
Group=mc
WorkingDirectory=/opt/mc/%i
EnvironmentFile=/opt/mc/%i/jvm.env
ExecStart=/usr/lib/jvm/temurin-21-jre-amd64/bin/java $JAVA_OPTS -jar server.jar
Restart=on-failure
RestartSec=15
TimeoutStopSec=120
SuccessExitStatus=0 143

[Install]
WantedBy=multi-user.target

```

Each directory gets a `jvm.env` and a `server.jar` symlink:

```bash
# /opt/mc/lobby/jvm.env
JAVA_OPTS=-Xms2G -Xmx2G -XX:+UseG1GC -XX:+AlwaysPreTouch

# /opt/mc/proxy/jvm.env
JAVA_OPTS=-Xms512M -Xmx512M -XX:+UseG1GC

```

```bash
sudo -u mc ln -s BungeeCord.jar /opt/mc/proxy/server.jar
sudo -u mc ln -s paper.jar /opt/mc/lobby/server.jar
sudo -u mc ln -s paper.jar /opt/mc/survival/server.jar
sudo systemctl daemon-reload
sudo systemctl enable --now mc@lobby mc@survival mc@proxy
journalctl -u mc@proxy -f

```

Backends get the full Aikar flag set from the [single-server post](/minecraft-java-server-linux/); I shortened them here to keep it readable. The proxy needs very little memory — it shuffles packets and doesn't load worlds. `%i` is replaced by whatever comes after the `@`, so `mc@lobby` runs in `/opt/mc/lobby`.

## Gotcha: BungeeCord rewrites config.yml

The proxy writes its config back to disk on shutdown. Edit `config.yml` while it's running, then restart, and your edits are gone. Stop first, edit, start:

```bash
sudo systemctl stop mc@proxy
sudo -u mc nano /opt/mc/proxy/config.yml
sudo systemctl start mc@proxy

```

## DNS

Point an A record (plus AAAA if you bind on `[::]`) at the proxy IP:

```text
play.example.com.       A   203.0.113.10
survival.example.com.   A   203.0.113.10

```

Same IP for both — `forced_hosts` in the config routes `survival.example.com` straight to the survival backend, everything else to the lobby. If you want players to connect on a non-default port without typing it, an SRV record does it:

```text
_minecraft._tcp.play.example.com. SRV 0 5 25570 play.example.com.

```

Players type `play.example.com`, the client looks up the SRV and connects to 25570\. Careful combining SRV with forced hosts: they match on the hostname the client puts into the handshake, and with SRV in the mix that isn't always the name the player typed. Test it before you announce the address.

## Permissions across the network

Bungee's built-in `groups:` / `permissions:` block is fine for two admins. Anything more, install LuckPerms on the proxy *and* every backend, pointed at one shared MySQL/MariaDB — then a rank change applies network-wide. Walkthrough: [LuckPerms on BungeeCord and Velocity](/luckperms-bungeecord-velocity-setup/).

## Testing it

1. Connect to `play.example.com`. You land in the lobby.
2. `/server survival` — switches without a relog.
3. On the survival console: check the player's UUID. It must be your real Mojang UUID. An offline-mode UUID means `ip_forward` or `bungeecord: true` is missing somewhere.
4. From outside the box, try connecting to `<public-ip>:25566`. It must fail. If it connects, stop everything and fix the firewall before anything else.

## Gotcha: "If you wish to use IP forwarding, please enable it in your BungeeCord config as well!"

That kick message means the backend has `bungeecord: true` but the proxy has `ip_forward: false` — or the player connected to the backend directly, bypassing the proxy. Fix the proxy config, or close the backend port you forgot.

## Where to go from here

Running this on BungeeCord works and will keep working as long as md\_5 keeps updating it. But the security model is "trust the handshake, firewall everything", and the plugin ecosystem is shifting to Velocity. When you have an evening, do the [migration to Velocity](/migrate-bungeecord-waterfall-to-velocity/) — the backends from this post stay the same apart from switching to modern forwarding.

---

### Related posts

- [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)
- [Migrating from BungeeCord/Waterfall to Velocity — A Practical Walkthrough](https://blog.diengdoh.com/migrate-bungeecord-waterfall-to-velocity/?ref=blog.sudowl.com)