Geyser 2.11.1 on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and use of Geyser 2.11.1 on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images.
Geyser is the standard open source bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition. Bedrock players on console, mobile and Windows normally cannot join a Java Edition server at all; Geyser sits in front of your Java server and translates the Bedrock protocol on the fly, so both editions can play together on infrastructure you control.
Geyser is a gateway, not a game server. This image does not include or require a bundled Minecraft server, and it ships no Mojang owned game content or assets of any kind. You bring your own Minecraft: Java Edition server, running on this VM or elsewhere, and your own Minecraft clients; Geyser only bridges the connection between them. Nothing about a working Geyser installation implies a Java server is already running anywhere — that is a separate step you control.
What you get
| Capability | What it means in practice |
|---|---|
| A working Bedrock listener from boot | Geyser starts automatically and binds the standard Bedrock port over UDP the moment the VM is up — no manual startup step. |
| Real protocol proof, not a port check | The image ships a self test that speaks the actual RakNet discovery protocol every Bedrock client uses, and proves a genuine reply, not merely that a process is running. |
| The address problem solved | First boot resolves the VM's real public IP and leaves it in a connection note — the value your Bedrock clients need is right there, no guessing. |
| Point and edit configuration | One clearly commented config.yml file. Point the java: section at your own Java server and restart. |
| A contained service | The server runs as a dedicated no shell account under a locked down systemd sandbox. There is no admin login, no web console and no credential of any kind. |
Licence
Geyser is free software licensed under the MIT License — verified from the LICENSE file bundled inside the exact jar this image ships, not from a badge.
Geyser's jar is a shaded build and bundles a small number of third party dependency licences alongside its own. All are permissive, and one is copyleft in a way that is fully compatible with redistribution:
/opt/geyser/licenses/LICENSE-geyser-MIT.txt— Geyser itself, MIT./opt/geyser/licenses/LICENSE-MinecraftAuth-LGPL-3.0.txt— the bundled MinecraftAuth library (handles Java/Xbox Live account authentication), GNU LGPL 3.0. Shipped unmodified, exactly as the licence permits./opt/geyser/licenses/LICENSE-thirdparty-Apache-2.0.txtandLICENSE-thirdparty-slf4j-MIT.txt— aggregated notices for further permissively licensed dependencies (Apache 2.0 and MIT/BSD style).
The same four files are also kept at /usr/share/doc/cloudimg/geyser/ for easy reference. No AGPL, SSPL or other network copyleft component exists anywhere in the shipped jar.
Minecraft is a trademark of Mojang Synergies AB. Geyser is an independent, community maintained project and is not affiliated with, endorsed by, or sponsored by Mojang or Microsoft.
Before you start
| Item | Value |
|---|---|
| Recommended VM size | Standard_B2s (2 vCPU / 4 GiB) — Geyser itself used around 590 MB resident with default heap settings while idling with the listener bound |
| Bedrock listener port | 19132, UDP — Minecraft: Bedrock Edition uses UDP exclusively for gameplay; this port must allow UDP traffic |
| SSH | 22, restricted to your own address |
| Admin credential | None exists. Geyser has no admin login, web console or credential of any kind — see Security posture |
| Java server | Not included. You provide your own Minecraft: Java Edition server, on this VM or elsewhere, and point Geyser at it |
Network security group
Bedrock Edition speaks to Geyser entirely over UDP. Opening only TCP is the single most common reason a freshly deployed Geyser "looks fine on the VM" but no Bedrock client can find it:
az network nsg rule create --resource-group <your-rg> --nsg-name <your-nsg> \
--name geyser-bedrock-udp --priority 1010 \
--access Allow --protocol Udp --direction Inbound \
--source-address-prefixes Internet --destination-port-ranges 19132
Run that from your workstation with your own resource names. Do not open anything else on this VM — SSH on 22 (restricted to your own address) and the Bedrock listener are the only two things this image exposes. If your Java Edition server runs on a different machine, that machine needs its own Java port (25565 by default) reachable from this VM — that is a separate NSG on that other machine, not this one.
First boot
On first boot the VM resolves its own public IP address and writes it into a connection note for you. Geyser itself has nothing to bootstrap or protect — there is no admin credential to rotate — so the Bedrock listener starts on its own at every boot, independent of this step.
Give the VM a minute after it reports Running, then check both units:
systemctl is-active geyser-firstboot.service geyser.service
Both should report active. Then read this VM's connection note:
sudo cat /root/geyser-instance-info.txt
Expected output (your address will differ):
# Geyser — Instance Info (written by geyser-firstboot.service on first boot)
# Geyser has no admin login of any kind — this file is informational only,
# it never contains a secret or credential.
GEYSER_PUBLIC_IP=20.106.160.134
GEYSER_BEDROCK_PORT=19132
GEYSER_MOTD=cloudimg Geyser
# Point Geyser at your own Minecraft: Java Edition server by editing the
# "java:" section of /opt/geyser/config.yml, then: sudo systemctl restart geyser
# Bedrock clients connect to: udp://20.106.160.134:19132
GEYSER_PUBLIC_IP and GEYSER_BEDROCK_PORT are exactly what your Bedrock clients need. The same summary is shown on every SSH login.

Point Geyser at your Java server
Geyser ships with an honest placeholder: java.address is 127.0.0.1 and java.port is 25565, Geyser's own upstream default. There is no fake or invented backend — until you edit this, Geyser is listening correctly but has nothing to bridge to.
sudo nano /opt/geyser/config.yml
Find the java: section near the top and set it to your real server:
java:
address: 127.0.0.1 # <- change to your Java server's address
port: 25565 # <- change to your Java server's port
auth-type: online # "online" (Microsoft account), "offline", or "floodgate"
forward-hostname: false
- If your Java Edition server runs on this same VM, install it separately and keep
address: 127.0.0.1, just correct theport:if it differs from 25565. - If it runs elsewhere, set
addressto that server's reachable IP or hostname. - Set
auth-typeto match how your Java server is configured:onlineif it runs in online mode (the default, requires a Microsoft account),offlineif your Java server runs in offline mode, orfloodgateif you have the Floodgate plugin installed on the Java server itself.
Apply the change:
sudo systemctl restart geyser
Verifying your deployment
The image carries its own protocol level check. It does not settle for "a port is open" — it speaks the real RakNet discovery protocol every Bedrock client and every third party server list tool uses:
sudo /usr/local/sbin/geyser-selftest
Expected output:
OK Bedrock RakNet unconnected-pong: edition=MCPE motd="Geyser" protocol=2168 mcversion=26.40 players=0/100
That line proves the JVM started cleanly, config.yml parsed without error, and the Bedrock RakNet listener is genuinely bound and answering with a well formed reply — independent of whether your Java backend is reachable yet. A Bedrock client performs exactly this exchange (an Unconnected Ping, answered with an Unconnected Pong carrying the MOTD) the moment it lists your server, before it ever attempts to join.

If the self test fails, see Troubleshooting.
Managing the service
systemctl status geyser.service --no-pager
The server logs to the systemd journal:
sudo journalctl -u geyser.service --no-pager | tail -20
A healthy start looks like this:
[INFO] Loading extensions...
[INFO] Loaded 0 extension(s)
[INFO] Loading Geyser version 2.11.1-b1216 (git-master-1e448d6)
[INFO] Registered 199 custom block overrides.
[INFO] Registered 7 custom blocks.
[INFO] Started Geyser on UDP port 19132
[INFO] Done (4.449s)! Run /geyser help for help!
Restart at any time — Geyser holds no persistent game state of its own, only in-flight connections, which reconnect automatically from the client side:
sudo systemctl restart geyser.service
The listener surface is deliberately minimal — the Bedrock port, and SSH:
ss -uln | grep ':19132 '
ss -tln | grep -E ':(22) '

Configuration reference
Geyser's own first run generated the full config.yml this image ships, with every option documented inline:
sudo cat /opt/geyser/config.yml
The settings you are most likely to touch:
| Setting | This image | Meaning |
|---|---|---|
bedrock.address / bedrock.port |
0.0.0.0 / 19132 |
The Bedrock listener. Leave as is unless you need to restrict which interface accepts connections. |
java.address / java.port |
127.0.0.1 / 25565 (placeholder) |
Your Java Edition server. You must edit this — see Point Geyser at your Java server. |
java.auth-type |
online |
Matches Geyser's own upstream default. Change to offline or floodgate to match your Java server. |
motd.primary-motd / motd.passthrough-motd |
Geyser / true |
The MOTD shown to Bedrock clients. Passthrough relays your Java server's real MOTD once it is reachable. |
gameplay.enable-integrated-pack |
true |
Serves the bundled resource pack Bedrock clients need for some Geyser only features. |
enable-metrics |
true |
Anonymous bStats usage reporting, Geyser's own default. Set to false to disable. |
Every option is documented with a comment directly above it in the file itself — there is no separate reference to keep in sync.
Upgrading Geyser
Geyser ships as a single jar with no bundled data to migrate. config.yml is preserved across an upgrade — Geyser only adds newly introduced keys, it never removes your edits.
curl -fsSL -o /tmp/Geyser-Standalone.jar \
https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest/downloads/standalone
sudo systemctl stop geyser.service
sudo install -o geyser -g geyser -m 0644 /tmp/Geyser-Standalone.jar /opt/geyser/Geyser-Standalone.jar
sudo systemctl start geyser.service
Then confirm the new version in the journal and re-run the self test:
sudo journalctl -u geyser.service --no-pager | grep 'Loading Geyser version' | tail -1
sudo /usr/local/sbin/geyser-selftest
Security posture
Geyser has no admin login, no web console and no user database of any kind — its entire purpose is to listen on the network and forward per its configuration. This image does not invent a credential where none exists; instead, secure by default means containment and honest configuration:
- A dedicated account. The server runs as the
geysersystem user with no shell and no home login. - A locked down sandbox. The systemd unit applies
NoNewPrivileges,ProtectSystem=strict,ProtectHome,PrivateTmpand a read write allowance for/opt/geyseronly. - A minimal surface. UDP 19132 and TCP 22 — nothing else listens, and the build fails if anything else ever does.
- No per instance secret to leak. First boot writes only an informational connection note; there is no credential file, no default password and nothing to rotate.
cat /opt/geyser/licenses/LICENSE-geyser-MIT.txt

Recommendations:
- Restrict the SSH rule in your NSG to your own address; only the Bedrock UDP rule needs
Internetas a source. - Give players the address from the connection note, nothing else — there is nothing else to give.
- If your Java server lives on a different machine, secure that machine's own Java port separately; this VM's NSG only governs Geyser's own listener.
Server components
| Component | Version | Install path |
|---|---|---|
| Geyser Standalone | 2.11.1 (build 1216) | /opt/geyser/Geyser-Standalone.jar |
| OpenJDK runtime | 21 (Ubuntu package, auto updated) | /usr/lib/jvm |
| Configuration | — | /opt/geyser/config.yml |
| Self test | — | /usr/local/sbin/geyser-selftest |
| Licences | MIT (Geyser) + LGPL 3.0 (MinecraftAuth) + Apache 2.0/MIT (third party) | /opt/geyser/licenses/, /usr/share/doc/cloudimg/geyser/ |
Filesystem layout
| Mount point | Size | Description |
|---|---|---|
| / | 30 GB | Root filesystem |
| /boot/efi | 100 MB | UEFI boot partition (Gen2 Hyper V) |
| /mnt | varies | Azure temporary resource disk |
Key directories:
| Path | Purpose |
|---|---|
/opt/geyser |
Working directory: the jar, config.yml, cached bundled assets and licences |
/var/lib/cloudimg |
First boot sentinel |
/root/geyser-instance-info.txt |
The per VM connection note (informational, not a secret) |
Troubleshooting
Bedrock clients cannot find the server.
Almost always the NSG: Bedrock Edition needs UDP 19132 open, not TCP. Re-check the rule, then run the self test on the VM — if it reports OK, the server side is proven and the problem is network reachability from the client's side.
The self test fails.
Read what it printed — the failure reason is in the message (FAIL-no-response, FAIL-unexpected-packet-id, etc.). FAIL-no-response with the service reporting active usually means a local firewall change blocked UDP; check the journal:
sudo journalctl -u geyser.service --no-pager | tail -30
Bedrock clients connect but cannot actually join a world.
This means the Bedrock side is working — the RakNet listener is proven live by the self test. The remaining step is entirely the Java side: confirm java.address / java.port in config.yml point at a real, running Java Edition server, and that server is reachable from this VM (nc -zv <java-address> <java-port> from this VM's shell is a quick check). Also confirm auth-type matches how that Java server is configured.
The service is not running.
systemctl status geyser.service --no-pager
sudo journalctl -u geyser.service --no-pager | tail -30
The connection note shows the wrong address. First boot resolves the address once; if the VM's public IP changes later (for example after deallocating and restarting without a static IP), re-run first boot manually:
sudo rm -f /var/lib/cloudimg/geyser-firstboot.done
sudo systemctl start geyser-firstboot.service
sudo cat /root/geyser-instance-info.txt
Support
cloudimg images come with 24/7 support. Include the output of sudo /usr/local/sbin/geyser-selftest and the last lines of sudo journalctl -u geyser.service with any request.
- Email: support@cloudimg.co.uk
- Response time: 24/7 with guaranteed 24 hour response SLA
- Website: https://www.cloudimg.co.uk
Geyser itself is community software — for protocol questions and feature requests, the upstream project and its Discord community are the right place.