119 lines
4.2 KiB
Markdown
119 lines
4.2 KiB
Markdown
# 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
|
||
|
||
```bash
|
||
./deploy.sh -n "Opengames" -a themiro \
|
||
-u https://games.abdelbaki.eu/mods \
|
||
--accept-eula
|
||
```
|
||
|
||
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:
|
||
|
||
```bash
|
||
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.
|
||
|
||
## 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 13 GB (`-X`/`-x` to change it). `-XX:+AlwaysPreTouch` means
|
||
the JVM commits the whole heap at startup rather than growing into it.
|
||
|
||
On a ZFS host, cap the ARC before running a heap this large — ZFS defaults to
|
||
using up to half of RAM for cache, which will fight the JVM for the same pages:
|
||
|
||
```bash
|
||
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, 13 GB heap + 2 GB ARC leaves ~1 GB
|
||
for everything else, which is tight — drop the heap to 10–11 GB if the host
|
||
does anything besides run the server.
|
||
|
||
## 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:
|
||
|
||
```bash
|
||
./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:
|
||
|
||
```bash
|
||
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.jar` → `create`). 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.
|