Skip to content

feat(geyser): bedrock entry point and floodgate delivery - #223

Merged
hbrombeer merged 3 commits into
mainfrom
feat/bedrock
Aug 13, 2026
Merged

feat(geyser): bedrock entry point and floodgate delivery#223
hbrombeer merged 3 commits into
mainfrom
feat/bedrock

Conversation

@hbrombeer

Copy link
Copy Markdown
Member

Three pieces of the Bedrock path. Both new images are pinned to an exact build with a verified sha256, so a version bump without a matching digest fails the build rather than shipping something unverified.

geyser

Geyser Standalone 2.11.1 build 1219. Terminates the RakNet/UDP session a Bedrock client opens and connects to Velocity as an ordinary Java client — nothing downstream of the proxy learns the player came from Bedrock.

The config is mounted at /config and copied into the working directory by start.sh, because Geyser rewrites config.yml on startup and cannot do that against a read-only mount. It exits with FileSystemException: ... Resource busy, reported as a config error. Matching chart change: groundsgg/charts#160.

No HEALTHCHECK: Geyser speaks RakNet over UDP and exposes no HTTP endpoint, and a UDP port probe cannot tell "listening" from "nothing there" — it would report healthy for a dead process.

plugin-floodgate

The Floodgate Velocity JAR 2.2.5 build 140 at /jar/plugin.jar, which is the plugin-velocity-jar chart's contract. Nothing in the image is ever executed.

Floodgate is what lets a single online-mode proxy accept Bedrock players: it verifies the player data Geyser signs with a shared key and assigns a UUID derived from the XUID, shaped 00000000-0000-0000-XXXX-XXXXXXXXXXXX so it can never collide with a real Java UUID. The alternative — an offline-mode proxy — derives UUIDs from the username, so a Bedrock player and a Java player sharing a name would share an identity. With ratings keyed on (player, mode) that is not a cosmetic difference.

The zeroed high bits are also how the rest of the network can recognise a Bedrock player (uuid.mostSignificantBits == 0) without taking a dependency on Floodgate.

velocity

start.sh learns VELOCITY_FORCE_KEY_AUTHENTICATION. Floodgate needs that setting off — Bedrock players have no Mojang profile key and are kicked at login while it is enforced. Making it an env var is what lets only the Bedrock proxy relax it while the Java proxies keep enforcing chat signatures; velocity.toml is baked into the image, so otherwise this would need a second image.

Unset keeps the image default, so this is a no-op for every existing release.

Registered in all three matrices

CI, build-push and release-please each carry a hardcoded container list. A container missing from one is not an error — the jobs skip and the run goes green having built nothing. (That exact trap cost a cycle in groundsgg/charts#158.)

Verified locally

Both images built with docker build, so the checksum verification actually ran:

  • plugin-floodgate/jar/plugin.jar, 6.9 MB, valid ZIP header
  • geyser — runs as uid 100, Java 25, /opt/geyser/Geyser.jar 29.7 MB

and geyser run against the chart's rendered config:

Loading Geyser version 2.11.1-b1219 (git-master-9163e05)
Started Geyser on UDP port 19132
Done (4.454s)! Run /geyser help for help!

One operational note

Geyser downloads a Minecraft JAR at startup to extract assets (Downloading Minecraft JAR to extract required files...). The pod needs egress for that. Worth checking against pulumi/core/src/platform/network-policies.ts before this runs anywhere locked down.

Three pieces of the Bedrock path, all pinned to an exact build with a
verified checksum so a version bump without a matching digest fails the
build rather than shipping something unverified.

geyser — Geyser Standalone (2.11.1 build 1219). Terminates the RakNet/UDP
session a Bedrock client opens and connects to Velocity as an ordinary Java
client. The config is mounted at /config and copied into the working
directory by start.sh, because Geyser rewrites config.yml on startup and
cannot do that against a read-only mount — it exits with "Resource busy",
reported as a config error.

plugin-floodgate — the Floodgate Velocity JAR (2.2.5 build 140) at
/jar/plugin.jar, which is the plugin-velocity-jar chart's contract. Floodgate
is what lets a single online-mode proxy accept Bedrock players: it verifies
the player data Geyser signs and assigns a UUID derived from the XUID, shaped
so it can never collide with a real Java UUID. An offline-mode proxy would
derive UUIDs from the username instead, which means a Bedrock player and a
Java player sharing a name share an identity.

velocity — start.sh learns VELOCITY_FORCE_KEY_AUTHENTICATION. Floodgate needs
that setting off, since Bedrock players have no Mojang profile key and are
kicked at login while it is enforced. Making it an env var is what lets only
the Bedrock proxy relax it while the Java proxies keep enforcing.

Both images are registered in all three hardcoded matrices — CI, build-push
and release-please. A container missing from one of them is not an error;
the jobs simply skip and the run goes green having built nothing.
Floodgate reads its key from its own plugin data directory and also creates
a config.yml there on first start, so mounting the Secret straight onto
plugins/floodgate would make that directory read-only and the plugin would
fail to initialise — the same trap Geyser has with its config.

FLOODGATE_KEY_FILE points at a neutral mount and the key is copied in,
leaving the directory writable. Unset is a no-op, so this changes nothing
for the Java proxies.
start.sh gained two load-testing knobs on main while this branch was open.
Both sides kept, with the Bedrock block placed FIRST on purpose: the
offline-mode block also forces force-key-authentication off, and it has to be
able to override an explicit `true` from VELOCITY_FORCE_KEY_AUTHENTICATION.
An offline player carries no Mojang-signed key either, so enforcing it there
would reject them one step later and look like an unrelated failure.
@hbrombeer
hbrombeer merged commit 1de7739 into main Aug 13, 2026
8 checks passed
@hbrombeer
hbrombeer deleted the feat/bedrock branch August 13, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant