libreportal-relocate re-bakes the helpers, the systemd unit and the WebUI
compose, but never touched the manager's crontab — and the @reboot entry embeds
an absolute path under the SYSTEM dir:
@reboot /libreportal-system/install/scripts/crontab/system/crontab_boot_app_reconcile.sh
Move that root and the path stops existing. The entry is redirected to
/dev/null, so nothing reports it; the only symptom is that apps quietly do not
come back after a reboot, which is easy to blame on anything else.
Rewrite it with the same old->new substitution already applied to the unit and
compose, keeping a copy in the relocation's backup dir first.
(A fresh install is unaffected — it generates the entry with the resolved
install_scripts_dir. Verified on a matrix case-4 install with all three roots on
test disks: the entry points at /mnt/lptest1/... and the target exists.)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Root-run command to move the system and/or containers root to another
disk after install, re-baking everything that carries those paths: the
nine root-owned helpers, the CLI wrapper, the systemd unit and the
WebUI's own compose bind-mounts.
Deliberately NOT in the manager's scoped sudoers, and symlinked into PATH
like the uninstaller. Moving a root re-bakes the very helpers the sudoers
allowlist trusts, so a helper that did it from a caller-supplied path
would hand the manager the entire trust boundary those helpers exist to
defend. A human with real root runs this; the WebUI can only print the
command, which is what the Storage step now does.
Copy-verify-then-leave, never move: the source tree is not removed at all
— the command tells you to delete it once you have confirmed the WebUI
works. An interrupted run therefore leaves a working install behind
rather than half of one, and the pre-relocation copies of every
root-owned file are kept under $lp_lib_dir/.relocate-<timestamp>/.
Admission mirrors libreportal-storage: absolute, no "..", not a protected
system path, not already in use, must be an empty directory, roots must
not nest, and space checked with 10% headroom.
One bug worth recording, caught on the first test run against a live
install: _validate_target was called inside $(...), and `die` runs `exit`
— which inside a command substitution kills only the subshell. Every
refusal silently became "proceed" and the relocation ran. No damage (the
copy steps were guarded on a now-empty variable, so the re-bake wrote
identical values and only the service bounced), but it is exactly the
difference between a refusal and an unintended relocation. It now sets a
global and returns, so `die` exits the script it is meant to.
footprint_version -> 7 for the new root-owned executable.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>