Commit Graph

8 Commits (f1731698ed54ef93f8b67bf6dfd95fc79c6e9904)

Author SHA1 Message Date
Amir Alexander Abdelbaki ed85ef98b3 Stop re-runs from locking the author out of their own files
mc-service-setup.sh ran chown -R minecraft:minecraft over the whole share on
every invocation. That is right for first-time setup and wrong afterwards: it
takes the generated guides and the pack away from the user who authors them, so
the next packwiz-setup.sh run could not overwrite files it had written itself.
The directory stayed writable, so the up-front -w check passed and the failure
surfaced as a bare "Permission denied" mid-write.

The blanket chown now runs only when the service user is created in that same
run. libraries/ is still chowned unconditionally, since the NeoForge installer
writes it and the service must own it.

packwiz-setup.sh also removes a guide it cannot write before regenerating it,
rather than truncating in place, so a share left in the old state repairs itself
instead of needing manual chown.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 00:09:14 +02:00
Amir Alexander Abdelbaki ae1671b361 Deploy a complete instance with no mods present
Two things stopped a from-scratch deploy finishing in one run.

The mirror reachability probe ran before counting jars, so a fresh instance
with an empty mods directory still failed on an unreachable mirror despite
having nothing to fetch. The probe now runs only when there is at least one jar,
which also means the reverse proxy does not have to be in place yet to build the
initial pack. mc-refresh-restart.sh gets the same treatment: zero jars is a
legitimate state, and the orphan sweep clears the metadata to match.

The probe itself never worked. curl -w '%{http_code}' already prints 000 on a
connection failure, so the trailing "|| echo 000" appended a second one and the
value was 000000, matching neither the unreachable case nor anything else — the
guard silently degraded to a warning. Use "|| true" with a :-000 fallback.
Verified against a refused port and a live host.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:38:57 +02:00
Amir Alexander Abdelbaki 908c4ecbb6 Do not fail when the mods directory is absent or empty
On a first deploy the server has not run yet, so /minecraft/mods does not
exist and packwiz-setup.sh died before creating anything. It now creates the
directory, and mc-service-setup.sh also creates it up front with setgid so jars
dropped in by either the service user or the admin stay group-readable.

An empty mods directory is likewise no longer fatal. A pack with no mods yet is
a valid starting point: the pack, the index and the player guides are all
generated, and jars registered later with mc-refresh-restart.sh.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:36:37 +02:00
Amir Alexander Abdelbaki b32b47f020 Add packwiz-http service and --scheme flag
The reverse proxy runs on a different host than the game server, so it cannot
alias the share directly — serving the pack needs an HTTP server on the game
server itself.

packwiz-http.py is a threaded static server over an allowlist: mods/, packs/,
and setup-*.html. Everything else 404s, since the same directory holds
server.properties, ops.json, whitelist.json, logs and the world. Threading
matters because installing a pack is one request per mod and a single-threaded
server serialises a whole lobby behind one download. pack.toml and index.toml
are sent no-cache so a proxy cannot serve a stale pack.

Installed as packwiz-http.service on port 18080 by default, configurable with
-H/-B, skippable with --no-http, and read-only via ReadOnlyPaths.

packwiz-setup.sh gains -S/--scheme, for when the pack is built against a mirror
reachable only over plain HTTP but clients must be handed the public HTTPS URL.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:27:40 +02:00
Amir Alexander Abdelbaki 7a84ef3117 Handle a mirror served under a base path
Deriving the site URL by reducing the mirror URL to its origin discarded any
base path, so a mirror at https://host/abdelpakDelta/mods produced a pack URL
of https://host/packs/<slug> — a location nothing serves. Strip the last path
segment instead, which gives the right answer with or without a base path.

The server address derivation also only stripped scheme and port, so a site URL
carrying a path leaked it into the address shown to players. Strip the path too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:12:40 +02:00
Amir Alexander Abdelbaki b4320303d3 Make deploy.sh safely re-runnable
Re-running previously died at step 2, because packwiz-setup.sh refused to
overwrite an existing pack.toml — so a run that failed partway, or any later
change to port or heap, could not be applied by simply running it again.

deploy.sh now snapshots the dataset, stops the server if it was running,
redeploys, and restarts it only if it had been up. packwiz-setup.sh gains
--force, which moves an existing pack to <pack>.bak.<timestamp> rather than
deleting it, since the directory may hold hand-edited .pw.toml files or git
history. deploy.sh passes --force unless --keep-pack is given.

World data and the server's mods directory are untouched throughout.

Also replaces the hardcoded sed line ranges in every usage() with an awk that
prints the leading comment block, so help text stops drifting out of sync when
the header changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:02:46 +02:00
Amir Alexander Abdelbaki debada2b56 Add -p/--port for the Minecraft server port
Threads a port through all three scripts. mc-service-setup.sh writes
server-port into server.properties (updating in place so a generated file keeps
its other settings) and opens the port in firewalld. packwiz-setup.sh renders it
into the player guides.

The guides print a bare hostname on 25565 and host:port otherwise — Minecraft
assumes the default, and a needless ":25565" in the address reliably confuses
players.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:00:12 +02:00
Amir Alexander Abdelbaki e738422dbe Initial commit: packwiz + NeoForge hosting kit
Deploys a self-hosted NeoForge server whose modpack clients pull automatically
on launch, with mods served from an HTTP mirror of the server's own mods dir
rather than Modrinth or CurseForge.

- mc-service-setup.sh: minecraft user, NeoForge install, systemd service paired
  with a console FIFO socket so stops are graceful and the world saves
- packwiz-setup.sh: packwiz install, pack init, mod index built from the
  mirror, and per-OS player setup guides generated with real URLs baked in
- mc-refresh-restart.sh: re-sync after mod changes, ZFS snapshot, restart
- deploy.sh: runs the above in order
- build.sh: release zip, refusing to package scripts that don't parse

Every entry point refuses to run when /minecraft is not a mountpoint, so an
unmounted dataset cannot silently fill the root filesystem.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 22:23:34 +02:00