Minecraft Field guide

How to run a NeoForge modpack server on Linux

Move a NeoForge modpack to a Linux server: server files, matching Java, dependencies and world verification without unnecessary client-only mods.

How to run a NeoForge modpack server on Linux

Start with the exact release of the modpack your players use. A server that boots with a different NeoForge build or a hand-picked subset of the pack may still reject clients or create a world with missing content. This walkthrough uses Ubuntu 24.04, Minecraft 1.21.1 and a dedicated Linux account; follow the pack author's requirements when they differ.

Pin the pack before downloading server files#

Record four things together: pack name and release, Minecraft version, NeoForge version and Java requirement. For the 1.21.1 example, install a 64-bit Java 21 runtime; the NeoForge Java guide explains the version boundary. “Latest NeoForge” is not a substitute for the build selected by the pack.

Look for the publisher's server pack on the exact release page. A launcher export containing a manifest is not necessarily an archive of downloaded mods. Install it through the author's supported launcher or installer when required. Keep the original download and instructions outside the live server directory.

Use the publisher's distribution permissions. A private server does not give you permission to repackage every mod and distribute the result publicly. Players should install the matching client release through the supported distribution channel.

Prepare an account and an empty directory#

Run these administrative commands on a fresh Ubuntu 24.04 host. They create a separate identity instead of giving mod code root privileges:

bash
sudo apt update
sudo apt install openjdk-21-jre-headless unzip curl
sudo useradd --create-home --home-dir /srv/neoforge --shell /bin/bash neoforge
sudo -iu neoforge
java -version
mkdir -p /srv/neoforge/game
cd /srv/neoforge/game

If the account already exists, inspect its home and ownership rather than recreating it. Confirm that java -version reports Java 21 in this account. A desktop launcher can bundle its own Java; that says nothing about the executable a Linux shell will use.

For a supplied server pack, inspect its archive layout and installation script first, extract it into this empty directory and follow its README. Do not add another independent loader installation over a pack that already manages one. The following manual route is for a pack whose instructions require you to provide NeoForge yourself.

Install the matching loader and preserve its launcher#

Download the exact installer from the official NeoForge server instructions or their linked Maven repository. Place it at /srv/neoforge/neoforge-installer.jar; this deliberately chosen local name must refer to the version you recorded, not an arbitrary renamed JAR.

From the server directory, run:

bash
cd /srv/neoforge/game
java -jar /srv/neoforge/neoforge-installer.jar --installServer
ls -l run.sh user_jvm_args.txt libraries

Keep the generated libraries tree and run.sh together. Starting a random JAR with java -jar bypasses the generated classpath and arguments. The working directory also matters: relative configuration and world paths belong to /srv/neoforge/game.

Install the pack's server-side files according to its instructions. These may include mods, config, defaultconfigs, scripts and datapacks. Copying only mod JARs can lose recipes or generation settings; copying the entire client instance can introduce graphics-only dependencies. Check each questionable mod's supported environment on its project page. A real NeoForge support thread illustrates why “works in singleplayer” does not establish dedicated-server compatibility.

Set memory and make the first start#

Edit user_jvm_args.txt, preserving pack-specific options. For a small example on a host with 8 GB RAM, these heap settings leave room for the OS and JVM overhead:

text
-Xms2G
-Xmx4G

They are a starting budget, not a promise that any pack fits. Use the pack's requirements and observed memory pressure before increasing the limit. Avoid duplicate heap flags elsewhere in a pack's launcher.

Run the generated launcher from the same directory:

bash
cd /srv/neoforge/game
bash ./run.sh nogui

The first start may stop at the EULA. Read the linked agreement in eula.txt; change its value to true only if you accept it, then launch again. Keep this first run in the foreground so you can see installer failures and use the console.

If it exits, read the first relevant error in logs/latest.log and any crash report. A missing mod dependency, wrong Minecraft target and client-only class failure need different fixes. Preserve the original log before replacing files; do not remove half the pack from an established world to make it start.

Keep the runtime and content as one versioned set; a successful loader start is only an intermediate check.

Admit players and verify the actual world#

After a clean start, stop with stop in the game console and edit the generated server.properties. Keep online-mode=true, leave server-ip empty for the ordinary host setup, choose the intended level-name, and enable white-list=true for a private group. Restart and add authorized player names using whitelist add PlayerName in the console.

For the default game port, inspect the listener in a second administrative terminal:

bash
sudo ss -lntp 'sport = :25565'

Check that its process belongs to this Java server. If using UFW, allow the selected TCP port; also check a VPS security group or forward that TCP port to the host's stable LAN address. A rule for UDP alone will not expose this Java server. For home connections, check CGNAT before repeating port forwarding.

Join using the exact client pack, visit a modded feature and check the console for a successful player entry. Then change something recognizable, disconnect, issue stop, restart and join again. Confirm that the same world and change persist. Only after that should you move the reviewed launch command into a service with this user and working directory.

Keep a rollback set before updating#

Stop cleanly and wait for the Java process to exit. From the same neoforge shell, archive the complete installation into a separate backup directory:

bash
umask 077
mkdir -p /srv/neoforge/backups
chmod 700 /srv/neoforge/backups
backup_file="/srv/neoforge/backups/game-$(date -u +%Y%m%dT%H%M%SZ).tgz"
tar -C /srv/neoforge -czf "$backup_file" game
tar -tzf "$backup_file" >/dev/null
sha256sum "$backup_file" > "$backup_file.sha256"

Keep the client pack release, loader installer and Java version beside the backup record. Test updates on a separate copy with separate ports before opening access. Restoring only old JARs over a world already changed by newer mods is not a reliable rollback; retain the matching stopped world and configuration as well.

Store a protected copy off the host. Listing an archive and recording its checksum help detect damage; verify a restore separately before relying on that copy.