Packwiz-Abdelpak-hosting-kit/README.md

5.3 KiB

mc-packwiz-deploy

Self-hosted NeoForge Minecraft server with a packwiz modpack that clients pull automatically on every launch. Mods are served from an HTTP mirror of the server's own mods directory — no Modrinth or CurseForge dependency.

Everything lives on a ZFS dataset mounted at /minecraft.

Quick start

./deploy.sh -n "Opengames" -a themiro \
    -u https://games.abdelbaki.eu/mods \
    --accept-eula

Add -p 25599 to run on a non-default port. It's written into server.properties, opened in firewalld, and shown in the player guides — which print a bare hostname on 25565 and host:port on anything else, since Minecraft assumes the default and a needless :25565 confuses people.

The NeoForge version is resolved automatically — the newest stable build in the series matching your Minecraft version, from the NeoForged maven. Pin one with -N 21.1.248 if you'd rather not track latest.

Then:

sudo systemctl start minecraft
journalctl -u minecraft -f

Send the players https://<your-host>/setup-windows-packwiz.html or setup-linux-packwiz.html. Those are generated with your real pack URL and server address already filled in.

Re-running

deploy.sh is safe to run repeatedly, and re-running is the intended way to apply changed settings — a port change, a different heap size, or a run that failed partway and left things half-applied.

Each run:

  1. Snapshots the dataset (<pool>@predeploy-<timestamp>)
  2. Stops the server if it was running
  3. Rewrites server.properties, user_jvm_args.txt and both unit files
  4. Moves any existing pack to <pack>.bak.<timestamp> and rebuilds it
  5. Regenerates the player guides
  6. Starts the server again if it had been running

The world and /minecraft/mods are never touched. The pack is moved aside rather than deleted, so hand-edited .pw.toml files and any git history in the pack directory survive.

--keep-pack skips the pack rebuild; --no-snapshot skips step 1.

What's in here

Script Runs as Does
deploy.sh you Runs the two setup scripts in order
mc-service-setup.sh root minecraft user, NeoForge server, systemd units
packwiz-setup.sh you packwiz install, pack init, mod index, player guides
mc-refresh-restart.sh you Re-sync the pack after changing mods, then restart
build.sh you Builds the release zip

Memory

The heap defaults to 10 GB (-X/-x to change it). -XX:+AlwaysPreTouch means the JVM commits the whole heap at startup rather than growing into it, so the number you set is the number actually taken.

On a ZFS host, cap the ARC to go with it — ZFS defaults to using up to half of RAM for cache, and will otherwise contend with the JVM for the same pages:

echo "options zfs zfs_arc_max=2147483648" | sudo tee /etc/modprobe.d/zfs.conf
sudo dracut --force && sudo reboot

That pins the ARC to 2 GB. On a 16 GB box that leaves roughly 4 GB for the OS and anything else the host runs, which is comfortable.

Requirements

  • Fedora (or any systemd distro; dnf calls need swapping otherwise)
  • A ZFS dataset mounted at /minecraft
  • Java 21
  • A web server already publishing /minecraft/mods and /packs must be reachable over HTTP

Every script refuses to run if /minecraft isn't a mountpoint. An unmounted dataset leaves it as an empty directory on the root filesystem, and writing a world or a mod mirror there fills the root disk instead of the pool.

Day-to-day

Add or remove a jar in /minecraft/mods, then:

./mc-refresh-restart.sh

That registers new mods, re-pins any whose file changed, drops metadata for deleted ones, takes a ZFS snapshot, restarts the server, and prunes to the 8 most recent snapshots. Players get the change on their next launch.

It refuses to restart if any mod failed to register, so the server never comes up on a half-synced pack. Edit the config block at the top first — PACK_DIR, BASE_URL, and PACK_URL need to match your deployment.

The server unit

minecraft.service pairs with minecraft.socket, a console FIFO at /run/minecraft-console. That's what makes a clean shutdown possible:

sudo systemctl stop minecraft            # sends "stop", world saves properly
echo "say hello" | sudo tee /run/minecraft-console
journalctl -u minecraft -f               # console output

Without the FIFO, systemd would SIGTERM the JVM and risk cutting a world save in half.

Web server

/minecraft needs to be served over HTTP. Serve pack.toml and index.toml with Cache-Control: no-cache — a caching proxy will otherwise hand clients a stale pack while the server runs the new one. mc-refresh-restart.sh checks for exactly that and stops before restarting if it finds it.

Caveats

  • packwiz-setup.sh probes packwiz --help at runtime rather than assuming flag names, since the NeoForge options have moved between builds. If it bails with an interface complaint, the installed packwiz differs from what's expected.
  • Mod names come from filenames with the trailing version stripped (create-1.21.1-6.0.4.jarcreate). It's a heuristic; rename the generated .pw.toml files if you don't like the result.
  • Hashes are pinned. Replacing a jar in place under the same filename requires a re-sync, or clients fail the hash check.