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>
82 lines
4.5 KiB
Markdown
82 lines
4.5 KiB
Markdown
# LibrePortal system footprint (outside the data roots)
|
|
|
|
LibrePortal's own data lives in **three independently-relocatable roots**, chosen
|
|
at install (defaults shown) and owned by exactly one principal each:
|
|
|
|
| Root (default) | Owner | Holds |
|
|
|---|---|---|
|
|
| `/libreportal-system` | the manager user | configs, logs, the install tree, the database, ssl/ssh |
|
|
| `/libreportal-containers` | the container user | live app data (one dir per app) |
|
|
| `/libreportal-backups` | the container user | backup repositories |
|
|
|
|
This file catalogues the few things LibrePortal must place **outside** those roots
|
|
to integrate with the host. The OS dictates where most of these live — sudoers,
|
|
systemd units, sysctl, and `$PATH` entries can only be read from their fixed
|
|
locations, so they can't sit inside a relocatable root. What we control, we keep
|
|
together in **`/usr/local/lib/libreportal/`**; everything else is named
|
|
`libreportal*` so the whole footprint is greppable and removable.
|
|
|
|
> The three roots **and** the manager username are chosen at install and **baked**
|
|
> into the helpers / systemd unit / CLI wrapper below (sed placeholders, like the
|
|
> manager name has always been) — never read at runtime from a manager-writable
|
|
> config. That immutability is the privilege boundary: a root helper can't be
|
|
> redirected at, say, `/etc` by editing config. This footprint itself stays at
|
|
> **fixed** paths by design; only the data roots relocate.
|
|
|
|
## Executables — `/usr/local/lib/libreportal/` (root:root, our own dir)
|
|
|
|
| File | Owner | Purpose |
|
|
|------|-------|---------|
|
|
| `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-dns` | root | edit `/etc/resolv.conf` (nameservers) |
|
|
| `libreportal-ssh-access` | root | manage admin `authorized_keys` + sshd `PasswordAuthentication` |
|
|
| `libreportal-socket` | root | docker-socket read perms (type switcher) |
|
|
| `libreportal-svc` | root | generate/install the task-processor systemd unit |
|
|
| `libreportal-bininstall` | root | install the restic/kopia backup-engine binaries |
|
|
| `libreportal-appcfg` | root | rewrite AdGuard/CrowdSec/ownCloud config files |
|
|
|
|
These are the scoped-sudoers trust boundary: root-owned in a root-owned dir, so the
|
|
manager can `sudo` them but can't modify them. Each bakes the three roots + the
|
|
manager name at install. Source of truth: `scripts/system/` in the repo; installed
|
|
by `init.sh` → `initRootHelpers` (re-installed only on a reinstall, not by the
|
|
quick-deploy).
|
|
|
|
## OS-mandated locations (must live where the OS reads them)
|
|
|
|
| Path | Owner | Purpose |
|
|
|------|-------|---------|
|
|
| `/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/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-rootless.conf` | root | rootless sysctl settings + "rootless configured" marker |
|
|
|
|
## Third-party tools we install (not ours, conventional home)
|
|
|
|
`/usr/local/bin/{restic,kopia,ufw-docker,docker-compose}` — installed on demand
|
|
(restic/kopia via the `libreportal-bininstall` helper). `/usr/local/bin` is the
|
|
correct home for these; left under their own names.
|
|
|
|
## System users
|
|
|
|
The **manager** (default `libreportal`, configurable via `--manager-user=` /
|
|
`LP_MANAGER_USER`) and the **container user** (default `dockerinstall`, from
|
|
`CFG_DOCKER_INSTALL_USER`) — each with a home under `/home/`. The rootless daemon
|
|
config lives at `~<container-user>/.config/docker/daemon.json`.
|
|
|
|
## Uninstall sketch
|
|
|
|
`init.sh uninstall` does all of this; the sketch (with default roots/manager):
|
|
|
|
```
|
|
sudo systemctl disable --now libreportal.service
|
|
sudo rm -f /etc/systemd/system/libreportal.service /etc/sudoers.d/libreportal
|
|
sudo rm -f /etc/sysctl.d/99-libreportal-*.conf
|
|
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
|
|
# optional: the backup-engine binaries and the two users
|
|
```
|