setupmc.com

Run Geyser and Floodgate on a Velocity Proxy with Docker

Add Bedrock crossplay at the Velocity edge, publish UDP 19132 correctly, configure Floodgate authentication, and keep Geyser off the individual backends.

Networking
setupmc.com Team

Use the matching tool

Minecraft proxy configurator

Create a Docker Compose setup for Velocity, BungeeCord, or a custom proxy.

Open Minecraft proxy configurator

Choose the proxy deployment intentionally

The existing direct Geyser and Floodgate guide installs both plugins on one Paper server. This guide covers a different architecture: Velocity is already the public entry point for multiple backends, so Geyser runs on the proxy.

Geyser's current proxy guidance is explicit:

  • install Geyser only on the proxy
  • install Floodgate on the proxy for Bedrock account authentication
  • add Floodgate to backends only when backend plugins need its API or related data
  • make every backend compatible with the Java protocol version Geyser currently emulates

Check Geyser's supported-versions page before an update. Bedrock clients move quickly, so hard-coded version claims age faster than the network design.

Step 1: Start from a working Velocity network

Complete these checks first:

  • Java players can join Velocity and reach a Paper backend.
  • Velocity modern forwarding works.
  • Backends are not public.
  • The proxy has a persistent /server mount.

Use the Velocity Compose guide and modern forwarding runbook if any of those statements is false.

Step 2: Add the proxy plugins and UDP mapping

The itzg/mc-proxy image can download plugin URLs into the proxy plugin directory. Add the official Geyser and Floodgate Velocity download endpoints and publish the Bedrock listener as UDP:

services:
  proxy:
    image: itzg/mc-proxy:latest
    ports:
      - "25565:25577"
      - "19132:19132/udp"
    environment:
      TYPE: VELOCITY
      MEMORY: 1G
      PLUGINS: "https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest/downloads/velocity,https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/velocity"
    volumes:
      - ./proxy:/server

The latest download endpoints are convenient for the first setup but change over time. For controlled production updates, pin reviewed plugin artifacts or preserve known-good JARs and update them as one tested operation.

Render the Compose file before starting:

docker compose config
docker compose up -d proxy
docker compose logs -f proxy

Confirm both plugins load without dependency or Java errors.

Step 3: Configure the Bedrock listener

After the first start, open the Geyser configuration below the proxy's plugin directory and check:

bedrock:
  address: 0.0.0.0
  port: 19132
  clone-remote-port: false

0.0.0.0 allows Geyser to listen on the container interfaces. The Compose mapping publishes that container UDP port on the host. Do not remove /udp; an unsuffixed Compose mapping is TCP and will not carry normal Bedrock traffic.

In the same generated Geyser configuration, locate auth-type and set it to floodgate. The surrounding section name can change between configuration versions, so edit the generated file instead of replacing it wholesale with an older example.

Restart the proxy after changing the configuration:

docker compose restart proxy
docker compose logs --tail=150 proxy

Step 4: Open UDP end to end

Four layers must agree on the same port and protocol:

  1. Geyser listens on UDP 19132 in the container.
  2. Compose maps 19132:19132/udp.
  3. The Linux or Windows host firewall allows UDP 19132.
  4. The router or cloud-provider firewall allows UDP 19132 to the host.

Do not replace the Java TCP rule with the Bedrock rule. Java and Bedrock use different transport paths here:

ClientPublic endpoint
Java Editionplay.example.com:25565/tcp
Bedrock Editionplay.example.com:19132/udp

An SRV record used by Java does not remove the Bedrock port in this setup. Tell Bedrock players the explicit port.

Step 5: Validate from inside and outside

Check the Docker mapping:

docker compose port proxy 19132/udp
docker compose logs --tail=150 proxy

Then run Geyser's own external connection test from the proxy console:

geyser connectiontest play.example.com 19132

Finally, test with a Bedrock client from a different network. A local Wi-Fi test alone does not prove that router or provider UDP ingress works.

The first successful login should reach the same backend selected by Velocity. Verify the player in both proxy and backend logs and confirm that their name/UUID behavior matches your Floodgate policy.

When backends need Floodgate too

Basic crossplay does not require Floodgate on every Paper server. Add it only when backend plugins need the Floodgate API, Bedrock skin handling, or Floodgate data.

The official extended procedure requires send-floodgate-data: true on the proxy and the same Floodgate key.pem on the trusted backends. That key enables Bedrock authentication and must never be published or sent to untrusted people. Transfer it as binary data, restrict file access, and rotate/rebuild the trust relationship if it leaks.

Troubleshooting

SymptomLikely causeFix
Java works, Bedrock shows “Unable to connect”UDP mapping or firewall missingVerify all four UDP layers and run geyser connectiontest
Geyser is loaded on every backendWrong proxy architectureKeep Geyser only on Velocity
Bedrock reaches Geyser but not the backendVelocity/backend path or version mismatchTest Java through Velocity and check Geyser supported versions
Floodgate login asks for Java authenticationGeyser auth type not set to FloodgateAlign generated Geyser and Floodgate configuration
AEADBadTagException after copying keysFloodgate keys differ or were transferred incorrectlyRecreate/copy the exact key according to Floodgate docs
UDP 19132 conflicts with another pluginTwo services use the same UDP portAssign unique UDP listeners

Next steps

Frequently asked questions

Short answers to the questions that usually come up while working through this topic.