From ed85ef98b3a28b9677b0a6435e8a089ae36d3b0c Mon Sep 17 00:00:00 2001 From: The_miro Date: Thu, 6 Aug 2026 00:09:14 +0200 Subject: [PATCH] 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 --- mc-service-setup.sh | 15 +++++++++++++-- packwiz-setup.sh | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/mc-service-setup.sh b/mc-service-setup.sh index cc004b2..922b675 100755 --- a/mc-service-setup.sh +++ b/mc-service-setup.sh @@ -76,16 +76,25 @@ jver="$(java -version 2>&1 | head -1 | grep -oE '"[0-9]+' | tr -d '"' || echo 0) # ------------------------------------------------------------------ user ---- +CREATED_USER=0 if ! getent passwd "$MCUSER" >/dev/null; then info "creating system user $MCUSER" useradd --system --home-dir "$SHARE" --shell /usr/sbin/nologin \ --comment "Minecraft server" "$MCUSER" + CREATED_USER=1 else info "user $MCUSER already exists" fi -info "setting ownership of $SHARE to $MCUSER" -chown -R "$MCUSER":"$MCUSER" "$SHARE" +# A blanket chown -R belongs to first-time setup only. On a re-run it would +# take the pack and the generated guides away from whoever authors them, and +# the next run of packwiz-setup.sh could no longer overwrite its own files. +if (( CREATED_USER )); then + info "setting ownership of $SHARE to $MCUSER" + chown -R "$MCUSER":"$MCUSER" "$SHARE" +else + info "user pre-existed — leaving ownership under $SHARE alone" +fi # The server creates mods/ on first run, but the pack setup needs it to exist # before that. Setgid so jars dropped in by either side stay group-readable. @@ -162,6 +171,8 @@ if [ -n "$NFVER" ]; then rm -rf "$tmp"; trap - EXIT fi +[ -d "$SHARE/libraries" ] && chown -R "$MCUSER":"$MCUSER" "$SHARE/libraries" + # Find the generated arg file — its path carries the NeoForge version, so # detect it rather than hardcoding one that goes stale on the next upgrade. ARGS_FILE="$(find "$SHARE/libraries/net/neoforged/neoforge" -name unix_args.txt 2>/dev/null | sort -V | tail -1 || true)" diff --git a/packwiz-setup.sh b/packwiz-setup.sh index c1cc5fa..ffbff84 100755 --- a/packwiz-setup.sh +++ b/packwiz-setup.sh @@ -582,6 +582,12 @@ if (( GUIDES )); then info "writing player setup guides to $WEBROOT" for os in windows linux; do out="$WEBROOT/setup-$os-packwiz.html" + # Remove first: a previous run may have left the file owned by another + # user, and truncating that fails even in a directory we can write. + if [ -e "$out" ] && [ ! -w "$out" ]; then + rm -f "$out" || die "cannot replace $out — owned by $(stat -c '%U' "$out") + fix with: sudo rm -f $out" + fi write_guide "$os" "$out" chmod 644 "$out" printf ' %s -> %s/setup-%s-packwiz.html\n' "$out" "$SITE_URL" "$os"