Serveur Minecraft Bedrock

Create a Minecraft Bedrock Server on Ubuntu 26.04 LTS

Updated the:

Reading time:

15–23 minutes

Minecraft Bedrock is the edition that lets players on Windows, Android, iOS, Xbox and PlayStation meet in the same world. This tutorial installs a Minecraft Bedrock server on Ubuntu 26.04 LTS — Mojang’s official software, not a fork — as a permanent service: it starts with the machine, restarts itself after a crash, backs itself up every night and updates with a single command.

Every command uses absolute paths, so you can paste them one after another without ever wondering which directory you are in.

What has changed since our Ubuntu 20.04 tutorial

Four things, and they matter:

  1. The firewall rules are no longer the same at all. Mojang replaced the original network transport (RakNet, on UDP 19132) with NetherNet, which listens on TCP 19132 for the handshake and then opens one UDP port per player. The old tutorial’s ufw allow 19132/udp rule no longer opens anything useful. Worse, the server now refuses the old mode: set to raknet, it writes in its log that NetherNet is the only supported transport type in this release and that players will not be able to connect. Sections 3 and 6 account for both changes.
  2. The download address has changed. The old minecraft.azureedge.net host no longer exists at all. Our command now looks up the current release in Mojang’s official index, so this tutorial will not go stale.
  3. No more libssl1.1 workaround. Many guides still have you install an old OpenSSL library. It is no longer needed: the current server depends only on the system C library, and Ubuntu 26.04 ships one far newer than the minimum required.
  4. The allow list is now on by default. A freshly installed server turns everyone away until you add players to it (section 7). This is the number one cause of “it doesn’t work” on recent servers.

What you need

  • An Ubuntu 26.04 LTS server on x86-64 hardware (Intel or AMD). Mojang does not publish an ARM build of the Bedrock server, so an ARM VPS will not work. If you don’t have a server yet, have a look at our virtual servers.
  • 2 cores and 1 GB of memory at a minimum, which is what Mojang recommends. Plan on 2 GB from four or five simultaneous players onward.
  • SSH access to the server with a user who can run sudo.
  • The Xbox gamertag of everyone who will play: you’ll need them for the allow list.

A note on licensing. The Bedrock server is free but proprietary software. By downloading it you accept the Minecraft End User Licence Agreement and the Microsoft privacy statement. The server also sends Mojang a report automatically if it crashes.


1. Update the server

Always start here. The first sudo command of the session will ask for your password.

Shell
sudo apt update && sudo apt full-upgrade -y

If the kernel was updated, a reboot is needed. This command reboots only if Ubuntu asks for one:

Shell
if [ -f /var/run/reboot-required ]; then echo "Rebooting in 5 seconds..."; sleep 5; sudo reboot; else echo "No reboot required."; fi

Reconnect over SSH if the server rebooted, then carry on.

2. Install the required packages

Four packages only: unzip to extract the archive, screen to keep the server console reachable, openssl for the server identity, and ufw for the firewall.

Shell
sudo apt install -y unzip screen openssl ufw

Watch out for curl. Microsoft’s content delivery network refuses requests whose user agent starts with curl/: a curl -O on the server file hangs without ever answering. This tutorial uses wget, which goes through fine.

3. Configure the firewall

The order matters: allow SSH before enabling the firewall, or you will lock yourself out. The --force flag avoids the y/n prompt that would stall a paste.

Shell
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 19132/tcp comment 'Bedrock NetherNet signalling'
sudo ufw allow 19140:19180/udp comment 'Bedrock NetherNet gameplay'
sudo ufw --force enable
sudo ufw status verbose
Output of sudo ufw status verbose showing the rules for SSH, TCP port 19132 and the UDP range 19140 to 19180
The rules you should see once the firewall is active. Each rule appears twice: once for IPv4, once for IPv6.

Two rules, because NetherNet uses two channels: TCP 19132 carries the initial handshake, and every connected player then gets a UDP port from the range we will set in section 6. Forty ports is plenty for a family server; widen the range — on both sides, here and in server.properties — if you expect a crowd.

If you have already moved your SSH port, replace OpenSSH with <your port>/tcp — and read appendix A, because the method has changed on Ubuntu 26.04.

4. Create the user and the directories

The game server must never run as root. We create a system user with no password and no login shell: nobody can open a session as that user, but the service runs perfectly well.

Shell
sudo useradd --system --create-home --home-dir /opt/minecraft --shell /usr/sbin/nologin minecraft
sudo mkdir -p /opt/minecraft/bedrock /opt/minecraft/backups
sudo chown -R minecraft:minecraft /opt/minecraft
sudo chmod 755 /opt/minecraft
sudo chmod 750 /opt/minecraft/backups

The last two lines deserve a word. useradd creates the home directory in mode 750, which would stop you reading your own configuration files without sudo on every command. So we open it for reading while keeping the backups closed — and the private key from section 8 will stay readable by the minecraft account alone.

5. Download the latest server release

This command asks Mojang for the address of the current release, prints it, then downloads it. No version number to copy by hand, and nothing in this tutorial to update as Minecraft moves on.

Shell
LINK=$(wget -qO- https://net-secondary.web.minecraft-services.net/api/v1.0/download/links | grep -o 'https://[^"]*bin-linux/bedrock-server-[0-9.]*\.zip')
echo "Release found: $LINK"
wget -O /tmp/bedrock-server.zip "$LINK"

Extract, set permissions, and record the installed version for the update script in section 14:

Shell
sudo unzip -o /tmp/bedrock-server.zip -d /opt/minecraft/bedrock
basename "$LINK" .zip | sed 's/bedrock-server-//' | sudo tee /opt/minecraft/bedrock/version.txt
sudo chown -R minecraft:minecraft /opt/minecraft
sudo chmod +x /opt/minecraft/bedrock/bedrock_server
rm -f /tmp/bedrock-server.zip

6. Configure the server

This is the most important section of the tutorial. The server.properties file holds about forty settings; these commands change only the ones that matter, leaving the rest of the file and its comments untouched.

Shell
sudo -u minecraft sed -i \
  -e 's/^server-name=.*/server-name=My Bedrock Server/' \
  -e 's/^gamemode=.*/gamemode=survival/' \
  -e 's/^difficulty=.*/difficulty=normal/' \
  -e 's/^max-players=.*/max-players=10/' \
  -e 's/^level-name=.*/level-name=World/' \
  /opt/minecraft/bedrock/server.properties

What remains is to pin the UDP port range. Without it the server picks at random from the system’s ephemeral ports every time a player connects — and your firewall blocks them. The property is not in the shipped file, so we add it:

Shell
grep -q '^server-udp-ports=' /opt/minecraft/bedrock/server.properties || echo 'server-udp-ports=19140-19180' | sudo -u minecraft tee -a /opt/minecraft/bedrock/server.properties

Check the result:

Shell
grep -E '^(transport|server-name|server-port|server-udp-ports|gamemode|difficulty|max-players|allow-list|level-name)=' /opt/minecraft/bedrock/server.properties

You should read transport=nethernet and server-udp-ports=19140-19180. That range must match exactly the one opened in the firewall in section 3: it is the pair of them that makes the server reachable.

What about the old raknet mode? You can still select it, and it does reopen UDP 19132 the way it used to — but the server then writes this error in its log: “In this release, NetherNet is the only supported transport type. Players will not be able to connect to your game without NetherNet.” The ports open, and nobody gets in. Don’t use it.

The server log shows TRANSPORT TYPE ERROR stating that NetherNet is the only supported transport, even though UDP port 19132 is open
The server set to raknet mode: the UDP port does open, but the log warns that nobody will be able to connect.

A few useful settings, if you want to go further in the same file:

SettingEffectValues
———
server-nameThe name shown in the game’s server listFree text, no semicolons
server-portTCP port of the handshake — this is the one your players type19132 by default
server-udp-portsUDP range for gameplay; must mirror the firewall rule19140-19180
level-nameThe name of the world folder on disk, not the displayed nameFree text
level-seedThe world seed, to reproduce a known terrainEmpty = random
gamemodeDefault game modesurvival, creative, adventure
difficultyDifficultypeaceful, easy, normal, hard
allow-cheatsLets operators use in-game commandstrue, false
view-distanceView distance, in chunks (direct impact on load)32 by default
player-idle-timeoutMinutes before an idle player is kicked30 by default

A change in this file needs a service restart (section 10). Two exceptions can be changed live from the console: difficulty and allow-cheats, with the changesetting command.

7. Allow your players in

The allow-list setting is true from the moment you install: the server turns away anyone who is not in allowlist.json. Replace the two example names with your players’ exact Xbox gamertags — case and spaces matter.

Shell
sudo -u minecraft tee /opt/minecraft/bedrock/allowlist.json >/dev/null <<'JSON'
[
  { "ignoresPlayerLimit": false, "name": "YourGamertag" },
  { "ignoresPlayerLimit": false, "name": "AFriendsGamertag" }
]
JSON

To add someone later, without touching the file or restarting, see section 12.

Would you rather run an open server? Replace the list with sudo -u minecraft sed -i 's/^allow-list=.*/allow-list=false/' /opt/minecraft/bedrock/server.properties. Be aware that bots will find your IP address within hours: we do not recommend it.

8. Create the server identity key

Without this key the server invents a new identity at every start, and your players have to re-accept the server’s trust prompt each time. A permanent key settles it for good. Mojang requires an unencrypted EC P-384 key.

Shell
sudo -u minecraft mkdir -p /opt/minecraft/bedrock/keys
sudo -u minecraft openssl ecparam -name secp384r1 -genkey -noout -out /opt/minecraft/bedrock/keys/server_identity_key.pem
sudo chmod 700 /opt/minecraft/bedrock/keys
sudo chmod 600 /opt/minecraft/bedrock/keys/server_identity_key.pem

This key is a secret: keep it with your backups, and do not share it.

9. Install the systemd service

The service does three things the old manual screen method did not: it starts the server when the machine boots, it restarts it after a crash, and above all it stops it cleanly. That last point is essential: the Bedrock server only saves its world on the stop command. Killing the process without sending it risks losing the last session, or corrupting the world.

That is why there are two ExecStop lines. The first sends stop to the server console; the second waits for it to finish. Without that second line, systemd considers the shutdown complete as soon as the command is sent and kills the server right after, before it has had time to write the world to disk. The -Logfile option keeps everything the server prints in a file you can read at your leisure.

Shell
sudo tee /etc/systemd/system/minecraft-bedrock.service >/dev/null <<'UNIT'
[Unit]
Description=Minecraft Bedrock server
Documentation=https://www.minecraft.net/en-us/download/server/bedrock
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=minecraft
Group=minecraft
WorkingDirectory=/opt/minecraft/bedrock
Environment=LD_LIBRARY_PATH=/opt/minecraft/bedrock
ExecStart=/usr/bin/screen -L -Logfile /opt/minecraft/bedrock/console.log -DmS bedrock /opt/minecraft/bedrock/bedrock_server
ExecStop=/usr/bin/screen -S bedrock -p 0 -X eval "stuff \"stop\\015\""
ExecStop=/bin/sh -c "while pgrep -x bedrock_server >/dev/null; do sleep 1; done"
TimeoutStopSec=120
Restart=on-failure
RestartSec=15
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true
ReadWritePaths=/opt/minecraft

[Install]
WantedBy=multi-user.target
UNIT
sudo systemctl daemon-reload

10. Start it and check

Shell
sudo systemctl enable --now minecraft-bedrock
sleep 20
sudo systemctl status minecraft-bedrock --no-pager

The status must read active (running). The first start creates the world, so it takes a few seconds longer than the ones after it.

Output of systemctl status showing the minecraft-bedrock service active, with screen as the main process and bedrock_server below it
The service running. You can see both processes: screen, which holds the console, and the game server itself.

Now check that the server is really listening where it should:

Shell
sudo ss -ltnp | grep 19132

You should see one LISTEN line on port 19132, held by bedrock_server. If this command returns nothing, the server did not start: see the log in section 15.

Don’t go looking for a UDP port in listening state — there is none as long as nobody is playing. NetherNet only opens a UDP port when a player connects, within the range set in section 6. This is normal, and it is why the firewall rule covers a range rather than a single port.

The ss command shows TCP port 19132 listening and no UDP port, which is normal when idle
A single port listening, and it is TCP. The absence of a UDP port is not a fault.

One last check, to run from another machine than the server — it proves the firewall lets the handshake through. Replace the address with your own:

Shell
curl -s -o /dev/null -w 'HTTP status: %{http_code}\n' http://YOUR-IP-ADDRESS:19132/

A 404 is the right answer: the server replied. A connection error or no answer at all means the port is not reachable — go back to section 3.

A curl request to port 19132 of the server returns HTTP status 404
A 404 means the NetherNet handshake is answering. That is the result you want.

And the address to give your players:

Shell
ip -4 addr show scope global | grep -oP '(?<=inet\s)\d+(\.\d+){3}'

The day-to-day commands:

Shell
sudo systemctl restart minecraft-bedrock   # restart (saves the world first)
sudo systemctl stop minecraft-bedrock      # stop cleanly
sudo systemctl start minecraft-bedrock     # start

11. Connect from Minecraft

In the game: Play → Servers → Add Server.

FieldValue
——
Server nameWhatever you like
Server addressThe IP address from section 10
Port19132

The first player to join has to accept the server’s trust prompt. Thanks to the key from section 8, they will only do it once.

Consoles. Xbox, PlayStation and Switch do not let you add a server by address in the game’s interface. Console players have to go through a third-party DNS redirection service, or join the game of a friend already connected from a computer or a phone.

12. The server console and the everyday commands

Most of the time all you need is to read what the server is saying — joins, leaves, errors. The file is right there, and you don’t even need sudo:

Shell
tail -f /opt/minecraft/bedrock/console.log

Ctrl-C to leave. Note that screen writes this file in bursts: a line can take ten seconds or so to appear. That is not a hang.

Extract of the server log showing version 1.26.52.3, the world name and the Server started line
The three lines to look for in the log after a successful start.

To talk to the server, attach to its console:

Shell
sudo -u minecraft screen -x bedrock

To leave without stopping the server: Ctrl-A then D. Never type stop in the console just to get out — that would shut the server down.

You can also send a command without attaching at all. Replace the text between quotes, keeping the \015 at the end (that is the Enter key):

Shell
sudo -u minecraft screen -S bedrock -p 0 -X eval 'stuff "allowlist add ANewPlayer\015"'
An allowlist list command sent to the server without attaching, and the server's answer in the log
The command goes out without attaching to the console, and the answer lands in the log a few seconds later.

The most useful commands, to type in the console or send this way:

CommandEffect
——
allowlist add <gamertag>Adds a player to the allow list, and writes them to the file
allowlist remove <gamertag>Removes them
allowlist listPrints the active list
allowlist reloadReloads the file after editing it by hand
op <player>Grants operator rights (persistent)
deop <player>Revokes them
kick <player> <reason>Kicks a player, with a message
changesetting difficulty hardChanges the difficulty without restarting
changesetting allow-cheats trueEnables in-game commands
stopStops the server, saving the world

13. Back up automatically

One backup a night, kept for two weeks. The script stops the service for the few seconds it takes to copy the world — which guarantees a consistent copy — then starts it again only if it was running before.

Shell
sudo tee /usr/local/sbin/minecraft-backup >/dev/null <<'SCRIPT'
#!/bin/bash
set -euo pipefail
DEST=/opt/minecraft/backups
SOURCE=/opt/minecraft/bedrock
WAS_RUNNING=no
if systemctl is-active --quiet minecraft-bedrock; then
  WAS_RUNNING=yes
  systemctl stop minecraft-bedrock
fi
mkdir -p "$DEST"
ARCHIVE="$DEST/bedrock-$(date +%Y-%m-%d-%H%M).tar.gz"
tar -czf "$ARCHIVE" -C "$SOURCE" worlds server.properties allowlist.json permissions.json keys
chmod 600 "$ARCHIVE"
if [ "$WAS_RUNNING" = yes ]; then
  systemctl start minecraft-bedrock
fi
find "$DEST" -name 'bedrock-*.tar.gz' -mtime +14 -delete
echo "Backup complete: $ARCHIVE"
SCRIPT
sudo chmod +x /usr/local/sbin/minecraft-backup

The service and the timer that call it every night at 4:30:

Shell
sudo tee /etc/systemd/system/minecraft-backup.service >/dev/null <<'UNIT'
[Unit]
Description=Minecraft Bedrock server backup

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/minecraft-backup
UNIT
sudo tee /etc/systemd/system/minecraft-backup.timer >/dev/null <<'UNIT'
[Unit]
Description=Nightly backup of the Minecraft Bedrock server

[Timer]
OnCalendar=*-*-* 04:30:00
Persistent=true

[Install]
WantedBy=timers.target
UNIT
sudo systemctl daemon-reload
sudo systemctl enable --now minecraft-backup.timer

To test it right away, and to see the next scheduled run:

Shell
sudo /usr/local/sbin/minecraft-backup
systemctl list-timers minecraft-backup --no-pager
The backup script prints the path of the archive it created, then the list of archives present
A backup takes about a second on a fresh world, and the service restarts on its own.

The backup directory is closed to other users, since the archives contain the identity key. To see what you have:

Shell
sudo ls -lh /opt/minecraft/backups/

A backup that stays on the same machine does not protect you from losing the server: copy this directory elsewhere from time to time.

To restore a world:

Shell
sudo systemctl stop minecraft-bedrock
sudo -u minecraft tar -xzf /opt/minecraft/backups/ARCHIVE-NAME.tar.gz -C /opt/minecraft/bedrock
sudo systemctl start minecraft-bedrock

14. Update the Bedrock server

When Minecraft updates, players cannot get in until the server follows. This script compares the installed version with the one Mojang publishes, backs up, updates if needed, and touches neither the world, nor your configuration, nor the allow list.

Shell
sudo tee /usr/local/sbin/minecraft-update >/dev/null <<'SCRIPT'
#!/bin/bash
set -euo pipefail
API=https://net-secondary.web.minecraft-services.net/api/v1.0/download/links
TARGET=/opt/minecraft/bedrock

LINK=$(wget -qO- "$API" | grep -o 'https://[^"]*bin-linux/bedrock-server-[0-9.]*\.zip' || true)
if [ -z "$LINK" ]; then
  echo "Could not obtain the official download link." >&2
  exit 1
fi
LATEST=$(basename "$LINK" .zip | sed 's/bedrock-server-//')
INSTALLED=$(cat "$TARGET/version.txt" 2>/dev/null || echo unknown)
if [ "$LATEST" = "$INSTALLED" ]; then
  echo "Already up to date (version $INSTALLED)."
  exit 0
fi

echo "Updating: $INSTALLED -> $LATEST"
/usr/local/sbin/minecraft-backup
wget -qO /tmp/bedrock-update.zip "$LINK"
systemctl stop minecraft-bedrock
unzip -oq /tmp/bedrock-update.zip -x server.properties allowlist.json permissions.json -d "$TARGET"
echo "$LATEST" > "$TARGET/version.txt"
chown -R minecraft:minecraft "$TARGET"
chmod +x "$TARGET/bedrock_server"
systemctl start minecraft-bedrock
rm -f /tmp/bedrock-update.zip
echo "Server updated to version $LATEST."
SCRIPT
sudo chmod +x /usr/local/sbin/minecraft-update

Run it whenever you like:

Shell
sudo /usr/local/sbin/minecraft-update
The update script reports that the server is already up to date at version 1.26.52.3
Run when nothing has changed, the command leaves everything alone.

We suggest running it by hand, once you have checked that the update doesn’t break anything for your players, rather than automating it.

15. Troubleshooting

SymptomMost likely causeFix
———
“Unable to connect to world”TCP port 19132 is not reachable from outsideThe curl test in section 10, then the firewall rule in section 3
The player connects, then is dropped immediatelyUDP range closed, or different from server-udp-portsThe firewall range (section 3) and the file’s range (section 6) must be identical
The log shows “TRANSPORT TYPE ERROR”transport set to raknetSet it back to nethernet (section 6), then restart the service
`sudo ss -ltnp \grep 19132` returns nothingService stopped or failedsystemctl status, then the log
The player sees the server but is refused entryGamertag missing from the allow list, or misspelledSection 7, then allowlist reload
“You have to accept the server’s trust prompt” at every restartIdentity key missingSection 8
The download hangs with no messageRequest made with curlUse wget, as in section 5
bedrock_server: cannot execute binary fileARM server (aarch64)There is no ARM build; you need an x86-64 machine
The service restarts in a loopCorrupted world, not enough memoryRead the server log: tail -50 /opt/minecraft/bedrock/console.log
The world lost the last session playedProcess killed without the stop commandAlways go through systemctl stop or restart
systemctl stop ends in “FAILURE” instantlyThe second ExecStop line is missing from the serviceSection 9: without it, systemd kills the server before it saves

Two logs not to confuse: systemctl tells you about the service, and console.log about what the game server itself is saying. It is almost always the second one that holds the answer.

Shell
tail -50 /opt/minecraft/bedrock/console.log
sudo systemctl status minecraft-bedrock --no-pager
sudo ufw status verbose

Appendix A — Changing the SSH port on Ubuntu 26.04

Moving SSH to another port cuts the noise from bots enormously. Careful: since Ubuntu 22.10, changing Port in /etc/ssh/sshd_config does nothing at all — the service is socket-activated by systemd, and it is the socket that decides the port. This is the main difference from our Ubuntu 20.04 tutorial.

Keep your current SSH session open throughout, and test the new one before closing the old. Here, port 22222:

Shell
sudo ufw allow 22222/tcp comment 'SSH'
sudo mkdir -p /etc/systemd/system/ssh.socket.d
sudo tee /etc/systemd/system/ssh.socket.d/port.conf >/dev/null <<'CONF'
[Socket]
ListenStream=
ListenStream=22222
CONF
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
sudo ss -ltnp | grep 22222

Open a second terminal and check that the connection works: ssh -p 22222 user@address. Once that is confirmed, close the old port:

Shell
sudo ufw delete allow OpenSSH
sudo ufw status verbose

Appendix B — Understanding the transport change

If you set up a Bedrock server a few years ago, section 3 probably surprised you: where did the famous “UDP 19132” go?

It used to be RakNet. The server listened directly on UDP 19132 (IPv4) and 19133 (IPv6). The client sent a packet to that address, the server answered, and that was that. A single firewall rule was enough, and monitoring tools could query a server to find out whether it was alive.

Today it is NetherNet, built on WebRTC. The server opens a dual-stack TCP socket on server-port and speaks HTTP on it: that is the handshake. Along the way, client and server agree on a separate UDP connection, whose port comes from the server-udp-ports range, and that connection carries the game. Hence the two firewall rules, and hence the fact that no UDP port shows up as listening while the server is idle.

Three practical consequences:

  • server-portv6 no longer does anything under NetherNet — a single dual-stack socket serves IPv4 and IPv6 at once. The property stays in the file, simply ignored.
  • Server lists and monitoring tools that query the old UDP port will not see your server. To check that it is alive, use the curl test from section 10.
  • Mojang recommends a reverse proxy (nginx, HAProxy) in front of the signalling port for an internet-facing server, since it is ordinary HTTP traffic: that lets you apply rate limits. It is not necessary for a family server, but it is worth considering if yours becomes popular.

The raknet mode still exists in server.properties, and it does reopen the old UDP ports. But the server writes an explicit error in its log — in this release, NetherNet is the only supported transport type — and players cannot connect. Don’t count on it.


References

The screenshots in this article come from a real installation on Ubuntu 26.04 LTS, made by following these very steps. The IP address in them is replaced by an address reserved for documentation.


Commentaires

Leave a Reply

Your email address will not be published. Required fields are marked *