--- title: "How to Set Up a Minecraft Java Server on Ubuntu 24.04" description: "Install a Minecraft Java Edition server on Ubuntu 24.04, run it as a systemd service, open the firewall, manage it with RCON and schedule automatic backups." category: "Use Cases" language: en source: https://cubepath.com/docs/use-cases/minecraft-server-configuration-on-linux updated: 2026-09-25 --- # How to Set Up a Minecraft Java Server on Ubuntu 24.04 A dedicated Minecraft Java Edition server gives you and your friends a world that stays online when you log off, with your own rules, whitelist and settings. In this tutorial you will install the official server from Mojang on Ubuntu 24.04, run it under a dedicated user as a systemd service, open its port in the firewall, manage it from the command line with RCON, and schedule automatic world backups. ## Prerequisites To follow this guide you need: - A server running Ubuntu 24.04 LTS, for example a CubePath VPS, with at least 2 vCPUs and 4 GB of RAM. Plan on about 1 GB of server heap per 5-10 active players on a vanilla world, plus 1 GB for the operating system. - A non-root user with `sudo` privileges. - A Minecraft Java Edition account to connect and test. - Optionally, a domain name with an A record pointing to your server's IP address, so players can connect with a name instead of an IP. ## Step 1 - Installing Java and tools The Minecraft server is a Java application, and each Minecraft release requires a minimum Java version. Install `jq` first so you can read that requirement from Mojang's version metadata: ```bash sudo apt update sudo apt install curl jq ``` Mojang publishes a manifest listing every version. Get the latest release and the URL of its metadata: ```bash MC_VERSION=$(curl -fsSL https://piston-meta.mojang.com/mc/game/version_manifest_v2.json | jq -r '.latest.release') MC_META=$(curl -fsSL https://piston-meta.mojang.com/mc/game/version_manifest_v2.json | jq -r --arg v "$MC_VERSION" '.versions[] | select(.id == $v) | .url') echo "$MC_VERSION" curl -fsSL "$MC_META" | jq '.javaVersion.majorVersion' ``` ```output 1.21.9 21 ``` Your version numbers may be newer. The second line is the Java major version you need. Install the matching headless OpenJDK runtime from Ubuntu's repositories, replacing `21` if the output showed a different number: ```bash sudo apt install openjdk-21-jre-headless java -version ``` ```output openjdk version "21.0.8" 2025-07-15 OpenJDK Runtime Environment (build 21.0.8+9-Ubuntu-0ubuntu124.04.1) OpenJDK 64-Bit Server VM (build 21.0.8+9-Ubuntu-0ubuntu124.04.1, mixed mode, sharing) ``` ## Step 2 - Creating a dedicated user Running the server as its own system user keeps it away from your account and the rest of the system if a plugin or exploit ever compromises it. Create a user with its home in `/opt/minecraft` and no login shell: ```bash sudo useradd --system --create-home --home-dir /opt/minecraft --shell /usr/sbin/nologin minecraft sudo mkdir -p /opt/minecraft/server /opt/minecraft/backups sudo chown -R minecraft:minecraft /opt/minecraft ``` ## Step 3 - Downloading the server Read the download URL of the server JAR from the version metadata you found in Step 1 and download it as the `minecraft` user. If you opened a new shell since then, run the two `MC_VERSION` and `MC_META` lines again first: ```bash SERVER_URL=$(curl -fsSL "$MC_META" | jq -r '.downloads.server.url') sudo -u minecraft curl -fsSL -o /opt/minecraft/server/server.jar "$SERVER_URL" sudo ls -lh /opt/minecraft/server/server.jar ``` ```output -rw-r--r-- 1 minecraft minecraft 57M Sep 25 10:12 /opt/minecraft/server/server.jar ``` Run it once to generate the configuration files. It stops immediately because the EULA has not been accepted: ```bash sudo -u minecraft sh -c 'cd /opt/minecraft/server && java -Xmx1G -jar server.jar --nogui' ``` ```output [ServerMain/WARN]: Failed to load eula.txt [ServerMain/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info. ``` Read the Minecraft EULA at `https://aka.ms/MinecraftEULA`. If you agree, accept it: ```bash sudo -u minecraft sed -i 's/^eula=false/eula=true/' /opt/minecraft/server/eula.txt ``` ## Step 4 - Configuring server.properties The main settings live in `/opt/minecraft/server/server.properties`. Open it: ```bash sudo -u minecraft nano /opt/minecraft/server/server.properties ``` Change these keys and leave the rest at their defaults: ```ini motd=My CubePath Minecraft Server max-players=20 difficulty=normal gamemode=survival view-distance=10 simulation-distance=8 online-mode=true white-list=true enforce-whitelist=true enable-rcon=true rcon.port=25575 rcon.password=your_strong_password server-port=25565 ``` What they do: - `online-mode=true` checks every player against Mojang's authentication servers. Keep it on; turning it off lets anyone join with any name. - `white-list` and `enforce-whitelist` only admit players you add, and kick anyone removed from the list. - `view-distance` and `simulation-distance` are the biggest levers on CPU and RAM use. Lower them if the server lags. - `enable-rcon` turns on the remote console you will use to run commands. Replace `your_strong_password` with a long random string, for example from `openssl rand -base64 24`. You will not open port 25575 in the firewall, so RCON stays reachable only from the server itself. Because the file now contains a password, restrict it to the `minecraft` user: ```bash sudo chmod 600 /opt/minecraft/server/server.properties ``` ## Step 5 - Creating the systemd service A systemd unit starts the server at boot, restarts it if it crashes and stops it cleanly on shutdown. Create the unit file: ```bash sudo nano /etc/systemd/system/minecraft.service ``` ```ini [Unit] Description=Minecraft Java Edition server After=network-online.target Wants=network-online.target [Service] User=minecraft Group=minecraft WorkingDirectory=/opt/minecraft/server ExecStart=/usr/bin/java -Xms2G -Xmx2G -jar server.jar --nogui SuccessExitStatus=0 143 Restart=on-failure RestartSec=10 TimeoutStopSec=90 NoNewPrivileges=true ProtectSystem=full ProtectHome=true PrivateTmp=true [Install] WantedBy=multi-user.target ``` `-Xms2G -Xmx2G` gives the server a fixed 2 GB heap; set both to the same value, and leave at least 1 GB of RAM for the operating system. On a 4 GB server, 2-3 GB is right; on 8 GB, use 5-6 GB. When systemd stops the service it sends `SIGTERM`, the server saves the world and exits with status 143, which `SuccessExitStatus` treats as a clean stop. Load the unit and start the server: ```bash sudo systemctl daemon-reload sudo systemctl enable --now minecraft ``` The first start generates the world and takes a minute. Follow the log: ```bash sudo journalctl -u minecraft -f ``` ```output [Server thread/INFO]: Preparing level "world" [Server thread/INFO]: Preparing spawn area: 100% [Server thread/INFO]: Done (18.412s)! For help, type "help" [Server thread/INFO]: Starting remote control listener [RCON Listener #1/INFO]: RCON running on 0.0.0.0:25575 ``` Press `Ctrl+C` to stop following. The `Done` line means the server is ready. ## Step 6 - Opening the firewall Players connect over TCP port 25565. Allow it in UFW, making sure SSH stays allowed before you enable the firewall: ```bash sudo ufw allow OpenSSH sudo ufw allow 25565/tcp sudo ufw enable sudo ufw status ``` ```output Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere 25565/tcp ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) 25565/tcp (v6) ALLOW Anywhere (v6) ``` Port 25575 (RCON) is not listed, so it is blocked from the internet. ## Step 7 - Managing the server with RCON The server runs in the background, so you need RCON to type console commands. Build `mcrcon`, a small command line RCON client: ```bash sudo apt install git build-essential git clone https://github.com/Tiiffi/mcrcon.git cd mcrcon make sudo make install ``` Store the RCON password in an environment variable for the current shell, so it does not end up on the command line of every call: ```bash read -rs MCRCON_PASS && export MCRCON_PASS ``` Type the password and press Enter. Now add yourself to the whitelist and make yourself an operator, replacing `your_player_name` with your Minecraft username: ```bash mcrcon -H 127.0.0.1 -P 25575 "whitelist add your_player_name" "op your_player_name" ``` ```output Added your_player_name to the whitelist Made your_player_name a server operator ``` Run `mcrcon -H 127.0.0.1 -P 25575 -t` for an interactive console, and type `Q` to leave it. Useful commands are `list` (online players), `say `, `whitelist remove ` and `save-all`. Now open Minecraft Java Edition, choose **Multiplayer**, **Add Server**, and enter `your_server_ip` or `your_domain`. The server should appear with your MOTD and you can join. ## Step 8 - Scheduling automatic backups A world copy taken while the server writes to it can be corrupted. The backup script below pauses autosaving, forces a full save, archives the world and turns autosaving back on. It keeps the last 14 archives. Store the RCON password in a file only root can read: ```bash sudo install -m 600 /dev/null /etc/minecraft-rcon.env sudo nano /etc/minecraft-rcon.env ``` ```ini MCRCON_PASS=your_strong_password ``` Create the script: ```bash sudo nano /usr/local/bin/minecraft-backup ``` ```bash #!/usr/bin/env bash set -euo pipefail SERVER_DIR="/opt/minecraft/server" BACKUP_DIR="/opt/minecraft/backups" KEEP=14 RCON=(/usr/local/bin/mcrcon -H 127.0.0.1 -P 25575) restore_autosave() { "${RCON[@]}" "save-on" >/dev/null || true; } trap restore_autosave EXIT "${RCON[@]}" "save-off" "save-all flush" >/dev/null archive="${BACKUP_DIR}/world-$(date +%Y%m%d-%H%M%S).tar.gz" tar -czf "$archive" -C "$SERVER_DIR" world find "$BACKUP_DIR" -maxdepth 1 -name 'world-*.tar.gz' -printf '%T@ %p\n' \ | sort -rn | tail -n +"$((KEEP + 1))" | cut -d' ' -f2- | xargs -r rm -- echo "Backup written to $archive" ``` Make it executable: ```bash sudo chmod 755 /usr/local/bin/minecraft-backup ``` Create a systemd service that runs the script as the `minecraft` user with the password file: ```bash sudo nano /etc/systemd/system/minecraft-backup.service ``` ```ini [Unit] Description=Back up the Minecraft world After=minecraft.service [Service] Type=oneshot User=minecraft EnvironmentFile=/etc/minecraft-rcon.env ExecStart=/usr/local/bin/minecraft-backup ``` And a timer that runs it every day at 04:30: ```bash sudo nano /etc/systemd/system/minecraft-backup.timer ``` ```ini [Unit] Description=Daily Minecraft world backup [Timer] OnCalendar=*-*-* 04:30:00 Persistent=true [Install] WantedBy=timers.target ``` Enable the timer and run one backup now to test it: ```bash sudo systemctl daemon-reload sudo systemctl enable --now minecraft-backup.timer sudo systemctl start minecraft-backup.service sudo journalctl -u minecraft-backup --no-pager -n 5 sudo ls -lh /opt/minecraft/backups ``` ```output Backup written to /opt/minecraft/backups/world-20260925-104512.tar.gz -rw-r--r-- 1 minecraft minecraft 38M Sep 25 10:45 world-20260925-104512.tar.gz ``` Backups on the same disk do not protect against losing the server. Copy `/opt/minecraft/backups` to another location regularly, for example with `rsync` or `rclone` to object storage. To restore, stop the server, move the current `world` directory aside, extract an archive into `/opt/minecraft/server` with `sudo -u minecraft tar -xzf -C /opt/minecraft/server`, and start the server again. ## Step 9 - Updating the server When a new Minecraft version is released, players' clients update automatically and can no longer join an older server. To update, take a backup, stop the server, replace the JAR and start it again: ```bash sudo systemctl start minecraft-backup.service sudo systemctl stop minecraft ``` Repeat the commands from Step 1 to read the new version and its Java requirement (install a newer OpenJDK package if it changed), then download the new JAR as in Step 3 and start the server: ```bash sudo systemctl start minecraft sudo journalctl -u minecraft -f ``` The server converts the world to the new format on first start. That conversion cannot be undone, which is why the backup comes first. ## Troubleshooting **The service fails with `UnsupportedClassVersionError`.** The installed Java is older than the version the server needs. Check `.javaVersion.majorVersion` as in Step 1 and install the matching `openjdk-NN-jre-headless` package. **The server is killed and the journal shows `Out of memory` or `OOM`.** `-Xmx` plus the operating system needs more RAM than the server has. Lower `-Xmx` in the unit file, run `sudo systemctl daemon-reload` and restart. **Players see `Connection timed out`.** Confirm the server is listening with `sudo ss -tlnp | grep 25565` and that UFW allows the port. If you use a domain, check that its A record points to the server. **Players see `You are not white-listed on this server`.** Add them with `whitelist add ` through RCON. The name must match their Java Edition username exactly. **`mcrcon` returns `Connection failed` or `Authentication failed`.** Check that `enable-rcon=true` is set, that the server has finished starting, and that `MCRCON_PASS` matches `rcon.password`. **The server lags with many players.** Lower `view-distance` and `simulation-distance`, and check CPU with `top`. The server's main game loop runs on a single thread, so CPU speed per core matters more than core count. ## Conclusion Your Minecraft Java Edition server now runs as a dedicated user under systemd, starts at boot, admits only whitelisted players, can be managed over RCON from the server itself, and backs up its world every day. From here you can switch to Paper for better performance and plugin support by replacing `server.jar` with a Paper build, pre-generate the world to reduce lag while players explore, and copy your backups to off-site storage.