Minecraft Field guide

Set up a Minecraft Fabric server on Ubuntu

Run a Minecraft Fabric server on Linux: match Minecraft, Java and Loader, install server-compatible mods and verify the first join.

Set up a Minecraft Fabric server on Ubuntu

Start Fabric without optional mods, verify a private connection, then add the server-compatible mod set. This makes a broken dependency easier to identify than starting with an entire client profile copied into the server.

The example uses a fresh Ubuntu 24.04 host, Minecraft Java Edition 1.21.1, Java 21, sudo access and an x86-64 machine. This deliberately pinned version suits an existing 1.21.1 modpack; it is not the latest Minecraft release. For 26.1 and newer, select Java 25 and compatible mods instead: Mojang changed the Java requirement in 26.1. Do not run these Java 21 commands unchanged for that branch.

Pin the game, loader and Java version#

Write down the Minecraft version, Fabric Loader version and launcher/installer version selected on the official server download page. Match the modpack's requirements rather than choosing every component independently by its newest date.

The versioned Fabric Java guide confirms Java 21 for this Minecraft branch. Install the example runtime and create a dedicated account on a fresh host:

bash
sudo apt update
sudo apt install openjdk-21-jre-headless curl
sudo useradd --system --create-home --home-dir /srv/minecraft-fabric --shell /usr/sbin/nologin minecraft-fabric
sudo install -d -o minecraft-fabric -g minecraft-fabric /srv/minecraft-fabric/server
/usr/lib/jvm/java-21-openjdk-amd64/bin/java -version

The explicit Java path is for this Ubuntu x86-64 package. Check the installed path on another architecture. The example heap later uses 2 GiB; the host needs additional memory for Java's native allocations and the OS. A modpack may require more than this starting allocation.

Download the selected official launcher#

On the Fabric page select Minecraft 1.21.1, a compatible Loader and the launcher version. Copy the generated executable-server download URL. Replace the placeholder below with that exact HTTPS URL; do not copy a client installer or a random mirror.

bash
FABRIC_URL='PASTE_SELECTED_OFFICIAL_HTTPS_URL'
sudo -u minecraft-fabric curl --fail --location --proto '=https' --proto-redir '=https' "$FABRIC_URL" --output /srv/minecraft-fabric/server/fabric-server.jar
sudo -u minecraft-fabric sh -c 'cd /srv/minecraft-fabric/server && /usr/lib/jvm/java-21-openjdk-amd64/bin/java -Xms1G -Xmx2G -jar fabric-server.jar nogui'

The executable launcher downloads its selected components on the first run, so outbound access is required. Keep the downloaded launcher and the version record together. The initial run creates files and stops for the EULA. Read the linked agreement in eula.txt, then change eula=false to eula=true only if you accept it.

With the server stopped, edit server.properties using sudoedit. Set these values without duplicating existing keys:

properties
server-port=25565
level-name=fabric-smoke
server-ip=
online-mode=true
white-list=true
enforce-whitelist=true
enable-rcon=false
enable-query=false

fabric-smoke is a disposable baseline world, not the final world for a terrain-modifying pack. Keep authentication enabled. An empty server-ip uses the host's available interfaces; firewall access before starting. RCON and query stay disabled because this setup does not need them.

Admit your test player before adding mods#

Run the same foreground Java command again from the server directory. Wait for startup to finish. In that server console, enter the following with your actual Java account name replacing the example, then connect with a matching Minecraft client:

text
whitelist add YourJavaName

Use the server's private address while preparing it. After checking the intended world, enter stop in the console and wait for the process to exit. Do not start the service while this foreground instance is still running.

Now add the compatible server mods to /srv/minecraft-fabric/server/mods and give their files to minecraft-fabric. Install Fabric API when the selected mods require it; it is a separate mod, not Fabric Loader. Check every mod's game version, loader, dependencies and supported environment. Rendering, menus and other client-only mods normally stay on clients. Gameplay mods may require matching installations on both sides; server-only mods have different requirements.

A profile working in single player is insufficient evidence for a dedicated server. A Fabric support discussion illustrates this distinction. Perform incremental mod tests only in the disposable fabric-smoke world or a separate test copy. Add a small group at a time and read logs/latest.log after each change rather than overriding dependency checks blindly.

After checking the complete intended mod set, and before generating the real world, change level-name to a new, unused name such as friends. This generates the final world with the full intended mod set; do not reuse vanilla-generated chunks for a terrain-modifying pack. Preserve fabric-smoke separately rather than deleting unrelated saves.

Establish a working Fabric baseline before adding the mod set.

Run the foreground process under systemd#

Create /etc/systemd/system/minecraft-fabric.service with sudoedit:

ini
[Unit]
Description=Minecraft Fabric server
Wants=network-online.target
After=network-online.target

[Service]
User=minecraft-fabric
Group=minecraft-fabric
WorkingDirectory=/srv/minecraft-fabric/server
Environment=HOME=/srv/minecraft-fabric
ExecStart=/usr/lib/jvm/java-21-openjdk-amd64/bin/java -Xms1G -Xmx2G -jar fabric-server.jar nogui
KillSignal=SIGINT
TimeoutStopSec=180
Restart=on-failure
RestartSec=10
UMask=0027

[Install]
WantedBy=multi-user.target

The working directory determines where the launcher reads configuration and writes the world. SIGINT allows normal shutdown; check the log for completed saving, especially with heavy mods. A timeout followed by forced termination is not a successful save.

bash
sudo systemctl daemon-reload
sudo systemctl enable --now minecraft-fabric
sudo journalctl -u minecraft-fabric -n 100 --no-pager
sudo ss -ltnp 'sport = :25565'

Open only the required access and verify persistence#

Java Edition gameplay here uses TCP 25565. If UFW is already your active firewall, allow the tester first; replace the documentation address with their actual public IP:

bash
sudo ufw allow from 198.51.100.24 to any port 25565 proto tcp

Apply an equivalent rule in the provider firewall. Do not enable UFW remotely without preserving SSH access. A home router additionally needs TCP forwarding to this host and a reachable public address; CGNAT requires a different connectivity arrangement. Do not expose RCON as a connectivity fix.

Connect with the matching modpack, change something recognizable, disconnect, and run sudo systemctl restart minecraft-fabric. Reconnect and confirm the change survived. If startup fails, inspect the earliest meaningful error: wrong Java, missing dependency, incompatible mod or client-only class. An active service alone does not prove a usable world.

Before updating, stop gracefully and back up the complete server directory plus the service definition and version record. Keep a copy away from this disk. Test recovery separately; changing a modded world's version can make rollback impossible without the pre-update state.