forked from heavy-duty/rig
fix(forgejo-runner): the cache server can start
ProtectHome=read-only made the whole home read-only and only RUNNER_DIR was punched back through, so forgejo-runner could not create $HOME/.cache and disabled its cache server on every install. actions/cache was silently off on every rig-installed Forgejo runner, evidenced by one error line in the journal while `status` reported a healthy runner. Both halves are required, and the obvious one-line version is WORSE than the bug: a ReadWritePaths entry naming a path that does not exist makes systemd refuse to start the unit at all — "Failed to set up mount namespacing", three restart attempts, service down. Measured on a live runner before writing this. So the directory is created at install, owned by the runner user like RUNNER_DIR beside it, and the unit lists it. ProtectHome stays read-only: the runner supervises job containers on this box's docker socket, and the cache is not a reason to widen that. Verified live from scratch: directory removed, unit removed, converge, then zero cache-server errors and the two cache listeners bound. Closes #135 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4a6e9761e5
commit
a45d84892f
3 changed files with 33 additions and 1 deletions
3
changelog.d/135.md
Normal file
3
changelog.d/135.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Forgejo runners installed by rig can start their cache server — `$HOME/.cache` is created and punched through `ProtectHome` (#135)
|
||||||
|
|
@ -397,6 +397,14 @@ fi
|
||||||
# holds the UUID. assert_runner_instance's contract survives either way — it
|
# holds the UUID. assert_runner_instance's contract survives either way — it
|
||||||
# asks about the instance, which both spellings record.
|
# asks about the instance, which both spellings record.
|
||||||
install -d -m 0755 -o "$RUNNER_USER" -g "$RUNNER_GROUP" "$RUNNER_DIR"
|
install -d -m 0755 -o "$RUNNER_USER" -g "$RUNNER_GROUP" "$RUNNER_DIR"
|
||||||
|
# forgejo-runner's cache server writes to $HOME/.cache, which ProtectHome makes
|
||||||
|
# read-only below. Create it HERE, before the unit can reference it: a
|
||||||
|
# ReadWritePaths entry naming a path that does not exist makes systemd refuse
|
||||||
|
# to start the unit at all ("Failed to set up mount namespacing"), which is
|
||||||
|
# worse than the disabled cache it was meant to fix. Measured on a live runner,
|
||||||
|
# 2026-07-31 (#135). Root-owned would fail the same way under User=, so it
|
||||||
|
# carries the runner's own ownership like RUNNER_DIR above.
|
||||||
|
install -d -m 0755 -o "$RUNNER_USER" -g "$RUNNER_GROUP" "$USER_HOME/.cache"
|
||||||
if [ -e "$RUNNER_DIR/.runner" ]; then
|
if [ -e "$RUNNER_DIR/.runner" ]; then
|
||||||
log "already registered; skipping registration"
|
log "already registered; skipping registration"
|
||||||
# Registration was skipped, so the labels on the instance are the ones it was
|
# Registration was skipped, so the labels on the instance are the ones it was
|
||||||
|
|
@ -461,7 +469,7 @@ NoNewPrivileges=true
|
||||||
PrivateTmp=true
|
PrivateTmp=true
|
||||||
ProtectSystem=full
|
ProtectSystem=full
|
||||||
ProtectHome=read-only
|
ProtectHome=read-only
|
||||||
ReadWritePaths=${RUNNER_DIR}
|
ReadWritePaths=${RUNNER_DIR} ${USER_HOME}/.cache
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
|
||||||
21
test/cli.sh
21
test/cli.sh
|
|
@ -3350,6 +3350,27 @@ check "forgejo-runner: remove warns about an orphaned unit" 0 "orphaned unit" \
|
||||||
check "forgejo-runner: remove never rm's an unguarded \$RUNNER_DIR path" 1 "" \
|
check "forgejo-runner: remove never rm's an unguarded \$RUNNER_DIR path" 1 "" \
|
||||||
grep -qE '^rm -f "\$RUNNER_DIR' "$ROOT/commands/forgejo-runner-remove.sh"
|
grep -qE '^rm -f "\$RUNNER_DIR' "$ROOT/commands/forgejo-runner-remove.sh"
|
||||||
|
|
||||||
|
# #135: ProtectHome=read-only made the whole home read-only and only RUNNER_DIR
|
||||||
|
# was punched back through, so forgejo-runner could not create $HOME/.cache and
|
||||||
|
# disabled its cache server on every install — actions/cache silently off, one
|
||||||
|
# error line in the journal, and `status` reporting a healthy runner.
|
||||||
|
#
|
||||||
|
# BOTH halves are asserted because the obvious one-line version is WORSE than
|
||||||
|
# the bug: listing the path in ReadWritePaths without creating it makes systemd
|
||||||
|
# refuse to start the unit at all ("Failed to set up mount namespacing"),
|
||||||
|
# measured on a live box. The directory must exist first.
|
||||||
|
FRI="$ROOT/commands/forgejo-runner-install.sh"
|
||||||
|
grep_cache_install() {
|
||||||
|
# shellcheck disable=SC2016 # $RUNNER_USER is literal text in the shipped file
|
||||||
|
grep -qE 'install -d .*-o "\$RUNNER_USER".*\.cache' "$FRI"
|
||||||
|
}
|
||||||
|
check "forgejo-runner: the cache dir is punched through ProtectHome" 0 "" \
|
||||||
|
grep -qE 'ReadWritePaths=.*\.cache' "$FRI"
|
||||||
|
check "forgejo-runner: …and the install creates it, owned by the runner user" 0 "" \
|
||||||
|
grep_cache_install
|
||||||
|
check "forgejo-runner: ProtectHome stays read-only (the cache is not an excuse to widen it)" 0 "" \
|
||||||
|
grep -qF 'ProtectHome=read-only' "$FRI"
|
||||||
|
|
||||||
check "forgejo-runner: status --help exits 0" 0 "usage:" "$ROOT/commands/forgejo-runner-status.sh" --help
|
check "forgejo-runner: status --help exits 0" 0 "usage:" "$ROOT/commands/forgejo-runner-status.sh" --help
|
||||||
check "forgejo-runner: remove --help exits 0" 0 "usage:" "$ROOT/commands/forgejo-runner-remove.sh" --help
|
check "forgejo-runner: remove --help exits 0" 0 "usage:" "$ROOT/commands/forgejo-runner-remove.sh" --help
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue