CrewWorlds

Minecraft ยท Server setup

How to run a modded Minecraft server for your friends

The cheapest way to run one that doesn't suck, on hardware you already own or a box you rent. The real steps, the honest costs, and the traps nobody warns you about.

Ten steps, in order, from nothing to a server your friends connect to. The bold lines are the fast version; read the rest for the detail and the traps.

What this covers

  1. Read the pack's spec sheet. The four lines that dictate every choice after them.
  2. Size it right. Your own machine or a rented box, and why single-core speed matters more than total RAM.
  3. Install the correct Java. The version table, and why newer is not always better.
  4. Get the SERVER pack, not the client pack. And which client-only mods stop a headless server booting.
  5. Loader, EULA, server.properties. The two distance settings that beat any amount of RAM.
  6. RAM and JVM flags. Aikar's flags, and why more heap can make stutter worse.
  7. First boot and pre-generation. Chunky before anyone plays, Spark to read real TPS.
  8. Survive reboots. A graceful stop, so a restart never corrupts a region file mid-write.
  9. Add, swap and remove mods. The registry-entry trap and the loop that keeps it reversible.
  10. Backups that actually restore. Including getting a copy off the box, and testing one on purpose.

Then: the honest money math and how to split it, the one port-forwarding step if you self-host at home, and the no-terminal route if you'd rather never open a shell.

Where to run it: your own machine, or a cheap box

Two honest ways to do this, and the right one just depends on the hardware you already have. This is the one call to make before anything else.

On a machine you own. If you have a computer you can leave on that you are not also gaming on (a spare PC, an old desktop, a home server), you can run the server there for nothing but a little electricity. A heavy modpack wants 8 to 12 GB of RAM to itself and a strong CPU core, so this works when that machine has the headroom to spare. Two catches: the world is only up while that machine is on, and you forward one port on your home router so friends can reach it (covered later). If you own capable hardware you are not otherwise using, this is the cheapest path, full stop. What you should not do is run it on the same PC you play on, because it fights the game for CPU and RAM and you end up with the worst experience of anyone.

On a cheap box you rent. No spare machine with 8 to 12 GB to give, or you would rather not leave a PC on and open your home network? Rent a small Linux box. It has a public IP so there is no port forwarding, it stays up on its own, and dollar for dollar it is more power than most home hardware for this. A box that runs a heavy modpack well comes to a few dollars a month split with the crew (the honest math is near the end). If you want a recommendation, a dedicated-vCPU VPS like the ones at crewworlds.com/go/host is what I would get.

One more fork, only if you rent and you hate terminals: a managed Minecraft host clicks your pack from a library and keeps Java and backups correct for a bit more per gigabyte, skipping the command line entirely. It is the right call if you never want to open a shell, and there is a no-terminal path near the end for exactly that.

The build below is the self-host path, whether that is your own machine or a box you rent, because it is cheaper, more powerful, and the version where you actually learn how the thing works. The server does not care where it runs; only the networking differs, and I flag that where it matters.


The build, step by step

Step 1: Read the pack's spec sheet before you touch anything

Open your modpack's page on CurseForge or Modrinth and write down four things:

  1. The exact Minecraft version (like 1.20.1, or 1.21.1).
  2. The modloader (Forge, NeoForge, or Fabric).
  3. The loader version.
  4. The recommended server RAM.

That one line dictates every choice after it: which Java you install, which loader you run, how much memory you give it. Guess here and you'll be debugging phantom crashes for hours.

A quick word on loaders in 2026, because this trips up a lot of people:

The trap: from 1.20.2 onward, Forge and NeoForge are separate universes and their mods are NOT cross-compatible. A Forge mod dropped into a NeoForge server silently fails or crashes. So every single time you grab a mod, check that its page lists your exact loader AND your exact Minecraft version. Not "close enough." Exact.

Step 2: Size it right (your box or machine)

Whether you picked your own machine or a rented box, for 3 to 8 friends on a heavy pack you want two things: enough RAM, and a strong single-core CPU. The CPU is the one people get wrong.

Rough RAM targets:

A pack's advertised "minimum RAM" is for one person on a brand-new world. You and five friends exploring in different directions is two to three times that load. If a host tells you "4GB is plenty for ATM9," they're wrong, and you'll crash constantly. Size for the real thing, not the brochure number.

For a VPS, I run these on Hostinger's KVM plans, and here's why they fit modded specifically: the KVM tiers give you dedicated vCPU (not the cheap shared-core stuff), which is exactly what a single-threaded game like Minecraft needs, plus enough RAM to actually breathe.

You can grab one here: crewworlds.com/go/host. Spin up Ubuntu or Debian (the latest LTS). A rented box has a public IP, so there is no port forwarding (see the connect step).

Do not cheap out on a shared-vCPU box just because it lists 16 GB for a few bucks. A weak shared core with tons of RAM will still stutter on chunk generation, because RAM was never your bottleneck. A strong core with 8 GB won't. Spend on the CPU.

Step 3: Install the correct Java

Java version tracks the Minecraft version, not the loader, and newer is not always better. Get this wrong and the server dies on boot with an UnsupportedClassVersion error.

Minecraft version Java you need
1.16.5 and older Java 8
1.17.x Java 16
1.18 through 1.20.4 Java 17
1.20.5 through 1.21.x Java 21

Use Eclipse Temurin (Adoptium) builds, they're the community standard and they're free. Grabbing "the latest Java" for an old Forge pack will throw cryptic class-loading errors, so match the table, don't chase the newest number.

Confirm it took with java -version before you move on. Evidence over assumption, always.

While you're in the terminal, create a dedicated non-root user for this (call it minecraft) and run everything as that user. Never run a game server as root.

Step 4: Get the SERVER pack, not the client pack

This is the single most common "my server won't start" cause, and it's a five-second fix once you know it.

The big green Download button on CurseForge or Modrinth gives you the CLIENT pack. That's the version you install in the launcher to play. Upload it to a server and it won't run, or it'll crash, because it's stuffed with mods that only make sense on your own machine.

What you want is the Server Pack, from the Files tab (CurseForge labels it exactly that). On Modrinth, grab the .mrpack and deploy it with a tool like mrpack-install. The server pack is the same content minus the client-only mods, plus the loader installer and a run.sh script.

Client-only mods are the visual and quality-of-life stuff that runs on your machine and does nothing (or actively crashes) on a headless server: Sodium, Iris and shaders, minimaps, HUD tweaks, controller mods, Controlling, TrashSlot, Clumps. If your server boots fine when you test it solo but dies when it's actually running as a server, a client-only mod snuck into the server's /mods folder. Pull it out. It belongs only in your friends' clients.

If no server pack was published, you build one: copy the client instance's /mods and /config, delete the client-only mods listed above, and install the matching loader's server files.

One heads-up that trips up auto-installers: CurseForge requires API-key authentication for automated file downloads (that rule went into force back in mid-2025), and some mod authors turn off third-party distribution entirely. If an auto-installer chokes on a specific mod, that's usually why, and you'll need to grab that one by hand. Not a big deal, just don't let it confuse you.

Step 5: Unzip, install the loader, accept the EULA, tune the settings

Drop the server pack into a clean directory and run the bundled loader installer (something like java -jar neoforge-<version>-installer.jar --installServer, or the Forge equivalent). You should end up with /mods, /config, the loader libraries, and a run.sh.

Open server.properties and set:

Then add your crew to the whitelist. Once the server's running you just type whitelist add <username> in the console for each person, or edit whitelist.json. A whitelist is not optional for a private server. It's the difference between "our world" and "some rando griefed the base while we slept."

Step 6: Set your RAM and JVM flags (and do NOT just max out the memory)

Throwing more RAM at the server can make it worse.

A bigger heap means the garbage collector has more memory to scan, which means longer pauses, which shows up in-game as stutter and TPS drops. Past what your pack actually needs, extra RAM buys you close to nothing on performance. It only prevents out-of-memory crashes.

So do two things:

1. Set -Xms equal to -Xmx, and leave headroom. On a 16 GB box, give the server 12 GB, not 16. That ~2 GB you held back is for the operating system and the JVM's own off-heap memory. Hand the JVM everything and Linux's out-of-memory killer will silently execute your server mid-session, and you'll have no idea why it "just died."

2. Use Aikar's flags. These are the community-standard G1GC tuning, and they help. Modern Forge and NeoForge put your memory settings in a user_jvm_args.txt file next to run.sh. Here's the standard set:

-Xms10G
-Xmx10G
-XX:+UseG1GC
-XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions
-XX:+DisableExplicitGC
-XX:+AlwaysPreTouch
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
-XX:G1HeapRegionSize=8M
-XX:G1ReservePercent=20
-XX:G1HeapWastePercent=5
-XX:G1MixedGCCountTarget=4
-XX:InitiatingHeapOccupancyPercent=15
-XX:G1MixedGCLiveThresholdPercent=90
-XX:G1RSetUpdatingPauseTimePercent=5
-XX:SurvivorRatio=32
-XX:+PerfDisableSharedMem
-XX:MaxTenuringThreshold=1

If your heap is larger than 12 GB, switch to the large-heap variant: G1NewSizePercent=40, G1MaxNewSizePercent=50, G1HeapRegionSize=16M, G1ReservePercent=15, InitiatingHeapOccupancyPercent=20, G1MixedGCCountTarget=8.

Step 7: First boot, then pre-generate the world

Start the server by hand the first time and watch the log scroll to a clean Done with no fatal errors. Then have one friend connect, on the exact same pack version, to confirm the mod lists match and nobody gets a mismatch kick. (More on that in the port section.)

The most CPU-punishing thing your server does is generate new chunks, and it does it on one thread while your friends watch the world stutter into existence. That is the mystery lag, and you can front-load it before anyone plays.

So generate it in advance, while nobody's playing. Install the Chunky mod and pre-generate a reasonable radius around spawn (a few thousand blocks). It front-loads the heavy work into the quiet hours, and most of your in-play lag vanishes. Add the Spark mod too, so you can type /spark and actually see your TPS and GC behavior instead of guessing.

If you ever see Can't keep up! Is the server overloaded? in the console with TPS dropping below 20, and your RAM and CPU graphs look half-empty, this is why. It's one core doing chunk work, not a memory shortage. Pre-gen and lower view distance, in that order, before you ever think about paying for a bigger box.

Step 8: Run it as a service, so it survives reboots

You want the server to launch on boot, come back after a reboot, and, critically, shut down gracefully so it never corrupts the world mid-save. (True crash auto-restart with this pattern is finicky, since systemd tracks the tmux session rather than the Java process itself; getting that bulletproof is one thing the Deploy Pack handles for you.)

You run the server inside a tmux session (so you can attach to the live console any time), and you wrap it in a systemd service. Here's the shape of it:

[Unit]
Description=Modded Minecraft Server
After=network.target

[Service]
User=minecraft
Type=forking
WorkingDirectory=/home/minecraft/server
ExecStart=/usr/bin/tmux new-session -d -s mc '/home/minecraft/server/run.sh'

# Graceful stop: save the world, wait, then stop the server, wait
ExecStop=/usr/bin/tmux send-keys -t mc 'save-all' Enter
ExecStop=/bin/sleep 10
ExecStop=/usr/bin/tmux send-keys -t mc 'stop' Enter
ExecStop=/bin/sleep 20

# The setting that matters most: stop systemd from SIGKILLing the JVM mid-write
KillMode=none
Restart=on-failure
RestartSec=15

[Install]
WantedBy=multi-user.target

Then systemctl enable --now minecraft and it survives reboots.

The KillMode line matters. Without a graceful stop, a plain systemctl stop or a reboot hard-kills the JVM mid-write, and a half-written region file is a classic way to corrupt a world. The save-all then stop then wait sequence keeps it intact every time the box restarts.

Step 9: Add, swap, and remove mods without breaking the world

Adding and removing mods are not the same risk. Adding is usually safe. Removing can permanently delete parts of your world. Mixing them up is how people lose bases, so here is how each one works.

Adding a mod: usually safe

New mods bring new blocks, items, mobs, and recipes. They don't touch what's already generated, and new content mostly shows up in freshly generated chunks. So adding is the low-risk move. But two things still bite people:

Swapping a mod (or updating one): medium risk

A swap is a remove plus an add, so it inherits the removal risk below. Version-matching a mod up or down can also change how it stored data. Treat it like a removal: back up first.

Removing a mod: THIS is the dangerous one

When you delete a mod that already wrote blocks or items into your world, the game restarts and finds references to content that no longer exists. On Forge and NeoForge you'll see:

Fatally missing registry entries

This is not a crash you can click through. On Forge (and its NeoForge descendants) you get past it by confirming: type /fml confirm in the console, or, since a headless server usually refuses to boot without an answer, pass -Dfml.queryResult=confirm as a JVM argument. Either way the world loads. But confirming permanently deletes every block and item that mod added. Those blocks become air (holes in your base), and those items vanish out of chests and inventories. Gone. Forge writes an automatic backup alongside your world folder when it does this, but never, ever rely on that. Make your own first.

And then there's the truly dangerous case, the one that doesn't just delete items but actually corrupts terrain:

Removing a worldgen, biome, or dimension mod after that terrain has already generated. Your existing chunks reference biomes, features, or whole dimensions that no longer exist. That can produce corrupt chunks, cascading worldgen errors, or hard crashes on load. This isn't "I lost some items," this is "the world won't open." Sometimes the only fix is deleting and regenerating the affected dimension's region folders. Treat pulling a worldgen mod like open-heart surgery, and never do it on your only copy.

The repeatable loop that makes all of it safe

Here's the workflow I run every single time, no exceptions. Follow it and you can experiment freely, because a mistake is never permanent:

  1. Announce it and stop the server. Never edit /mods on a live world.
  2. Back up the WHOLE instance, not just /world. The full folder. (Step 10 automates this. Before it's automated, do it by hand.)
  3. Make the change on the server. Add dependencies too. For a removal, know first whether the mod wrote to the world, and especially whether it touched worldgen.
  4. Mirror the exact change on every client, same versions, for every content mod. This is non-negotiable, it's the "it works on my machine but nobody can join" fix.
  5. Restart and watch the log. If you hit missing registry entries, only confirm past it (/fml confirm in the console, or the -Dfml.queryResult=confirm JVM arg on a headless box) after you know your backup exists.
  6. Verify everyone can join and the base is intact.
  7. Keep it, or roll back to the backup you made in step 2. That last option is the whole reason this is safe.

That's it. You're not risking the world every time you try a mod; you're making a backup and running a checklist.

Step 10: Backups that actually restore

A backup you've never tested is a rumor, not a safety net. Two rules make backups real:

1. Never copy the world while the server is writing to it. You'll get a torn, unrestorable file. Either stop the server, or run save-off then save-all in the console, copy or tar the files, then save-on to resume writes.

2. Automate it and get a copy off the box. A cron job that runs the save-off/save-all dance, tars /world (plus world/serverconfig, where a lot of packs keep per-world settings) with a timestamp, prunes old archives with find -mtime, and rsyncs a copy somewhere else. If the whole VPS dies, a backup that only lived on that VPS died with it. There's a ready-made script, nicolaschan/minecraft-backup, that handles the tmux/RCON save dance and tar or restic out of the box.

The part people skip: actually restore one, once, on purpose. Prove the file opens into a working world before you need it.

Keep a "sticky" snapshot right before every mod change and every pack update. Those are the ones that save you.

Quick note on updating the whole pack: snapshot first, keep your /world, replace /mods and the loader with the new version's server pack, then re-apply any custom edits to /config (the update usually overwrites that folder, so note your tweaks before you start). Make sure every friend updates to the identical version. If the world won't load on the new pack, restore the snapshot and stay put. There's no shame in staying a version behind on a world you love.


Getting your friends connected

Half the "my friends can't join" agony out there is one problem: port forwarding. The endless spiral of connection timed out, "is it my router," "do we have to use Hamachi." It has a reputation as a nightmare. It is not, once you know which of the two paths you are on.

If you rented a box, there is nothing to forward. It sits on the open internet with its own public IP and no router in front of it, so you just open the game port in its firewall:

sudo ufw allow 25565/tcp
sudo ufw allow OpenSSH

Then hand your friends the server's IP address and they connect. No router settings, no Hamachi, no calling your ISP.

If you self-host at home, forward the port on your router: log in (usually 192.168.1.1 in a browser), find port forwarding, and forward TCP 25565 to the machine running the server. Give friends your home's public IP.

One security note either way: open only the game port (25565), plus your SSH port on a rented box. Do NOT expose RCON (port 25575) to the internet. Leave it bound to localhost.

And to be clear about the other "can't join" cause, the mod-version mismatch kick: that's not a network problem at all. That's the mod-list-must-match rule from Step 9. Everyone on the identical pack version, and that error disappears too.


The honest money math

Here's what it costs, and how to split it without chasing anyone for four dollars.

Your own hardware: if you have a spare, capable machine you can leave on, the server costs nothing but a little electricity. This is the cheapest path, full stop, as long as it is not the PC you game on (more on that below).

Rent a box: a 16 GB dedicated-vCPU box runs roughly $15 to $25 a month depending on the term. You own the ops, which this guide just handed you.

Managed host: budget around $3.75 per gigabyte, so an 8 GB heavy-modded plan lands near $30 a month, and a 10 to 12 GB plan closer to $35 to $45. More per gigabyte, but it buys back your time.

Now split it, because nobody should be paying for this alone:

Crew size$20/mo VPS$30/mo managed
3 people$6.67 each$10.00 each
4 people$5.00 each$7.50 each
5 people$4.00 each$6.00 each
6 people$3.33 each$5.00 each
8 people$2.50 each$3.75 each

At five people that's four dollars a month each. You will all spend more than that on one indie game you play for two hours and never open again.

When "free" is not actually free

Self-hosting on a spare machine really is close to free. But if the "free" plan is to run it on the PC you actually game on, that has a bill; it just does not arrive as an invoice:

So a spare box you would leave on anyway is the cheap option. Your main rig doing double duty usually is not, and once you count the real costs a rented box is often cheaper.


The no-terminal path (if systemd made your eyes glaze over)

If you read Step 8 and thought "absolutely not," that's a completely valid answer, and there's a clean path for you.

A managed modded host does the sysadmin work so you don't. You pick your pack from a library, it installs in one click, the correct Java is already set, backups run on a schedule, and there's a web panel instead of a command line. You skip Steps 3, 5, 6, 8, and 10 entirely, and you point your friends at an address the host gives you.

For the no-terminal route I'd point you at Apex Hosting. They've got a strong reputation for a clean panel, one-click modpack installs, automatic Java, and offsite backups, which is exactly the "I just want to play, not administrate" package. Their pricing is a flat rate across the mid-range (roughly $7.49 for 2 GB, $29.99 for 8 GB), so you can right-size to your pack.

You lose some control and pay a bit more per gigabyte. You gain your evenings back. For a lot of people, that's the right trade, and there's nothing wrong with making it.


If you'd rather not do it by hand

Everything above works, and if you follow it you won't need anything else here.

But if you'd rather not spend the evening in a terminal, the Deploy Pack does the setup for you. You still rent your own box (Step 2). Then you run one script, and it walks you through the whole thing: it works out the right Java for your pack, installs the server, sets the memory and Aikar's flags, wires up the backups, and handles adding, removing and version-matching mods, including the single zip your friends install so nobody gets a mismatch kick. It doesn't test your restores, so Step 10 is still yours, and it doesn't buy the server for you.

A Discord bot, Server Butler, for starting, stopping and backing up the server from chat, is coming later.

Now go get the box. Your crew's waiting.

CrewWorlds