TL;DR:
- Install Java, run the Fabric launcher or NeoForge installer as an unprivileged user, add mods or a server pack, and run it under systemd on TCP port 25565.
- On October 6, 2026, Minecraft 26.2 was the newest release with stable builds of both loaders: Fabric Loader 0.19.5 and NeoForge 26.2.0.88.
- Minecraft 26.1 and newer need Java 25; packs for 1.20.5 to 1.21.11 need Java 21.
- NeoForge's default settings file calls a 4 GB heap a good default for a modded server. All the Mods 10, with about 500 mods, sets an 8 GB maximum.
- Players need the same Minecraft version, loader and mods as the server, except mods that run on one side only.
Applies to: Ubuntu 24.04 LTS · Minecraft: Java Edition 26.2 · Fabric Loader 0.19.5 · NeoForge 26.2.0.88 · Java 25 (Temurin 25.0.4.1) · checked October 2026
A modded Minecraft server is a Minecraft: Java Edition server that runs a mod loader, such as Fabric or NeoForge, so it can load mods that add blocks, creatures, mechanics and world generation. This tutorial shows how to host a modded Minecraft server on Ubuntu 24.04 LTS with either loader, add mods or a CurseForge or Modrinth server pack, run it under systemd and back it up before mod updates. The Paper tutorial covers the Java repository and plugin servers.
Fabric or NeoForge: choose a mod loader
A mod loads only on the loader and Minecraft versions it was built for. Mod pages on Modrinth and CurseForge list both, and a modpack fixes them: install the loader and version the pack names.
| Fabric | NeoForge | |
|---|---|---|
| Server install | Server launcher JAR; downloads Mojang's server on first start | Installer JAR with --installServer; writes run.sh and user_jvm_args.txt |
| Memory flags | On the java command line | In user_jvm_args.txt |
| Minecraft 26.3 on October 6, 2026 | Stable builds | Beta builds only |
Most Fabric mods also need Fabric API. NeoForge refuses Fabric mods at startup with is a Fabric mod and cannot be loaded and rejects Paper plugins too; for plugins, use Paper.
Which Java version does a modded server need?
Each Minecraft release declares its minimum Java version in Mojang's version files, and a modded server needs the same Java.
| Minecraft version | Minimum Java | Temurin package |
|---|---|---|
| 1.18 to 1.20.4 | Java 17 | temurin-17-jre |
| 1.20.5 to 1.21.11 | Java 21 | temurin-21-jre |
| 26.1 and newer | Java 25 | temurin-25-jre |
All the Mods 10, a large pack, runs on Minecraft 1.21.1 with NeoForge 21.1.251, and its start script stops with Minecraft 1.21 requires Java 21 when Java is missing. Several Temurin versions can sit side by side under /usr/lib/jvm.
How much RAM does a modded Minecraft server need?
Take the heap from the loader's defaults or the pack's own files. Paper's documentation advises leaving 1,000 to 1,500 MB for the operating system and setting -Xms equal to -Xmx.
| Setup | Heap (-Xmx) | Source of the figure | VPS RAM |
|---|---|---|---|
| Fabric launcher example | 2 GB | Example command on Fabric's server download page | 4 GB |
| NeoForge with a mod list | 4 GB | NeoForge's generated user_jvm_args.txt | 6 to 8 GB |
| All the Mods 10 (about 500 mods) | 8 GB | -Xms4G -Xmx8G in the pack's server files | 10 to 12 GB |
A 1 GB or 2 GB VPS cannot hold a large pack's heap. The Minecraft Wiki recommends good single-core performance: core world mechanics tick on one main thread, and each tick has 50 ms to hold 20 ticks per second. The Ryzen VPS hosting guide covers clock speed for game servers.
Prerequisites
- A VPS running Ubuntu 24.04 LTS with root SSH access and the RAM from the table above. On Arct Cloud, 4 GB RAM comes with
cvm.micro,vm.microandhvm.micro(2 vCPU), 8 GB withcvm.small,vm.tinyandhvm.tiny(4 vCPU), and 12 GB withcvm.large,vm.smalland the High Performancehvm.small(6 vCPU); sustained full-CPU load is not permitted, so run heavy jobs such as chunk pre-generation on demand. - A non-root user with sudo privileges who signs in with an SSH key. Generate an SSH key, add it at deploy, then log in as root and run
adduser deploy,usermod -aG sudo deployandrsync --archive --chown=deploy:deploy ~/.ssh /home/deploy. - The Adoptium apt repository, added with Step 3 of How to Make a Minecraft Server on Ubuntu 24.04.
- Minecraft: Java Edition for each player.
Commands run as the sudo user. Replace values in capitals, such as YOUR_EMAIL, with your own.
Step 1: Install Java and the download tools
Install Java 25 and the tools the scripts use. For a pack on Minecraft 1.20.5 to 1.21.11, add temurin-21-jre:
sudo apt update
sudo apt install -y temurin-25-jre curl jq unzip ufw
ls /usr/lib/jvm
The list includes temurin-25-jre-amd64. Later commands call Java by its full path.
Step 2: Create the minecraft service user
Create an unprivileged system user with its home in /opt/minecraft, and the server folder:
sudo useradd --system --create-home --home-dir /opt/minecraft --shell /usr/sbin/nologin minecraft
sudo -u minecraft mkdir /opt/minecraft/modded
If you followed the Paper tutorial, skip the first line and stop Paper, which also uses port 25565: sudo systemctl disable --now minecraft. Mods run with the server's permissions, so this user owns only its own folder.
Step 3: Choose the Minecraft and loader versions
The server, loader, mods and players must share one Minecraft version. For your own mod list, look up the newest stable loader builds:
curl -fsS https://meta.fabricmc.net/v2/versions/loader | jq -r 'first(.[] | select(.stable)).version'
curl -fsS https://meta.fabricmc.net/v2/versions/installer | jq -r 'first(.[] | select(.stable)).version'
curl -fsS "https://maven.neoforged.net/api/maven/latest/version/releases/net/neoforged/neoforge?filter=26.2" | jq -r .version
On October 6, 2026, the output was:
0.19.5
1.1.2
26.2.0.88
A NeoForge version ending in -beta is a beta build. The API returns it when a Minecraft version has no stable NeoForge build yet. NeoForge versions start with the Minecraft version: 26.2.0.88 is for Minecraft 26.2, and 21.1.251 for 1.21.1. Set the variables, and set them again after each new login:
MC_VERSION="26.2"
FABRIC_LOADER="0.19.5"
FABRIC_INSTALLER="1.1.2"
NEOFORGE_VERSION="26.2.0.88"
JAVA=/usr/lib/jvm/temurin-25-jre-amd64/bin/java
For a server pack, use the pack's versions. Download it on your PC (CurseForge server files sit under additional files on the pack's Files tab; a Modrinth .mrpack is on the Versions tab) and copy it to /tmp on the server, as in How to Copy Files to a VPS with rsync and scp. Read a Modrinth pack's versions:
unzip -p /tmp/YOUR_PACK.mrpack modrinth.index.json | jq .dependencies
The output looks similar to this:
{
"minecraft": "26.2",
"fabric-loader": "0.19.3"
}
For CurseForge server files, check the pack page and the start script. All the Mods 10's startserver.sh sets NEOFORGE_VERSION=21.1.251 and requires Java 21, so set MC_VERSION="1.21.1", NEOFORGE_VERSION="21.1.251" and JAVA=/usr/lib/jvm/temurin-21-jre-amd64/bin/java.
Step 4: Install Fabric or NeoForge
Run one of the two options.
Option A: Fabric server JAR
Fabric's server JAR is a launcher that starts a Minecraft Fabric server for the versions in its URL, with no separate install step:
sudo -u minecraft curl -fsSL -o /opt/minecraft/modded/fabric-server-launch.jar \
"https://meta.fabricmc.net/v2/versions/loader/${MC_VERSION}/${FABRIC_LOADER}/${FABRIC_INSTALLER}/server/jar"
On first start, it downloads Mojang's server JAR to .fabric/server/ and checks its SHA-1 checksum against Mojang's metadata.
Option B: NeoForge installer
Download the installer, check it against NeoForge's published SHA-256 file, and install the server:
NEOFORGE_URL="https://maven.neoforged.net/releases/net/neoforged/neoforge/${NEOFORGE_VERSION}/neoforge-${NEOFORGE_VERSION}-installer.jar"
sudo -u minecraft curl -fsSL -o /opt/minecraft/neoforge-installer.jar "$NEOFORGE_URL"
echo "$(curl -fsSL "${NEOFORGE_URL}.sha256") /opt/minecraft/neoforge-installer.jar" | sudo sha256sum -c
sudo -u minecraft bash -c "cd /opt/minecraft/modded && $JAVA -jar /opt/minecraft/neoforge-installer.jar --installServer"
The checksum line prints OK, and the installer prints The server installed successfully.
Step 5: Add mods or a server pack
Download mods only from Modrinth, CurseForge or the mod author. Fabric's documentation warns that many other mod sites are malware sites.
Option A: Add mods from Modrinth
Modrinth's API returns each file's SHA-512 hash. Create /usr/local/bin/modrinth-get, which downloads a project's newest release for a Minecraft version and loader into a folder and verifies it:
sudo tee /usr/local/bin/modrinth-get > /dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
UA="modded-server-setup/1.0 (YOUR_EMAIL)"
LINE=$(curl -fsS -G -H "User-Agent: $UA" \
"https://api.modrinth.com/v2/project/$1/version" \
--data-urlencode "game_versions=[\"$2\"]" \
--data-urlencode "loaders=[\"$3\"]" \
| jq -r 'first(.[] | select(.version_type == "release")) | .files
| (map(select(.primary)) + .)[0] | [.hashes.sha512, .filename, .url] | @tsv')
[ -n "$LINE" ] || { echo "No release of $1 for $2 on $3" >&2; exit 1; }
IFS=$'\t' read -r SHA512 FILE URL <<< "$LINE"
curl -fsSL -H "User-Agent: $UA" -o "$4/$FILE" "$URL"
echo "$SHA512 $4/$FILE" | sha512sum -c
EOF
sudo chmod 755 /usr/local/bin/modrinth-get
Modrinth requires an identifying User-Agent, so replace YOUR_EMAIL. On Fabric, install Fabric API, then each mod by the name in its Modrinth URL:
sudo -u minecraft mkdir -p /opt/minecraft/modded/mods
sudo -u minecraft modrinth-get fabric-api "$MC_VERSION" fabric /opt/minecraft/modded/mods
sudo -u minecraft modrinth-get lithium "$MC_VERSION" fabric /opt/minecraft/modded/mods
The output looks similar to this:
/opt/minecraft/modded/mods/fabric-api-0.161.0+26.2.jar: OK
/opt/minecraft/modded/mods/lithium-fabric-0.25.3+mc26.2.jar: OK
On NeoForge, pass neoforge as the loader. The script skips dependencies, which each mod page lists. Leave mods that Modrinth marks client-only off the server.
Option B: Install CurseForge server files
CurseForge's API needs a developer key, so download server files in a browser. Unzip them after the loader install, so the pack's user_jvm_args.txt and configs replace the defaults:
sudo -u minecraft unzip -o -q /tmp/YOUR_SERVER_FILES.zip -d /opt/minecraft/modded
sudo ls /opt/minecraft/modded
Replace YOUR_SERVER_FILES with the archive name, such as ServerFiles-8.2 for All the Mods 10. If an archive holds one top-level folder, move its contents up. Step 8's service replaces the pack's start script, so copy any settings it writes. All the Mods 10's script sets these server.properties values:
printf '%s\n' allow-flight=true max-tick-time=180000 view-distance=8 simulation-distance=5 \
| sudo -u minecraft tee /opt/minecraft/modded/server.properties
Option C: Install a Modrinth modpack
A .mrpack lists every mod with its URL, hashes and whether the server needs it, plus overrides folders. Create /usr/local/bin/mrpack-server-install, which takes the pack file and the server folder:
sudo tee /usr/local/bin/mrpack-server-install > /dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
PACK=$(realpath "$1"); DEST=$(realpath "$2")
WORK=$(mktemp -d); trap 'rm -rf "$WORK"' EXIT
unzip -q "$PACK" -d "$WORK"
jq -r '.files[] | select(.env.server != "unsupported")
| [.path, .hashes.sha512, .downloads[0]] | @tsv' "$WORK/modrinth.index.json" |
while IFS=$'\t' read -r FILE SHA512 URL; do
case "$FILE" in /*|*..*) echo "Unsafe path: $FILE" >&2; exit 1 ;; esac
case "$URL" in
https://cdn.modrinth.com/*|https://github.com/*|https://raw.githubusercontent.com/*|https://gitlab.com/*) ;;
*) echo "Unexpected download host: $URL" >&2; exit 1 ;;
esac
mkdir -p "$DEST/$(dirname "$FILE")"
curl -fsSL -o "$DEST/$FILE" "$URL"
echo "$SHA512 $DEST/$FILE" | sha512sum -c --quiet
done
for DIR in overrides server-overrides; do
if [ -d "$WORK/$DIR" ]; then cp -r "$WORK/$DIR/." "$DEST/"; fi
done
echo "Installed $(jq -r '.name + " " + .versionId' "$WORK/modrinth.index.json")"
EOF
sudo chmod 755 /usr/local/bin/mrpack-server-install
sudo -u minecraft mrpack-server-install /tmp/YOUR_PACK.mrpack /opt/minecraft/modded
The script skips files marked unsupported on the server, checks every SHA-512 hash, refuses paths outside the folder and allows only Modrinth's permitted download hosts.
Step 6: Set the memory flags
Pick the heap from the RAM table. On NeoForge, write it to user_jvm_args.txt, which run.sh reads:
printf '%s\n' '-Xms4G' '-Xmx4G' | sudo -u minecraft tee /opt/minecraft/modded/user_jvm_args.txt
Skip this for a pack whose user_jvm_args.txt already sets -Xmx. On Fabric, the flags go on the Java command in Steps 7 and 8.
Step 7: Accept the EULA and start the server once
Read the Minecraft EULA, then record that you accept it. Its mods section allows Java Edition owners to add mods and forbids distributing modded versions of the game or server software. This folder contains Mojang's server JAR, so do not share it; point players to the mod or pack pages on Modrinth or CurseForge.
echo "eula=true" | sudo -u minecraft tee /opt/minecraft/modded/eula.txt
Start the server in the foreground to create the world and configs. On Fabric, change both 4G values to the heap from the RAM table:
sudo -u minecraft bash -c "cd /opt/minecraft/modded && $JAVA -Xms4G -Xmx4G -jar fabric-server-launch.jar nogui"
On NeoForge:
sudo -u minecraft bash -c "cd /opt/minecraft/modded && PATH=$(dirname $JAVA):\$PATH ./run.sh nogui"
Fabric logs Loading N mods with the list. When a line starting Done ( appears, turn on the whitelist, add your account, make it an operator and stop:
whitelist on
whitelist add YOUR_PLAYER
op YOUR_PLAYER
stop
Step 8: Run the server as a systemd service
Create /etc/systemd/system/minecraft-modded.service with sudo nano. This is the Fabric version; change both 4G values to your heap:
[Unit]
Description=Modded Minecraft server
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=600
StartLimitBurst=3
[Service]
User=minecraft
Group=minecraft
WorkingDirectory=/opt/minecraft/modded
ExecStart=/usr/lib/jvm/temurin-25-jre-amd64/bin/java -Xms4G -Xmx4G -jar fabric-server-launch.jar nogui
SuccessExitStatus=0 143
Restart=on-failure
RestartSec=10
TimeoutStopSec=180
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.target
For NeoForge, replace the ExecStart line with these two lines, so run.sh finds the right Java:
Environment=PATH=/usr/lib/jvm/temurin-25-jre-amd64/bin:/usr/bin:/bin
ExecStart=/opt/minecraft/modded/run.sh nogui
For a Java 21 pack, use temurin-21-jre-amd64. StartLimitBurst=3 stops restarts after three failures in 10 minutes, so a broken mod does not reload in a loop. After fixing the mod, run sudo systemctl reset-failed minecraft-modded before sudo systemctl start minecraft-modded. Save with Ctrl+O, exit with Ctrl+X and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now minecraft-modded
sudo journalctl -u minecraft-modded -f
Press Ctrl+C once the Done ( line appears.
Step 9: Open TCP port 25565 in UFW
Allow SSH before you enable UFW, then open the Minecraft port:
sudo ufw allow OpenSSH
sudo ufw allow 25565/tcp
sudo ufw enable
sudo ufw status
Type y to confirm. The list shows OpenSSH and 25565/tcp as ALLOW. If your provider runs a network firewall in front of the server, open TCP 25565 there too.
Step 10: Install the same mods on each PC and verify
Each player installs the server's loader and Minecraft version, then the same mods:
- Fabric: run the Fabric installer for the server's Minecraft version and put the same mod JARs, including Fabric API, in the
modsfolder. - NeoForge: run the same installer JAR with Install client selected, per NeoForge's client guide, then add the mods.
- Server pack: install the same pack version in the CurseForge app or the Modrinth App.
Confirm the server listens:
sudo ss -tlnp | grep 25565
The output shows a LISTEN socket owned by java. In Minecraft, open Multiplayer, select Add Server, enter the server's IP address, such as 203.0.113.10, and join.
Pre-generate chunks with a small radius (optional)
Chunky is a Fabric and NeoForge mod that generates terrain before players explore it. Its FAQ says it runs as fast as possible by default and that modern Minecraft uses many threads for world generation. Run it once with a small radius before players join, or skip it.
sudo -u minecraft modrinth-get chunky "$MC_VERSION" fabric /opt/minecraft/modded/mods
sudo systemctl restart minecraft-modded
On NeoForge, use neoforge. In game, as an operator, set a 500-block radius (centered on 0, 0 by default) and start:
/chunky radius 500
/chunky start
/chunky pause saves progress and stops, /chunky continue resumes, and /chunky cancel deletes the task. Remove Chunky afterwards.
Back up the server before mod updates
NeoForge's documentation says to back up the world before updating NeoForge or mods. This script stops the server, archives the folder except logs, starts it again and keeps 7 days of archives:
sudo tee /usr/local/bin/minecraft-modded-backup > /dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
BACKUP_DIR=/var/backups/minecraft-modded
mkdir -p "$BACKUP_DIR"
if systemctl is-active --quiet minecraft-modded; then
trap 'systemctl start minecraft-modded' EXIT
systemctl stop minecraft-modded
fi
tar -czf "$BACKUP_DIR/modded-$(date +%F-%H%M).tar.gz" \
--exclude=./logs --exclude=./crash-reports \
-C /opt/minecraft/modded .
find "$BACKUP_DIR" -name 'modded-*.tar.gz' -mtime +6 -delete
EOF
sudo chmod 755 /usr/local/bin/minecraft-modded-backup
sudo minecraft-modded-backup
The archive holds the world, mods, configs and loader files. To restore, stop the server, move the folder aside and extract an archive:
sudo systemctl stop minecraft-modded
sudo mv /opt/minecraft/modded /opt/minecraft/modded.old-$(date +%F-%H%M)
sudo install -d -o minecraft -g minecraft /opt/minecraft/modded
sudo tar -xzf /var/backups/minecraft-modded/modded-YYYY-MM-DD-HHMM.tar.gz -C /opt/minecraft/modded
sudo systemctl start minecraft-modded
The archives share the server's disk, so copy them to another machine with rsync or scp. For platform backups, see VPS backup options.
Update mods, the loader and Minecraft
Stop the server, back up, then change files:
sudo systemctl stop minecraft-modded
sudo minecraft-modded-backup
sudo -u minecraft bash -c 'rm -f /opt/minecraft/modded/mods/fabric-api-*.jar'
sudo -u minecraft modrinth-get fabric-api "$MC_VERSION" fabric /opt/minecraft/modded/mods
sudo systemctl start minecraft-modded
- Fabric Loader: download the launcher again over
fabric-server-launch.jarwith the newFABRIC_LOADER. - NeoForge: run the newer installer with
--installServerin the same folder. It rewritesrun.shand keeps youruser_jvm_args.txt. - Packs: install the new version and its loader into an empty folder, then copy
world,server.properties,eula.txt,whitelist.jsonandops.jsonacross. - Minecraft: wait until every mod has a build for the new version, then update players at the same time.
Troubleshoot common modded server errors
| Symptom | Cause | Fix |
|---|---|---|
UnsupportedClassVersionError with class file version 69.0 (NeoForge), or requires version 25 or later of ... (java) (Fabric) | Java older than 25 runs a 26.x server | Point ExecStart or PATH at Temurin 25 |
Incompatible mods found! and requires any version of fabric-api, which is missing! | Fabric API missing | modrinth-get fabric-api |
but only the wrong version is present | A mod built for another Minecraft version (if the line names (java), see the first row) | Get the build for MC_VERSION |
is a Fabric mod and cannot be loaded | Fabric mod on NeoForge | Use the NeoForge build |
Currently, ... is not installed | Missing NeoForge dependency | Install the named mod |
Crash report names a class under net/minecraft/client | Client-only mod on the server | Remove it from the server |
This channel is missing on the client side, but required on the server! | Player lacks a mod | Install the same mods |
java.lang.OutOfMemoryError: Java heap space | Heap too small | Raise -Xms and -Xmx |
FAQ
How much RAM do I need for a modded Minecraft server?
Plan for 6 to 8 GB of RAM for a NeoForge server with a mod list and 10 to 12 GB for a pack the size of All the Mods 10. NeoForge's default settings file calls a 4 GB heap a good default, and All the Mods 10 sets an 8 GB maximum.
Is Fabric allowed on servers?
Yes. Fabric publishes a server launcher, and its documentation says most mods also need Fabric API. Each mod declares whether it loads on the client, the server or both, so client-only mods stay on players' PCs.
Can you make a server with CurseForge?
Yes. Modpack authors can upload a server pack as an additional file on the pack's Files tab. Download the version that matches your players' pack, unzip it on the server and install the loader version the pack names.
How to install NeoForge on Linux?
Download the installer JAR from maven.neoforged.net, run it with java -jar and --installServer in the server folder, then start the server with ./run.sh. NeoForge 26.x needs Java 25, and NeoForge 21.1 for Minecraft 1.21.1 needs Java 21.
Where is the NeoForge server jar?
NeoForge has no single server JAR to run by default. The installer writes run.sh, user_jvm_args.txt and a libraries folder, and run.sh starts the server. The installer can also create an optional server starter JAR.
Is hosting a modded Minecraft server free?
The software is. Fabric (Apache 2.0) and NeoForge (LGPL 2.1) are open source, and Mojang's server software is a free download. Each player needs their own copy of Minecraft: Java Edition.
Do players need the same mods to join a modded server?
Yes, for mods that add content: players need the server's Minecraft version, loader and mod versions. Client-only mods stay on the PC.
Next steps
- How to Make a Minecraft Server on Ubuntu 24.04 (Paper, Java 25) for plugin servers and a daily backup timer.
- Installing a NeoForge Server
- Fabric's server download page
High Performance plans run on AMD Ryzen 9 up to 5.7 GHz or AMD EPYC Genoa 9004 Series up to 4.3 GHz, with DDR5 RAM. Compare plans.
This work is licensed under CC BY-NC-SA 4.0.