Direct answer: to let Minecraft Bedrock players join a Java Paper or Purpur server, get Geyser-Spigot and Floodgate-Spigot from the official download page, place both JARs in plugins, start once to generate their files, shut the server down fully, configure a Bedrock UDP port, and set auth-type to floodgate. If the Java backend predates 26.2, add ViaVersion. The job is not complete until a Bedrock client connects from another network and the existing Java endpoint still works.
This guide uses Paper/Purpur for the full installation and then maps the differences for Fabric, NeoForge, Velocity, BungeeCord, and Geyser Standalone. The commands are examples for an administrator to adapt; they are not represented as tests performed on your server by Teramont.
What GeyserMC and Floodgate do—and do not do
Geyser listens for Bedrock traffic, usually on UDP 19132, translates Bedrock packets into the Java protocol, and hands the session to a Java server. It is a protocol gateway. It does not convert a world, create a second Bedrock copy of the map, or run two game servers. Java and Bedrock players reach the same backend, world, and server-side logic.
Floodgate handles a different layer. It authenticates Bedrock identities and lets those players join without owning Java Edition. It does not replace Geyser, and it does not mean turning authentication off. In a straightforward Paper deployment, Geyser performs protocol translation while Floodgate supplies the Bedrock identity; normal Java authentication can remain in place for Java players.
- Bedrock edge: a public IPv4 or A record plus the assigned UDP port.
- Translation: Geyser presents a Java-compatible session to the backend.
- Identity: Floodgate identifies and authenticates the Bedrock player.
- Backend: Paper, Purpur, or another supported platform owns the world. Geyser does not alter its format.
Compatibility as of July 30, 2026
Check the official supported-version table before chasing firewall or DNS issues. A perfectly open port cannot fix a protocol combination that has not been confirmed.
Version matrix at the editorial cutoff:
| Layer | Confirmed state | Operational effect |
|---|---|---|
| Bedrock clients | 26.0 through 26.33 | Update Geyser and recheck the table when the client falls outside this range. |
| Java client emulated by Geyser | 26.2 | The entry point and every backend must accept Java 26.2. |
| Java backend older than 26.2 | Needs ViaVersion | ViaVersion bridges the Java protocol gap; it does not change the world. |
| Geyser-Spigot | Paper/Spigot 1.20.5+ on Java 21+ | Verify both the server release and the runtime before installation. |
| Geyser-Fabric and Geyser-NeoForge | Currently limited to a 26.2 server | Fabric also needs Fabric API; client-required mods are not translated. |
Mojang documented Bedrock 26.34 on July 23 in the official hotfix changelog; see also what the Bedrock 26.34 hotfix changes. At the July 30 cutoff, Geyser’s official table still ends at 26.33. That means support is not yet confirmed; it does not prove 26.34 is incompatible. Update Geyser from the official source and check the table again before diagnosing the network. Do not recommend unofficial downloads or client downgrades as a workaround.
Choose the topology before copying a JAR
The correct build and placement depend on where public connections terminate. Installing Geyser on every node behind a proxy creates competing listeners and makes packet flow harder to reason about.
Platform decision table:
| Platform | Placement | Best fit | Critical detail |
|---|---|---|---|
| Paper/Purpur | Geyser-Spigot and Floodgate-Spigot in plugins | One server or a deployment with no proxy | Paper/Spigot 1.20.5+, Java 21+, and an assigned UDP port. |
| Fabric/NeoForge | Loader-specific mods in mods | A modded server that still accepts a vanilla client | Only server 26.2 at the cutoff; Fabric requires Fabric API. |
| Velocity/BungeeCord | Geyser and Floodgate on the proxy | A lobby and multiple backend servers | Geyser belongs only on the proxy. Backend Floodgate is optional for API/skins and requires the same protected key. |
| Standalone | A separate Java process pointed at the backend | No plugin/mod access at the edge, or deliberate gateway separation | Java 21+, its own service, a UDP port, and the correct Java target address and port. |
On Velocity or BungeeCord, every destination must accept the Java 26.2 client Geyser emulates. Put Geyser only on the proxy. Under the official Floodgate topology, install Floodgate on a backend only when its API or skin support is needed there. Then enable data forwarding, configure secure proxy forwarding, and distribute the same key.pem through a private channel.
Standalone is an application, not a plugin. It needs its own startup and supervision. For Floodgate authentication, Floodgate runs on the target Java server and the key is copied into the Standalone directory because that topology explicitly requires it.
Prerequisites and change plan
- Recoverable backup: take a full snapshot or backup and separately preserve
plugins,config, and firewall state. Make sure you can identify the restore point. - Known versions: record Paper/Purpur, the backend protocol, and the existing Geyser, Floodgate, and ViaVersion versions.
- Correct Java runtime: Geyser requires Java 21 or newer, and the server build must support that runtime.
- Operational access: you need full stop/start control, the complete startup log, file upload, and YAML editing. A
/reloadcommand is not a substitute. - Assigned UDP port: reserve 19132/UDP or another approved port. Voice Chat, Query, or any other UDP service cannot listen on the same port.
- Complete public path: account for OS and cloud firewalls, NAT, and DNS on a VPS; a Pterodactyl allocation; or a Docker UDP mapping.
- Measurable headroom: there is no universal Geyser RAM or CPU number. Keep capacity available, capture a baseline, and observe the actual workload.
Back up while the server is fully stopped
Stop the service through systemd or the panel and adjust these paths. The systemd example verifies that the unit is already stopped, creates a private backup of the changed areas, and preserves the previous UFW state; in Pterodactyl, confirm the stopped state in the panel before copying. A provider snapshot or full-server backup remains the preferred protection for the world.
#!/usr/bin/env bash
set -Eeuo pipefail
SERVER_DIR=/srv/minecraft
BACKUP_DIR=$HOME/minecraft-backups/geyser-$(date +%Y%m%d-%H%M%S)
UNIT=minecraft.service
umask 077
SERVICE_STATE=$(sudo systemctl show "$UNIT" --property=ActiveState --value)
[[ "$SERVICE_STATE" == inactive || "$SERVICE_STATE" == failed ]] || {
printf '%s\n' "Service $UNIT is not stopped; backup cancelled." >&2
exit 70
}
[[ -d "$SERVER_DIR/plugins" ]] || {
printf '%s\n' "Directory $SERVER_DIR/plugins does not exist." >&2
exit 66
}
install -d -m 700 "$BACKUP_DIR"
sudo cp -a -- "$SERVER_DIR/plugins" "$BACKUP_DIR/plugins"
if [[ -d "$SERVER_DIR/config" ]]; then
sudo cp -a -- "$SERVER_DIR/config" "$BACKUP_DIR/config"
fi
sudo find "$BACKUP_DIR/plugins" -type f -name key.pem -exec chmod 600 {} +
sudo ufw status numbered | tee "$BACKUP_DIR/ufw-before.txt" >/dev/null
Keep the previous JARs as well when this is an update. Rollback should restore a binary and its matching configuration; pairing an old JAR with a newly migrated config.yml can create a second failure.
How to install GeyserMC and Floodgate on Paper or Purpur
1. Confirm the runtime and backend
With the server stopped, check the Java executable the service actually uses. If a panel selects the runtime, verify its startup setting as well as the Java in your SSH shell.
java -version
The result must be Java 21 or newer. Confirm the Paper/Purpur base is supported by Geyser-Spigot and decide whether the backend accepts Java 26.2. If it is older, include ViaVersion in the change plan before opening public access.
2. Download only official artifacts
On the official download page, select Geyser for Spigot and Floodgate for Spigot. Avoid repackaging sites and build URLs copied from an old tutorial. Upload Geyser-Spigot.jar and Floodgate-Spigot.jar to plugins.
3. Generate files, then stop again
Start the server once and read the log from the beginning. Both plugins must enable without class-version, Java, or dependency errors. Once plugins/Geyser-Spigot/config.yml and the Floodgate directory exist, perform a full stop. Never swap these JARs while the server is running.
4. Change only the required keys
Keep the file generated by the installed release and edit its existing values. The essential fragment is:
bedrock:
address: 0.0.0.0
port: 19132
clone-remote-port: false
java:
auth-type: floodgate
bedrock.address: 0.0.0.0binds Geyser to all IPv4 interfaces in the host or container. It is not an address players should enter.bedrock.port: 19132is the inbound UDP port. If the panel assigned another port, use that number consistently in Geyser, the firewall, mapping, and client.clone-remote-port: falsepreserves the explicit Bedrock port. Enable it only when the provider requires the Java port to be cloned; when true, it can overwriteportat startup.java.auth-type: floodgatedelegates the Bedrock identity to Floodgate. Do not select it when Floodgate is absent.
When Geyser and Floodgate run on the same Paper/Purpur instance, do not manually copy key.pem into the Geyser directory. Local integration discovers it, and a stale duplicate can later produce a key mismatch.
5. Start cleanly and retain the log
Start again without /reload. Geyser and Floodgate should enable, and the Bedrock listener should bind without errors. If startup fails, stop here. More firewall rules cannot repair a plugin that never loaded.
Expose UDP 19132 without exposing anything else
Minecraft Java normally listens on TCP 25565; Bedrock uses UDP. A TCP-only rule for 19132 will not carry Geyser traffic. On an Ubuntu VPS with UFW, inspect the current policy first and allow only UDP on the chosen port:
sudo ufw status verbose
sudo ufw allow 19132/udp comment 'Geyser Bedrock'
sudo ufw status numbered
sudo ss -lunp 'sport = :19132'
Open your server to Java and Bedrock players
Choose a Minecraft hosting environment for deploying Geyser and managing versions, plugins, and network access in one infrastructure.


ss should show a Java process listening on UDP. No listener means the next check belongs in the startup log and config.yml. UFW covers only one layer: mirror the UDP permission in the provider’s cloud firewall or security rule, and configure NAT/port forwarding when the host does not own the public IPv4 directly.
Pterodactyl and Docker
Pterodactyl
With Pterodactyl, a node administrator must create and assign an allocation to the server. That allocation’s port must match bedrock.port, and the host must permit UDP. Editing YAML inside the container does not reserve a node port.
Docker and Compose
Docker and Compose also require an explicit UDP publication. This minimal section shows the protocol distinction:
services:
minecraft:
ports:
- '25565:25565/tcp'
- '19132:19132/udp'
Recreate the container with your normal deployment process and inspect the effective mapping. Publishing a port does not replace host or cloud firewall policy. Do not assume UFW handles every Docker-published path exactly like a non-container process.
The address Bedrock players should use
Provide a public IPv4 or a hostname with an A record, plus the explicit Bedrock port. Bedrock does not use a Minecraft Java SRV record, so a domain that hides the Java port may fail for Bedrock. External users must not receive 0.0.0.0, 127.0.0.1, or a private container address.
When ViaVersion is required
Geyser emulates a Java 26.2 client. If Paper/Purpur, the proxy, or any backend rejects that version because it runs an older protocol, install a current compatible ViaVersion release at the layer that processes protocol negotiation. On a proxy network, the official Geyser setup guide says that backends not running 26.2 need ViaVersion on those backends; then test the lobby and every server switch.
ViaVersion does not translate Bedrock and cannot replace Geyser. It only lets the Java server accept the Java protocol Geyser presents. Review the dependency chain of other plugins too; our guide to Minecraft server plugins can help organize that review, while each project’s official compatibility matrix remains authoritative.
End-to-end verification
- Startup: read the complete log and rule out Java 21, class, YAML, bind, and authentication errors.
- Plugin state: run
pluginsin the Paper/Purpur console. Geyser and Floodgate should be enabled. Use the platform-equivalent command on a proxy. - Listener: run
sudo ss -lunp 'sport = :19132'on the host. For containers, inspect both the internal listener and host mapping. - Built-in test: run
geyser connectiontest <public-ip> <port>in the server or proxy console. It is a Geyser command, not a Bash or SSH command. - External Bedrock join: use cellular data or another network and enter the public IPv4/A-record name and port. A same-LAN test can hide NAT trouble.
- Java regression: join through the normal Java endpoint and test the lobby, authentication, and backend switching where applicable.
- Correlate: watch the log during a Bedrock attempt. If no new line appears, the attempt probably did not reach the listener or was not logged; confirm the listener, log level, and UDP path. A logged attempt followed by disconnect points to version, auth, proxy, plugin, or anticheat behavior.
Record versions, port, timestamp, and the outcome. That evidence turns “GeyserMC does not work” into a fault isolated to one layer.
GeyserMC troubleshooting by symptom
The official Unable to Connect to World guide and common-issues page are the living references. Use this table to pick the first check instead of changing every setting at once.
Symptom, likely layer, and next check:
| Symptom | Likely layer | What to check |
|---|---|---|
| Unable to connect to world with no new console line | Network before Geyser | Bedrock IP/port, UDP in UFW/cloud/NAT, Pterodactyl allocation, Docker mapping, and connectiontest. Do not change authentication yet. |
Geyser is absent from plugins | Plugin loading | The Spigot build is in plugins, Paper/Spigot is 1.20.5+, Java is 21+, and the first relevant startup exception. The last log line is rarely enough. |
| Outdated client or Outdated server | Protocol | Update Geyser officially, check supported versions, and install ViaVersion when the backend predates 26.2. Bedrock 26.34 was still unconfirmed at the cutoff; do not blame the firewall by default. |
| Address already in use or BindException | Local port collision | Identify the listener with sudo ss -lunp 'sport = :19132'. Stop the duplicate instance or assign a different UDP port; do not kill unknown processes. Voice Chat and Query cannot share it. |
| Java works, Bedrock does not | Bedrock UDP route or DNS | Confirm you did not allow TCP only, the client uses the Bedrock port, and the hostname has an A/IPv4 record. Bedrock ignores the Java SRV route. |
| The attempt is logged, then login fails | Floodgate/authentication | Confirm Floodgate loaded and auth-type is floodgate. Remove obsolete manual key copies on a single Paper server; on proxy/Standalone, verify the required key matches and remains private. |
| Works on a host, fails in Pterodactyl or Docker | Container isolation | Align the internal listener, UDP allocation or mapping, host firewall, and public port. Opening UFW alone does not publish a container port. |
| Mobile/Windows joins, a console does not | Console connection method | Custom-server restrictions vary by console. BedrockConnect or a LAN proxy may be required. Use a mobile/Windows client as the control; do not promise universal direct connection. |
| The player joins and anticheat kicks them | Movement/packet compatibility | Consult the official anticheat compatibility page, update, and apply only documented Bedrock/Floodgate adjustments. |
| Crossplay works but performance is poor | Performance | Separate translation overhead from ticks, networking, and plugins. Profile a repeatable case; the spark troubleshooting guide keeps the investigation evidence-based. |
Floodgate and network security
- Protect
key.pem: never attach it to public tickets, commit it, place it in a shared backup, or expose it in screenshots. It authorizes Floodgate identities across Java authentication. - Copy the key only when the topology calls for it: a single Paper server does not need a Geyser-side copy. Proxy backends using Floodgate and Standalone do require a matching key as documented; transfer it privately.
- Do not set
online-mode=falseas a Floodgate “fix”: a direct Paper deployment can keep normal Java authentication. Proxy backends need isolation and secure Velocity/Bungee forwarding, not public exposure. - Expose only the game port: allowing UDP for Geyser does not justify opening the panel, SSH, RCON, database, or administration ports to the internet.
- Do not disable the firewall permanently: if a brief controlled test isolates the firewall, re-enable it and write the narrow rule.
- Audit identity-aware plugins: permissions, chat, bans, and databases must handle Floodgate names and UUIDs correctly.
On a VPS, set the key owner and mode to the actual service account. Do not run this example until both the path and user have been verified:
KEY_FILE=/srv/minecraft/plugins/floodgate/key.pem
sudo chown minecraft:minecraft "$KEY_FILE"
sudo chmod 600 "$KEY_FILE"
Real limitations with mods, plugins, and interfaces
Geyser works with server-side mods only when a vanilla client can join. It does not download, emulate, or translate a mod that needs a client installation. A Java modpack with custom client blocks, screens, or packets therefore does not become Bedrock-compatible just because Geyser is present.
Plugin design can expose edition differences as well. The official current-limitations list includes left-versus-right inventory clicks that cannot be distinguished, command arguments outside Brigadier, some custom enchantment or recipe behavior, and visual states represented differently by Bedrock. Test these flows before launch:
- shop, auction, claim, and kit-selection inventories;
- essential commands and arguments from the Bedrock UI;
- anticheat, parkour, vehicles, and movement-sensitive mechanics;
- resource packs and custom content;
- permissions, bans, chat, and teleportation with a new Floodgate identity.
A visual mismatch does not always mean the server lost state, but a critical workflow that depends on an unavailable click needs a compatible alternative or redesign.
Maintenance and future update policy
- Before or immediately after an automatic Bedrock update, check Geyser’s supported-version table and official download.
- Back up the working JAR, configuration, and
key.pem; record the known-good release. - Fully stop, replace the JAR, and start. Avoid hot reload.
- Review generated config changes. Do not overwrite a new file with an old one without comparing keys.
- Update ViaVersion when the emulated Java protocol changes, then verify every backend.
- Repeat an external Bedrock join and a Java regression. On proxy networks, include server switching.
- Revisit limitations and anticheat compatibility when updates affect inventories, movement, or custom content.
The update rule is simple: if the official table has not yet listed a newly released version, call support unconfirmed, observe the project’s official channels, and wait for an official build. Do not turn a protocol update into a hunt for questionable old clients.
Rollback: remove Geyser without touching the world
If Java worked before the change and crossplay fails acceptance testing, restore the artifacts and their matching configuration. This example assumes a systemd unit named minecraft.service; use Pterodactyl Stop/Start controls where applicable. Replace BACKUP_DIR with the restore point created before installation. Run this flow only in a change window with no concurrent plugin changes: it replaces the complete plugins tree with the restore point and returns ViaVersion to its previous state. If other changes occurred after the backup, do not run it; restore from an explicit manifest of every changed artifact and its prior state.
#!/usr/bin/env bash
set -Eeuo pipefail
SERVER_DIR=/srv/minecraft
BACKUP_DIR=/home/minecraft/minecraft-backups/geyser-20260730-120000
UNIT=minecraft.service
QUARANTINE_DIR="$SERVER_DIR/rollback-geyser-$(date +%Y%m%d-%H%M%S)"
[[ -d "$SERVER_DIR/plugins" ]] || {
printf '%s\n' "Directory $SERVER_DIR/plugins does not exist." >&2
exit 66
}
[[ -d "$BACKUP_DIR/plugins" ]] || {
printf '%s\n' "Restore point does not contain plugins: $BACKUP_DIR." >&2
exit 66
}
sudo systemctl stop "$UNIT"
if sudo systemctl is-active --quiet "$UNIT"; then
printf '%s\n' "Service is still active; rollback cancelled." >&2
exit 70
fi
sudo install -d -m 700 "$QUARANTINE_DIR"
sudo mv -- "$SERVER_DIR/plugins" "$QUARANTINE_DIR/plugins-after-change"
sudo cp -a -- "$BACKUP_DIR/plugins" "$SERVER_DIR/plugins"
sudo systemctl start "$UNIT"
sudo systemctl is-active --quiet "$UNIT"
Read the startup log and join over Java. If UDP was opened only for Geyser, compare ufw-before.txt with the current state and remove only the numbered rule that did not exist before. Preserve any equivalent rule found in the saved state. Recheck numbering after every deletion, including any IPv6 entry.
#!/usr/bin/env bash
set -Eeuo pipefail
BACKUP_DIR=/home/minecraft/minecraft-backups/geyser-20260730-120000
[[ -f "$BACKUP_DIR/ufw-before.txt" ]] || {
printf '%s\n' "Previous UFW state is missing; no rule will be removed." >&2
exit 66
}
sudo ufw status numbered
diff -u "$BACKUP_DIR/ufw-before.txt" <(sudo ufw status numbered) || true
read -r -p 'Exact number of the new Geyser rule (blank to cancel): ' RULE_NUMBER
[[ "$RULE_NUMBER" =~ ^[0-9]+$ ]] || {
printf '%s\n' 'No exact rule was selected; UFW remains unchanged.' >&2
exit 64
}
sudo ufw delete "$RULE_NUMBER"
sudo ufw status numbered
Remove the UDP mapping on the next Docker deployment, release the Pterodactyl allocation if it is no longer needed, and delete the matching cloud rule. Do not delete or convert world files: Geyser never required a world-format change. Keep the quarantine until Java is confirmed stable.
Frequently asked questions
Does a Bedrock player need to own Java Edition?
No, provided Floodgate is installed and configured correctly. Floodgate authenticates the player’s Bedrock identity for entry through Geyser.
Can Java and Bedrock use the same port number?
TCP and UDP are distinct, so the same number can technically be used when the provider allocates both and no other UDP listener conflicts. Java TCP 25565 plus Bedrock UDP 19132 is usually clearer. Never share Geyser’s UDP listener with Voice Chat, Query, or another UDP service.
Can Bedrock use my Java SRV record?
Not as a general connection path. Provide an A/IPv4 record and the explicit Bedrock port. An SRV record that hides the Java port can produce an invalid-address error or route Bedrock to the wrong destination.
Does Geyser support Fabric or NeoForge?
Yes, through loader-specific builds, but as of July 30, 2026 they run only on a 26.2 server; Fabric also requires Fabric API. Only server-side mods compatible with vanilla clients are candidates.
Why does geyser connectiontest fail in SSH?
It is a plugin or proxy command. Run it in the Minecraft console where Geyser is loaded, using the public IP and Bedrock port.
Can Xbox, PlayStation, or Switch connect directly?
There is no universal guarantee. Custom-server controls vary by platform, and BedrockConnect or a LAN proxy may be needed. If mobile or Windows works while a console fails, investigate that console’s connection method first.
Does Geyser duplicate or modify the world?
No. It translates protocols into the same Java backend. Rollback removes plugins, configuration, and network exposure; it does not need to touch the world.
Conclusion
Reliable Java–Bedrock crossplay comes from aligning five layers: a supported version, the right Geyser build and placement, Floodgate authentication, a live UDP listener, and an actually published port. Use official downloads, test from outside the network, and keep a rollback that leaves Java intact. If an attempt leaves no console record, start with the listener, logging, and UDP path; if it is logged and fails, inspect version, authentication, or compatibility. That boundary is far more useful than changing settings at random.








