{"id":24961,"date":"2026-10-14T10:42:15","date_gmt":"2026-10-14T10:42:15","guid":{"rendered":"https:\/\/atalnetworks.com\/?p=24961"},"modified":"2026-10-14T10:45:32","modified_gmt":"2026-10-14T10:45:32","slug":"minecraft-java-server-on-a-linux-vps-setup-guide","status":"publish","type":"post","link":"https:\/\/atalnetworks.com\/fr\/minecraft-java-server-on-a-linux-vps-setup-guide\/","title":{"rendered":"Minecraft Java Server on a Linux VPS: Setup Guide"},"content":{"rendered":"<p><span style=\"font-size: 2em; font-weight: bold;\">Set Up a Minecraft Java Server on a Linux VPS<\/span><\/p>\n<article>To set up a Minecraft Java server on a Linux VPS, install the Java version your server release requires, download the official server JAR, review the EULA, and configure player access. Then create a systemd service, open the game port, and test both a player connection and a backup restore.<\/p>\n<p>We use Ubuntu 24.04 LTS and the official Vanilla server in this guide. The Java 25 commands suit the Minecraft 26.3 setup described here. Use the same Minecraft release on the server and player clients. Check the release notes before applying these commands to another version.<\/p>\n<p>This setup covers Java Edition. For Bedrock or home-PC hosting, start with our Minecraft server setup guide.<\/p>\n<h2>Check Your VPS and Minecraft Requirements<\/h2>\n<p>A VPS gives us control over the operating system, game files, and update schedule. It also makes us responsible for Linux updates, access rules, backups, and recovery.<\/p>\n<p>Before starting, prepare:<\/p>\n<ul>\n<li>A fresh Ubuntu 24.04 LTS VPS with systemd.<\/li>\n<li>An administrator account with SSH and sudo access.<\/li>\n<li>Access to the provider&#8217;s recovery console.<\/li>\n<li>A public IP address, or the provider&#8217;s documented port mapping.<\/li>\n<li>A Minecraft Java Edition account and matching client release.<\/li>\n<li>Storage for the world, working files, and backup copies.<\/li>\n<\/ul>\n<p>For a small private test world, we can start with 4 GB of VPS memory and a 2 GB maximum Java heap. This is a starting configuration, not a player-capacity promise. World activity, CPU performance, view distance, and other processes change the requirements.<\/p>\n<p>Leave memory for Linux and for Java allocations outside the heap. More RAM will not fix a slow or heavily shared CPU.<\/p>\n<h2>Choose One Server Type<\/h2>\n<table>\n<thead>\n<tr>\n<th scope=\"col\">Server software<\/th>\n<th scope=\"col\">Main use<\/th>\n<th scope=\"col\">Scope of this guide<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Vanilla<\/td>\n<td>Official Minecraft behavior<\/td>\n<td>Full setup below<\/td>\n<\/tr>\n<tr>\n<td>Paper<\/td>\n<td>Server plugins and additional administration options<\/td>\n<td>Separate installation and migration checks<\/td>\n<\/tr>\n<tr>\n<td>Fabric or NeoForge<\/td>\n<td>Compatible mods and modpacks<\/td>\n<td>Follow the selected loader and pack requirements<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Paper and mod loaders have their own release requirements. Do not swap server files on an existing world without a backup and compatibility check. Paper&#8217;s setup documentation explains its installation path.<\/p>\n<h2>Keep These Setup Values Consistent<\/h2>\n<table>\n<thead>\n<tr>\n<th scope=\"col\">Item<\/th>\n<th scope=\"col\">Value used here<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Linux service account<\/td>\n<td><code>minecraft<\/code><\/td>\n<\/tr>\n<tr>\n<td>Live server directory<\/td>\n<td><code>\/opt\/minecraft\/server<\/code><\/td>\n<\/tr>\n<tr>\n<td>Server file<\/td>\n<td><code>\/opt\/minecraft\/server\/server.jar<\/code><\/td>\n<\/tr>\n<tr>\n<td>Fixed Java launcher<\/td>\n<td><code>\/opt\/minecraft\/java<\/code><\/td>\n<\/tr>\n<tr>\n<td>Service name<\/td>\n<td><code>minecraft.service<\/code><\/td>\n<\/tr>\n<tr>\n<td>Game port<\/td>\n<td>TCP 25565<\/td>\n<\/tr>\n<tr>\n<td>Starting heap<\/td>\n<td>1G<\/td>\n<\/tr>\n<tr>\n<td>Maximum heap<\/td>\n<td>2G<\/td>\n<\/tr>\n<tr>\n<td>Local backup directory<\/td>\n<td><code>\/var\/backups\/minecraft<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Run Linux commands through your administrator SSH session unless a step says otherwise. Blocks labeled Minecraft console contain game commands, not Linux commands.<\/p>\n<h2>Step 1. Connect to the VPS and Prepare Linux<\/h2>\n<p>On your computer, replace ADMIN_USER and VPS_IP with your details:<\/p>\n<pre><code class=\"language-bash\">ssh ADMIN_USER@VPS_IP<\/code><\/pre>\n<p>If your provider uses a custom SSH port, add <code>-p PORT<\/code> to that command.<\/p>\n<p>On the VPS, check the operating system, architecture, memory, and disk:<\/p>\n<pre><code class=\"language-bash\">cat \/etc\/os-release\r\nuname -m\r\nfree -h\r\ndf -h \/\r\nsudo -v<\/code><\/pre>\n<p>Confirm Ubuntu 24.04 before using this package setup. Then update the fresh host and install the tools we need:<\/p>\n<pre><code class=\"language-bash\">sudo apt update\r\nsudo apt upgrade\r\nsudo apt install curl ca-certificates gpg nano ufw unzip<\/code><\/pre>\n<p>If Linux requests a reboot, restart now and reconnect. Keep the provider console available while changing network rules later.<\/p>\n<h2>Step 2. Install the Required Java Version<\/h2>\n<p>Minecraft and Java have separate version numbers. Installing Java 21 does not make every newer Minecraft server work. Mojang&#8217;s Minecraft 26.1 release notes specify Java 25.<\/p>\n<p>For this Java 25 setup, we use Eclipse Temurin through the official Adoptium package repository. The JDK includes the runtime needed to launch Minecraft.<\/p>\n<p>Download the repository key:<\/p>\n<pre><code class=\"language-bash\">curl -fsSL https:\/\/packages.adoptium.net\/artifactory\/api\/gpg\/key\/public \\\r\n  -o \/tmp\/adoptium-key.asc\r\ngpg --dearmor --output \/tmp\/adoptium-key.gpg \/tmp\/adoptium-key.asc\r\nsudo install -m 0644 \/tmp\/adoptium-key.gpg \/usr\/share\/keyrings\/adoptium.gpg<\/code><\/pre>\n<p>Stop if a command fails. Add the repository for Ubuntu 24.04, whose release name is noble:<\/p>\n<pre><code class=\"language-bash\">echo 'deb [signed-by=\/usr\/share\/keyrings\/adoptium.gpg] https:\/\/packages.adoptium.net\/artifactory\/deb noble main' \\\r\n  | sudo tee \/etc\/apt\/sources.list.d\/adoptium.list\r\nsudo apt update\r\nsudo apt install temurin-25-jdk<\/code><\/pre>\n<p>Find the Java executable installed by that package:<\/p>\n<pre><code class=\"language-bash\">JAVA_BIN=$(dpkg -L temurin-25-jdk | awk '\/\\\/bin\\\/java$\/ {print; exit}')\r\nprintf '%s\\n' \"$JAVA_BIN\"\r\n\"$JAVA_BIN\" -version<\/code><\/pre>\n<p>The output must identify Java 25. If the path is empty or the version differs, stop and check the installation.<\/p>\n<p>Create a fixed launcher path for the game service:<\/p>\n<pre><code class=\"language-bash\">sudo install -d -m 0755 \/opt\/minecraft\r\nsudo ln -s \"$JAVA_BIN\" \/opt\/minecraft\/java\r\n\/opt\/minecraft\/java -version<\/code><\/pre>\n<p>We use this launcher in every later command. It avoids accidentally running Minecraft through another Java version selected as the system default. Check it again after Java package changes.<\/p>\n<h2>Step 3. Create a Separate Minecraft Account<\/h2>\n<p>Run the game under its own Linux account. Keep administrative access in your normal sudo account.<\/p>\n<pre><code class=\"language-bash\">sudo useradd --system --user-group \\\r\n  --home-dir \/opt\/minecraft \\\r\n  --shell \/usr\/sbin\/nologin minecraft\r\nsudo install -d -o minecraft -g minecraft -m 0750 \/opt\/minecraft\/server<\/code><\/pre>\n<p>The minecraft account owns the game directory. It does not need an interactive login shell.<\/p>\n<p>Check ownership:<\/p>\n<pre><code class=\"language-bash\">ls -ld \/opt\/minecraft\/server<\/code><\/pre>\n<p>Both the owner and group should be minecraft. Do not use <code>chmod 777<\/code> to work around permission errors.<\/p>\n<h2>Step 4. Download the Official Server JAR<\/h2>\n<p>Open the official Minecraft Java server download page or the 26.3 release page. Copy the server JAR link for the release you selected.<\/p>\n<p>Replace the placeholder below with that link:<\/p>\n<pre><code class=\"language-bash\">sudo -u minecraft curl -fL \\\r\n  'PASTE_OFFICIAL_SERVER_JAR_URL_HERE' \\\r\n  -o \/opt\/minecraft\/server\/server.jar<\/code><\/pre>\n<p>Check that the download completed and that the archive is readable:<\/p>\n<pre><code class=\"language-bash\">sudo -u minecraft ls -lh \/opt\/minecraft\/server\/server.jar\r\nsudo -u minecraft unzip -t \/opt\/minecraft\/server\/server.jar<\/code><\/pre>\n<p>An archive check can find a broken file, but it does not prove its origin. Use the official HTTPS download and compare its hash with official release metadata when available.<\/p>\n<p>Record the release for future recovery:<\/p>\n<pre><code class=\"language-bash\">printf 'Minecraft Java 26.3\\n' \\\r\n  | sudo -u minecraft tee \/opt\/minecraft\/server\/installed-version.txt<\/code><\/pre>\n<p>Change that text if you selected another release. Keep the download version, client version, and record in agreement.<\/p>\n<h2>Step 5. Review the EULA and Start the Server Once<\/h2>\n<p>For the initial setup, bind Minecraft to the VPS loopback address. This prevents direct remote game connections while we prepare access controls.<\/p>\n<p>On this fresh installation, create the initial settings:<\/p>\n<pre><code class=\"language-bash\">sudo -u minecraft tee \/opt\/minecraft\/server\/server.properties &gt; \/dev\/null &lt;&lt;'EOF'\r\nserver-ip=127.0.0.1\r\nserver-port=25565\r\nonline-mode=true\r\nwhite-list=true\r\nenforce-whitelist=true\r\nenable-rcon=false\r\nEOF<\/code><\/pre>\n<p>Move into the game directory and run the server:<\/p>\n<pre><code class=\"language-bash\">sudo -u minecraft \/bin\/bash -c \\\r\n  'cd \/opt\/minecraft\/server &amp;&amp; exec \/opt\/minecraft\/java -Xms1G -Xmx2G -jar server.jar nogui'<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th scope=\"col\">Option<\/th>\n<th scope=\"col\">Meaning<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>-Xms1G<\/code><\/td>\n<td>Start with a 1 GB Java heap<\/td>\n<\/tr>\n<tr>\n<td><code>-Xmx2G<\/code><\/td>\n<td>Allow the heap to grow to 2 GB<\/td>\n<\/tr>\n<tr>\n<td><code>-jar server.jar<\/code><\/td>\n<td>Run the downloaded server file<\/td>\n<\/tr>\n<tr>\n<td><code>nogui<\/code><\/td>\n<td>Run without the graphical server window<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The first launch normally stops and creates eula.txt. Read the Minecraft EULA. If you agree, edit the file:<\/p>\n<pre><code class=\"language-bash\">sudo -u minecraft nano \/opt\/minecraft\/server\/eula.txt<\/code><\/pre>\n<p>Change <code>eula=false<\/code> to <code>eula=true<\/code>, save, and run the launch command again.<\/p>\n<p>Wait for world preparation to finish and the console to report that startup is complete. Startup time depends on the host and world. Do not treat a fixed number of seconds as a pass condition.<\/p>\n<h3>Add Approved Players<\/h3>\n<p>In the Minecraft console, replace the example names:<\/p>\n<pre aria-label=\"Minecraft console\"><code class=\"language-text\">whitelist add YourJavaName\r\nwhitelist add FriendJavaName\r\nop YourJavaName<\/code><\/pre>\n<p>Grant operator access only to people who need administration rights. A player does not need operator rights simply to join.<\/p>\n<p>Stop the server through the Minecraft console:<\/p>\n<pre aria-label=\"Minecraft console\"><code class=\"language-text\">stop<\/code><\/pre>\n<p>Wait for the world-saving messages and the return of the Linux prompt.<\/p>\n<h2>Step 6. Set Player Access and World Options<\/h2>\n<p>With Minecraft stopped, open the settings file:<\/p>\n<pre><code class=\"language-bash\">sudo -u minecraft nano \/opt\/minecraft\/server\/server.properties<\/code><\/pre>\n<p>Update existing entries rather than adding duplicate keys.<\/p>\n<table>\n<thead>\n<tr>\n<th scope=\"col\">Setting<\/th>\n<th scope=\"col\">Starting value<\/th>\n<th scope=\"col\">Purpose<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>server-ip<\/code><\/td>\n<td>Leave empty<\/td>\n<td>Allow listening on the host&#8217;s available interfaces<\/td>\n<\/tr>\n<tr>\n<td><code>server-port<\/code><\/td>\n<td>25565<\/td>\n<td>Set the game TCP port<\/td>\n<\/tr>\n<tr>\n<td><code>online-mode<\/code><\/td>\n<td>true<\/td>\n<td>Keep account authentication active<\/td>\n<\/tr>\n<tr>\n<td><code>white-list<\/code><\/td>\n<td>true<\/td>\n<td>Restrict access to approved players<\/td>\n<\/tr>\n<tr>\n<td><code>enforce-whitelist<\/code><\/td>\n<td>true<\/td>\n<td>Enforce the approved-player list<\/td>\n<\/tr>\n<tr>\n<td><code>max-players<\/code><\/td>\n<td>10<\/td>\n<td>Set an example admission limit<\/td>\n<\/tr>\n<tr>\n<td><code>gamemode<\/code><\/td>\n<td>survival<\/td>\n<td>Set the default game mode<\/td>\n<\/tr>\n<tr>\n<td><code>difficulty<\/code><\/td>\n<td>normal<\/td>\n<td>Set game difficulty<\/td>\n<\/tr>\n<tr>\n<td><code>level-name<\/code><\/td>\n<td>world<\/td>\n<td>Use the world folder created earlier<\/td>\n<\/tr>\n<tr>\n<td><code>view-distance<\/code><\/td>\n<td>8<\/td>\n<td>Set an initial chunk viewing distance<\/td>\n<\/tr>\n<tr>\n<td><code>simulation-distance<\/code><\/td>\n<td>6<\/td>\n<td>Set an initial simulation distance<\/td>\n<\/tr>\n<tr>\n<td><code>enable-rcon<\/code><\/td>\n<td>false<\/td>\n<td>Keep remote-console access off<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The empty address entry should read <code>server-ip=<\/code>. Do not enter a public address that the VPS does not own on its network interface.<\/p>\n<p>These values are starting choices. A ten-player limit does not promise ten-player performance on every VPS.<\/p>\n<p>Set access rules explicitly. Mojang changed the default white-list value in Minecraft 26.3, so old tutorials may describe different defaults.<\/p>\n<h2>Step 7. Start Minecraft Automatically with systemd<\/h2>\n<p>systemd manages the Minecraft process after SSH closes and can start it when the VPS boots. It also gives us one place to check status and logs.<\/p>\n<p>Create the service file:<\/p>\n<pre><code class=\"language-bash\">sudo nano \/etc\/systemd\/system\/minecraft.service<\/code><\/pre>\n<p>Add:<\/p>\n<pre><code class=\"language-ini\">[Unit]\r\nDescription=Minecraft Java Server\r\nAfter=network-online.target\r\nWants=network-online.target\r\n\r\n[Service]\r\nType=simple\r\nUser=minecraft\r\nGroup=minecraft\r\nWorkingDirectory=\/opt\/minecraft\/server\r\nExecStart=\/opt\/minecraft\/java -Xms1G -Xmx2G -jar server.jar nogui\r\nRestart=on-failure\r\nRestartSec=10\r\nTimeoutStopSec=180\r\nKillSignal=SIGTERM\r\nUMask=0027\r\nNoNewPrivileges=true\r\nPrivateTmp=true\r\n\r\n[Install]\r\nWantedBy=multi-user.target<\/code><\/pre>\n<p>Reload systemd and enable the service:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl daemon-reload\r\nsudo systemctl enable --now minecraft\r\nsudo systemctl status minecraft --no-pager\r\nsudo journalctl -u minecraft -n 60 --no-pager<\/code><\/pre>\n<p><code>active (running)<\/code> shows that the process is running. Also inspect the logs for successful world startup. A process can run before the world is ready.<\/p>\n<p>Use these commands for daily control:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl stop minecraft\r\nsudo systemctl start minecraft\r\nsudo systemctl restart minecraft\r\nsudo journalctl -u minecraft -f<\/code><\/pre>\n<p>Press Ctrl+C to leave the log viewer. That does not stop the service.<\/p>\n<p>journalctl shows output; it is not a Minecraft command console. Once connected, an operator can run approved game commands from in-game chat, with a leading \/.<\/p>\n<p>Check a controlled stop before relying on backups. The service sends SIGTERM and allows up to 180 seconds before forced termination. Confirm world-saving messages and a clean stop in your logs. If the server times out, fix the shutdown problem or allow more time before proceeding.<\/p>\n<h2>Step 8. Open the Firewall and Join the Server<\/h2>\n<p>A public IP does not prove that the game port is reachable. The operating-system firewall and the provider&#8217;s network rules can each block a connection.<\/p>\n<h3>Preserve SSH Access First<\/h3>\n<p>Inspect the existing rules:<\/p>\n<pre><code class=\"language-bash\">sudo ufw status verbose<\/code><\/pre>\n<p>For SSH on the standard TCP port 22, allow:<\/p>\n<pre><code class=\"language-bash\">sudo ufw allow 22\/tcp<\/code><\/pre>\n<p>If SSH uses another port, allow that actual port instead. Keep the current session open and the recovery console available.<\/p>\n<p>Allow the Minecraft port, then enable UFW if it is not already active:<\/p>\n<pre><code class=\"language-bash\">sudo ufw allow 25565\/tcp\r\nsudo ufw enable\r\nsudo ufw status verbose<\/code><\/pre>\n<p>Open a second SSH session to confirm that administrative access still works. Ubuntu&#8217;s firewall documentation explains UFW rule management.<\/p>\n<p>In your provider panel, allow inbound TCP 25565 if a separate cloud firewall applies. Preserve the provider&#8217;s SSH rule as well. A NAT-based VPS also needs the provider&#8217;s assigned external port mapping.<\/p>\n<p>A VPS with a directly assigned public address does not need a port-forwarding rule on your home router.<\/p>\n<h3>Check the Listener and Join<\/h3>\n<p>On the VPS:<\/p>\n<pre><code class=\"language-bash\">sudo ss -ltnp 'sport = :25565'<\/code><\/pre>\n<p>Look for a Java listener on a reachable interface, rather than only 127.0.0.1.<\/p>\n<p>From another computer, use a TCP test if available:<\/p>\n<pre><code class=\"language-bash\">nc -vz VPS_IP 25565<\/code><\/pre>\n<p>On Windows PowerShell, the equivalent check is:<\/p>\n<pre><code class=\"language-powershell\">Test-NetConnection VPS_IP -Port 25565<\/code><\/pre>\n<p>Then open the matching Minecraft Java client:<\/p>\n<ol>\n<li>Select Multiplayer.<\/li>\n<li>Select Add Server.<\/li>\n<li>Enter VPS_IP:25565.<\/li>\n<li>Join with an approved account.<\/li>\n<\/ol>\n<p>Walk through the world and make a small change that you can recognize later. A TCP probe alone cannot confirm player authentication, release compatibility, or world access.<\/p>\n<p>Log out of SSH and confirm the game remains available. Then announce a brief interruption, reboot the VPS, and check that players can rejoin:<\/p>\n<pre><code class=\"language-bash\">sudo reboot<\/code><\/pre>\n<h3>Use a Domain Name<\/h3>\n<p>Create a DNS A record such as play.example.com pointing to the public IPv4 address. With the default game port, players can usually enter that name without a port suffix.<\/p>\n<p>Use DNS-only mode unless your DNS provider offers a specific Minecraft-compatible proxy service. Add an AAAA record only when IPv6 connectivity and firewall rules work end to end.<\/p>\n<p>An SRV record can advertise a custom port. It does not open a firewall or hide the underlying server address.<\/p>\n<h2>Step 9. Back Up the Server and Test Recovery<\/h2>\n<p>For this first server, we use a stopped backup. The job briefly takes the game offline, waits for shutdown, copies the server directory, and starts the service again.<\/p>\n<p>This approach is simpler to inspect than a live backup that depends on remote-console save commands. Schedule it during a quiet period and tell players about the interruption.<\/p>\n<h3>Create the Backup Job<\/h3>\n<p>Create a private backup location:<\/p>\n<pre><code class=\"language-bash\">sudo install -d -o root -g root -m 0700 \/var\/backups\/minecraft\r\nsudo nano \/usr\/local\/sbin\/minecraft-backup<\/code><\/pre>\n<p>Add this script:<\/p>\n<pre><code class=\"language-bash\">#!\/usr\/bin\/env bash\r\nset -euo pipefail\r\numask 077\r\n\r\nexec 9&gt;\/run\/lock\/minecraft-backup.lock\r\nflock -n 9 || exit 1\r\n\r\nwas_running=0\r\nif systemctl is-active --quiet minecraft; then\r\n  was_running=1\r\nfi\r\n\r\nrestart_if_needed() {\r\n  if [ \"$was_running\" -eq 1 ]; then\r\n    systemctl start minecraft\r\n  fi\r\n}\r\ntrap restart_if_needed EXIT\r\n\r\nsystemctl stop minecraft\r\nif systemctl is-active --quiet minecraft; then\r\n  echo 'Backup stopped: Minecraft is still active.' &gt;&amp;2\r\n  exit 1\r\nfi\r\n\r\nresult=$(systemctl show minecraft -p Result --value)\r\nif [ \"$result\" != 'success' ]; then\r\n  echo \"Backup stopped: service result is $result.\" &gt;&amp;2\r\n  exit 1\r\nfi\r\n\r\nstamp=$(date -u +%Y%m%dT%H%M%S%NZ)\r\narchive=\"\/var\/backups\/minecraft\/server-$stamp.tar.gz\"\r\n\r\ntar -czf \"$archive.partial\" -C \/opt\/minecraft server\r\ntar -tzf \"$archive.partial\" &gt;\/dev\/null\r\nmv \"$archive.partial\" \"$archive\"\r\nprintf 'Created %s\\n' \"$archive\"<\/code><\/pre>\n<p>Set permissions and run it once:<\/p>\n<pre><code class=\"language-bash\">sudo chmod 0750 \/usr\/local\/sbin\/minecraft-backup\r\nsudo \/usr\/local\/sbin\/minecraft-backup\r\nsudo systemctl status minecraft --no-pager\r\nsudo ls -lh \/var\/backups\/minecraft<\/code><\/pre>\n<p>The script keeps the JAR, version record, world files, configuration, and player lists in the archive. It does not remove older backups. Check available disk space and remove old copies only after confirming your retention needs and off-server copies.<\/p>\n<p>If the copy fails, inspect the error and any .partial archive. The script attempts to restart a service that was running before the backup, but check the logs and confirm players can reconnect.<\/p>\n<h3>Schedule the Backup<\/h3>\n<p>Create <code>\/etc\/systemd\/system\/minecraft-backup.service<\/code>:<\/p>\n<pre><code class=\"language-ini\">[Unit]\r\nDescription=Back up Minecraft with a short service stop\r\n\r\n[Service]\r\nType=oneshot\r\nExecStart=\/usr\/local\/sbin\/minecraft-backup<\/code><\/pre>\n<p>Create <code>\/etc\/systemd\/system\/minecraft-backup.timer<\/code>:<\/p>\n<pre><code class=\"language-ini\">[Unit]\r\nDescription=Daily Minecraft backup\r\n\r\n[Timer]\r\nOnCalendar=*-*-* 04:00:00\r\nUnit=minecraft-backup.service\r\n\r\n[Install]\r\nWantedBy=timers.target<\/code><\/pre>\n<p>The schedule uses the VPS time zone. Check it with timedatectl, then enable the timer:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl daemon-reload\r\nsudo systemctl enable --now minecraft-backup.timer\r\nsudo systemctl list-timers minecraft-backup.timer<\/code><\/pre>\n<p>Review job results regularly:<\/p>\n<pre><code class=\"language-bash\">sudo journalctl -u minecraft-backup.service -n 50 --no-pager\r\nsudo systemctl --failed<\/code><\/pre>\n<p>This timer runs at the scheduled time when the VPS is online; it does not catch up a missed run at boot. Choose a schedule and monitoring method that meet your recovery needs.<\/p>\n<p>Keep a copy outside the VPS. A local archive does not protect against loss of the VPS disk. Also save the service unit and backup job configuration in your recovery records.<\/p>\n<h3>Restore a Copy Before You Need It<\/h3>\n<p>Choose a completed archive from the backup listing. Replace BACKUP_FILENAME.tar.gz below with its exact name:<\/p>\n<pre><code class=\"language-bash\">sudo install -d -o minecraft -g minecraft -m 0750 \/opt\/minecraft\/restore-test\r\nsudo tar -xzf \/var\/backups\/minecraft\/BACKUP_FILENAME.tar.gz \\\r\n  -C \/opt\/minecraft\/restore-test\r\nsudo chown -R minecraft:minecraft \/opt\/minecraft\/restore-test<\/code><\/pre>\n<p>Use a fresh test directory for each exercise. Edit the restored settings with <code>sudo -u minecraft nano \/opt\/minecraft\/restore-test\/server\/server.properties<\/code> so they use:<\/p>\n<pre><code class=\"language-properties\">server-ip=127.0.0.1\r\nserver-port=25566<\/code><\/pre>\n<p>Keep authentication and the allowlist active. On a small VPS, stop the live server during this test so two Java processes do not exhaust memory:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl stop minecraft-backup.timer\r\nsudo systemctl stop minecraft\r\nsudo -u minecraft \/bin\/bash -c \\\r\n  'cd \/opt\/minecraft\/restore-test\/server &amp;&amp; exec \/opt\/minecraft\/java -Xms1G -Xmx2G -jar server.jar nogui'<\/code><\/pre>\n<p>From a second terminal on your computer, create an SSH tunnel:<\/p>\n<pre><code class=\"language-bash\">ssh -N -L 25566:127.0.0.1:25566 ADMIN_USER@VPS_IP<\/code><\/pre>\n<p>Add your custom SSH port if needed. In Minecraft, join localhost:25566. Confirm the expected world, your player data, and the change made before the backup.<\/p>\n<p>In the restored server&#8217;s Minecraft console, enter stop. Close the tunnel, then start the live service and timer:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl start minecraft\r\nsudo systemctl start minecraft-backup.timer<\/code><\/pre>\n<p>Record the archive name, restored release, result, and recovery time. An archive that opens is useful; a world that you can restore and join provides stronger proof.<\/p>\n<h2>Step 10. Update Minecraft and Roll Back Safely<\/h2>\n<p>Read the new release notes before updating. Check its Java requirement and coordinate the client update with players.<\/p>\n<p>Use this order:<\/p>\n<ol>\n<li>Stop the backup timer and ensure no backup job is running.<\/li>\n<li>Stop Minecraft cleanly.<\/li>\n<li>Run the backup script while Minecraft is stopped. It will leave the service stopped.<\/li>\n<li>Record the completed pre-update archive name.<\/li>\n<li>Test the new release against a separate copy of that backup.<\/li>\n<li>Download the approved new JAR as server.jar.new and check it.<\/li>\n<li>Replace the live JAR while the service remains stopped.<\/li>\n<li>Update the version record and start Minecraft.<\/li>\n<li>Check logs, player access, world state, and saving.<\/li>\n<li>Start the backup timer again.<\/li>\n<\/ol>\n<p>Do not let a scheduled backup race with an update or restore. If a backup job is active, let it finish before changing the live files.<\/p>\n<h3>Restore the Pre-Update State<\/h3>\n<p>If an update fails, stop the service and timer. Preserve the failed state before restoring:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl stop minecraft-backup.timer\r\nsudo systemctl stop minecraft\r\ncd \/opt\/minecraft\r\nsudo mv server \"server-before-rollback-$(date -u +%Y%m%dT%H%M%SZ)\"\r\nsudo tar -xzf \/var\/backups\/minecraft\/PRE_UPDATE_BACKUP.tar.gz -C \/opt\/minecraft\r\nsudo chown -R minecraft:minecraft \/opt\/minecraft\/server<\/code><\/pre>\n<p>Replace PRE_UPDATE_BACKUP.tar.gz with the recorded archive. Confirm that \/opt\/minecraft\/java still points to a runtime supported by the restored release. Restore its previous setting if you changed it during the update.<\/p>\n<p>Then start the service, check the world, and restart the timer:<\/p>\n<pre><code class=\"language-bash\">sudo systemctl start minecraft\r\nsudo journalctl -u minecraft -n 60 --no-pager\r\nsudo systemctl start minecraft-backup.timer<\/code><\/pre>\n<p>Rollback returns the world to the backup time. Players lose changes made after that point. Replacing only the JAR does not reverse changes a newer release made to world data.<\/p>\n<h2>Fix Common Minecraft Linux Server Errors<\/h2>\n<p>Start with the service log:<\/p>\n<pre><code class=\"language-bash\">sudo journalctl -u minecraft -n 100 --no-pager<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th scope=\"col\">Symptom<\/th>\n<th scope=\"col\">First checks<\/th>\n<th scope=\"col\">Next action<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>UnsupportedClassVersionError<\/td>\n<td>Server release and <code>\/opt\/minecraft\/java -version<\/code><\/td>\n<td>Install the required runtime and correct the launcher path<\/td>\n<\/tr>\n<tr>\n<td>EULA message repeats<\/td>\n<td>eula.txt and service working directory<\/td>\n<td>Check agreement status and file location<\/td>\n<\/tr>\n<tr>\n<td>Unable to access JAR<\/td>\n<td>JAR path and permissions<\/td>\n<td>Correct the filename or ownership<\/td>\n<\/tr>\n<tr>\n<td>Invalid or corrupt JAR<\/td>\n<td>Download and archive check<\/td>\n<td>Download again from the official source<\/td>\n<\/tr>\n<tr>\n<td>Service fails at CHDIR<\/td>\n<td>Working directory and parent permissions<\/td>\n<td>Correct directory access<\/td>\n<\/tr>\n<tr>\n<td>Failed to bind to port<\/td>\n<td>Listening processes and configured address<\/td>\n<td>Stop duplicate instances or correct the bind address<\/td>\n<\/tr>\n<tr>\n<td>Connection refused<\/td>\n<td>Process, listening socket, address, and reject rules<\/td>\n<td>Check the listener before changing network rules<\/td>\n<\/tr>\n<tr>\n<td>Connection times out<\/td>\n<td>Provider firewall, UFW, routing, and NAT mapping<\/td>\n<td>Test the network path from another host<\/td>\n<\/tr>\n<tr>\n<td>Player is not allowed<\/td>\n<td>Account name and allowlist<\/td>\n<td>Add the intended account through an operator or console<\/td>\n<\/tr>\n<tr>\n<td>Client\/server version mismatch<\/td>\n<td>Both Minecraft releases<\/td>\n<td>Use matching releases<\/td>\n<\/tr>\n<tr>\n<td>Process disappears or reports Killed<\/td>\n<td>Kernel log and available memory<\/td>\n<td>Check for memory exhaustion before increasing the heap<\/td>\n<\/tr>\n<tr>\n<td>Disk is full<\/td>\n<td>World growth, logs, and backups<\/td>\n<td>Free space without deleting the only recovery copy<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For memory-related shutdowns, inspect:<\/p>\n<pre><code class=\"language-bash\">sudo journalctl -k -n 100 --no-pager\r\nfree -h\r\ndf -h<\/code><\/pre>\n<p>Do not turn off authentication or the entire firewall to make a connection test pass. Fix the failed layer.<\/p>\n<h2>Check Performance Before Buying More Resources<\/h2>\n<p>Minecraft performance problems can come from the network, the server, or the player&#8217;s computer.<\/p>\n<table>\n<thead>\n<tr>\n<th scope=\"col\">Problem<\/th>\n<th scope=\"col\">Typical sign<\/th>\n<th scope=\"col\">Useful check<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Network delay<\/td>\n<td>Delayed actions while server processing remains healthy<\/td>\n<td>Player routes, latency, and packet loss<\/td>\n<\/tr>\n<tr>\n<td>Slow server ticks<\/td>\n<td>World actions fall behind for several players<\/td>\n<td>Tick timing, CPU load, active chunks, and entities<\/td>\n<\/tr>\n<tr>\n<td>Client frame-rate limits<\/td>\n<td>One player sees poor rendering performance<\/td>\n<td>Client settings and local hardware<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Minecraft normally targets 20 ticks per second. That leaves about 50 milliseconds for each tick at that rate. Repeated processing above that budget can make the world fall behind.<\/p>\n<p>Use the profiling tools available in your selected release. Do not copy a Paper-only command into a Vanilla server and assume it exists there.<\/p>\n<p>Check view distance and simulation distance before increasing heap size. Change one setting, repeat the same workload, and compare the result. More memory helps only when memory is part of the limit.<\/p>\n<p>A VPS near the main player group can reduce network delay, but location cannot fix an overloaded CPU. Choose resources and location as separate decisions.<\/p>\n<h2>Minecraft Java Server on Linux VPS FAQs<\/h2>\n<h3>Which Java version does my Minecraft server need?<\/h3>\n<p>Use the requirement for your exact Minecraft release. Minecraft 26.1 moved to Java 25. Older servers and modpacks can need another runtime. Check the release notes before downloading the JAR, and confirm which executable your service runs.<\/p>\n<h3>Does Minecraft keep running after I close SSH?<\/h3>\n<p>Yes, when systemd manages it as shown here. A directly launched process in a normal SSH terminal may stop when the session closes. Also enable the service if you want Minecraft to start after a VPS reboot.<\/p>\n<h3>Do I need port forwarding on a VPS?<\/h3>\n<p>A VPS with a directly assigned public address normally needs firewall rules, not home-router port forwarding. A NAT-based VPS needs its provider&#8217;s port mapping. Check the address and network model included with your plan.<\/p>\n<h3>Why can I reach port 25565 but still not join?<\/h3>\n<p>A reachable TCP port only proves that a service accepts a connection. Check the Minecraft release, Java Edition client, allowlist, account authentication, and server log. A different process can also be listening on the expected port.<\/p>\n<h3>Can I run Minecraft on a VPS with 4 GB of RAM?<\/h3>\n<p>A 4 GB VPS can be a starting point for a small private Vanilla workload. Leave space for Linux and Java memory outside the heap. Test your world and settings before setting a player limit. CPU performance can become the limit first.<\/p>\n<h3>Can Bedrock players join this Java server?<\/h3>\n<p>Not through the standard Vanilla setup shown here. Crossplay needs additional software such as Geyser and a supported deployment method. Check its current client support, authentication requirements, and network ports before offering crossplay.<\/p>\n<h3>Can I move a single-player world to the VPS?<\/h3>\n<p>Yes. Back up both worlds, stop the service, and copy a compatible Java world into the server directory. Set level-name to its folder name and correct ownership. Keep the original copy until you have checked player data, world loading, and saving.<\/p>\n<h3>Can I undo a Minecraft server update?<\/h3>\n<p>You can restore the pre-update world, configuration, and compatible software from a backup. Do not assume a world opened by a newer release can safely run on an older JAR. A rollback also removes changes made after the backup.<\/p>\n<h2>Choose Hosting for Your Minecraft Workload<\/h2>\n<p>A useful Minecraft setup starts with the release, world, players, and location. Choose a plan from those needs, then measure the server under normal play.<\/p>\n<p>Our Linux VPS hosting page provides a starting point for comparing VPS options. For a workload that needs a hardware review, see our dedicated game servers.<\/p>\n<p>Share your expected active players, Minecraft release, mods or plugins, player locations, and budget with our team. We can discuss the infrastructure options against those requirements.<\/p>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>Set Up a Minecraft Java Server on a Linux VPS To set up a Minecraft Java server on a Linux [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":24963,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-24961","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-grade-server"],"acf":[],"_links":{"self":[{"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/posts\/24961","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/comments?post=24961"}],"version-history":[{"count":3,"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/posts\/24961\/revisions"}],"predecessor-version":[{"id":24965,"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/posts\/24961\/revisions\/24965"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/media\/24963"}],"wp:attachment":[{"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/media?parent=24961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/categories?post=24961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/atalnetworks.com\/fr\/wp-json\/wp\/v2\/tags?post=24961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}