feat(uninstall): location-agnostic 'libreportal-uninstall' command (+ de-hardcode docs)

The docs were telling users to run /libreportal-system/install/uninstall.sh — a
hardcoded data path, wrong for any custom --system-dir, contradicting the whole
relocatable design.

Fix it the way the CLI already works: install uninstall.sh to the FIXED footprint
(/usr/local/lib/libreportal/uninstall.sh) and symlink it onto $PATH as
'libreportal-uninstall' (initLibrePortalCommand). It self-resolves the real data
roots from the systemd unit, so the command is the same everywhere regardless of
where data lives. Teardown removes the new symlink; FOOTPRINT.md lists it.

Docs now say 'sudo libreportal-uninstall' — no data path. (Dev-from-clone still
uses ./uninstall.sh / ./init.sh uninstall.)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
librelad 2026-05-25 18:50:26 +01:00
parent 55dd62af56
commit 8472fdf0ae
3 changed files with 18 additions and 8 deletions

View File

@ -28,6 +28,7 @@ together in **`/usr/local/lib/libreportal/`**; everything else is named
| File | Owner | Purpose | | File | Owner | Purpose |
|------|-------|---------| |------|-------|---------|
| `libreportal` | root | the CLI wrapper (symlinked onto `$PATH`, see below) | | `libreportal` | root | the CLI wrapper (symlinked onto `$PATH`, see below) |
| `uninstall.sh` | root | the uninstaller (symlinked onto `$PATH` as `libreportal-uninstall`) |
| `libreportal-ownership` | root | reconcile the three-root ownership model | | `libreportal-ownership` | root | reconcile the three-root ownership model |
| `libreportal-dns` | root | edit `/etc/resolv.conf` (nameservers) | | `libreportal-dns` | root | edit `/etc/resolv.conf` (nameservers) |
| `libreportal-ssh-access` | root | manage admin `authorized_keys` + sshd `PasswordAuthentication` | | `libreportal-ssh-access` | root | manage admin `authorized_keys` + sshd `PasswordAuthentication` |
@ -47,6 +48,7 @@ quick-deploy).
| Path | Owner | Purpose | | Path | Owner | Purpose |
|------|-------|---------| |------|-------|---------|
| `/usr/local/bin/libreportal` | root | **symlink**`/usr/local/lib/libreportal/libreportal` (puts the CLI on `$PATH`) | | `/usr/local/bin/libreportal` | root | **symlink**`/usr/local/lib/libreportal/libreportal` (puts the CLI on `$PATH`) |
| `/usr/local/bin/libreportal-uninstall` | root | **symlink**`/usr/local/lib/libreportal/uninstall.sh` (location-agnostic uninstall command) |
| `/etc/sudoers.d/<manager>` | root | scoped least-privilege grant for the manager (drop-in named after the manager user) | | `/etc/sudoers.d/<manager>` | root | scoped least-privilege grant for the manager (drop-in named after the manager user) |
| `/etc/systemd/system/libreportal.service` | root | the task-processor service (`User=<manager>`; bakes the roots as `Environment=LP_*_DIR`) | | `/etc/systemd/system/libreportal.service` | root | the task-processor service (`User=<manager>`; bakes the roots as `Environment=LP_*_DIR`) |
| `/etc/sysctl.d/99-libreportal-hardening.conf` | root | kernel LPE-surface hardening | | `/etc/sysctl.d/99-libreportal-hardening.conf` | root | kernel LPE-surface hardening |
@ -73,7 +75,7 @@ config lives at `~<container-user>/.config/docker/daemon.json`.
sudo systemctl disable --now libreportal.service sudo systemctl disable --now libreportal.service
sudo rm -f /etc/systemd/system/libreportal.service /etc/sudoers.d/libreportal sudo rm -f /etc/systemd/system/libreportal.service /etc/sudoers.d/libreportal
sudo rm -f /etc/sysctl.d/99-libreportal-*.conf sudo rm -f /etc/sysctl.d/99-libreportal-*.conf
sudo rm -rf /usr/local/lib/libreportal /usr/local/bin/libreportal sudo rm -rf /usr/local/lib/libreportal /usr/local/bin/libreportal /usr/local/bin/libreportal-uninstall
sudo rm -rf /libreportal-system /libreportal-containers /libreportal-backups sudo rm -rf /libreportal-system /libreportal-containers /libreportal-backups
# optional: the backup-engine binaries and the two users # optional: the backup-engine binaries and the two users
``` ```

View File

@ -85,15 +85,15 @@ the required ownership and will warn.
## Uninstall ## Uninstall
```bash ```bash
sudo /libreportal-system/install/uninstall.sh sudo libreportal-uninstall
# keep the rootless Docker layer + image cache for a fast reinstall: # keep the rootless Docker layer + image cache for a fast reinstall:
sudo /libreportal-system/install/uninstall.sh --skip-docker-images sudo libreportal-uninstall --skip-docker-images
``` ```
`uninstall.sh` finds your install automatically (even with custom roots — it reads `libreportal-uninstall` is a fixed command on `$PATH` (no data path to type — it
the real locations from the installed service) and removes the three roots, the reads the real install locations from the installed service, so it works even with
system users, and the small out-of-tree footprint (`/usr/local/lib/libreportal`, custom roots). It removes the three roots, the system users, and the small
the `/etc` integration files). `sudo init.sh uninstall` does the same thing. out-of-tree footprint (`/usr/local/lib/libreportal`, the `/etc` integration files).
> ⚠️ Uninstall permanently deletes all app data, configs, and the database. Take a > ⚠️ Uninstall permanently deletes all app data, configs, and the database. Take a
> backup first if you want to keep anything. > backup first if you want to keep anything.

10
init.sh
View File

@ -1467,6 +1467,14 @@ EOF
sudo chown root:root $command_script sudo chown root:root $command_script
# Put it on $PATH via a symlink (replaces any older real file at this path). # Put it on $PATH via a symlink (replaces any older real file at this path).
sudo ln -sfn "$command_script" "$command_symlink" sudo ln -sfn "$command_script" "$command_symlink"
# Install the uninstaller at the fixed footprint + put it on $PATH as
# `libreportal-uninstall` — a location-agnostic command (it resolves the real
# data roots from the systemd unit at run time), so users never type a data path.
if [[ -f "$script_dir/uninstall.sh" ]]; then
sudo install -m 0755 -o root -g root "$script_dir/uninstall.sh" "$lp_lib_dir/uninstall.sh"
sudo ln -sfn "$lp_lib_dir/uninstall.sh" /usr/local/bin/libreportal-uninstall
fi
source $sudo_bashrc source $sudo_bashrc
} }
@ -1643,7 +1651,7 @@ runFullUninstall()
fi fi
# 3. Remove the out-of-/docker footprint (see docs/FOOTPRINT.md). # 3. Remove the out-of-/docker footprint (see docs/FOOTPRINT.md).
rm -f /usr/local/bin/libreportal rm -f /usr/local/bin/libreportal /usr/local/bin/libreportal-uninstall
rm -rf /usr/local/lib/libreportal rm -rf /usr/local/lib/libreportal
rm -f "/etc/sudoers.d/$mgr" rm -f "/etc/sudoers.d/$mgr"
# Keep the sysctl drop-ins when preserving docker — removing + reloading them # Keep the sysctl drop-ins when preserving docker — removing + reloading them