docs: move dev/reference docs into docs/ + refresh FOOTPRINT for the 3-root layout
Tidy the repo root (README + LICENSE stay there per convention; everything else moves): - CONTRIBUTING.md, PROMISE.md, FOOTPRINT.md -> docs/ (alongside USER.md/DEVELOPMENT.md) - update the references: README links, the website site.json raw URLs, init.sh's 'see FOOTPRINT.md' comments -> docs/FOOTPRINT.md; drop the now-redundant CONTRIBUTING.md export-ignore (docs/ is already export-ignored). Refresh FOOTPRINT.md: it claimed 'everything lives under /docker', which is no longer true. Now describes the three relocatable roots (system/containers/backups) and makes explicit that the roots + manager name are baked into the helpers/unit/ wrapper at install (the privilege boundary) while this out-of-root footprint stays fixed by design. Uninstall sketch + sudoers/unit rows updated for the configurable manager. CONTRIBUTING/PROMISE were already current — left as-is. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
846936617e
commit
40aa6d9d1a
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -8,4 +8,3 @@ docs export-ignore
|
|||||||
.claude export-ignore
|
.claude export-ignore
|
||||||
.gitignore export-ignore
|
.gitignore export-ignore
|
||||||
.gitattributes export-ignore
|
.gitattributes export-ignore
|
||||||
CONTRIBUTING.md export-ignore
|
|
||||||
|
|||||||
59
FOOTPRINT.md
59
FOOTPRINT.md
@ -1,59 +0,0 @@
|
|||||||
# LibrePortal system footprint (outside `/docker`)
|
|
||||||
|
|
||||||
Everything LibrePortal *is* lives under `/docker` (app data, configs, the install
|
|
||||||
tree, the database). This file catalogues the few things it must place **outside**
|
|
||||||
`/docker` 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 all sit in one folder. What we control, we keep
|
|
||||||
together in **`/usr/local/lib/libreportal/`**; everything else is named
|
|
||||||
`libreportal*` so the whole footprint is greppable and removable.
|
|
||||||
|
|
||||||
## Executables — `/usr/local/lib/libreportal/` (root:root, our own dir)
|
|
||||||
|
|
||||||
| File | Owner | Purpose |
|
|
||||||
|------|-------|---------|
|
|
||||||
| `libreportal` | root | the CLI wrapper (symlinked onto `$PATH`, see below) |
|
|
||||||
| `libreportal-ownership` | root | reconcile the `/docker` 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. 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`) |
|
|
||||||
| `/etc/sudoers.d/libreportal` | root | scoped least-privilege grant for the manager |
|
|
||||||
| `/etc/systemd/system/libreportal.service` | root | the task-processor service (`User=libreportal`) |
|
|
||||||
| `/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
|
|
||||||
|
|
||||||
`libreportal` (the manager) and `dockerinstall` (the rootless docker user), each
|
|
||||||
with a home under `/home/`. The rootless daemon config lives at
|
|
||||||
`~dockerinstall/.config/docker/daemon.json`.
|
|
||||||
|
|
||||||
## Uninstall sketch
|
|
||||||
|
|
||||||
```
|
|
||||||
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
|
|
||||||
# optional: the backup-engine binaries, the users, and /docker itself
|
|
||||||
```
|
|
||||||
@ -21,7 +21,7 @@ toggle — it's the whole point.
|
|||||||
|
|
||||||
The entire platform is **free software under the [GNU AGPLv3](LICENSE)**.
|
The entire platform is **free software under the [GNU AGPLv3](LICENSE)**.
|
||||||
Self-host it and you get **everything** — every feature, no paywalls, no
|
Self-host it and you get **everything** — every feature, no paywalls, no
|
||||||
telemetry. See [our Promise](PROMISE.md) for exactly what that means.
|
telemetry. See [our Promise](docs/PROMISE.md) for exactly what that means.
|
||||||
|
|
||||||
## What you get
|
## What you get
|
||||||
|
|
||||||
@ -59,11 +59,11 @@ different: we work like a **courier carrying a sealed box.** We move your data
|
|||||||
between your devices and store backup copies, but it stays locked and *you*
|
between your devices and store backup copies, but it stays locked and *you*
|
||||||
hold the only key — we can't open it, and we never run your apps for you.
|
hold the only key — we can't open it, and we never run your apps for you.
|
||||||
**Everything we offer, you can also set up yourself for free.**
|
**Everything we offer, you can also set up yourself for free.**
|
||||||
[Our Promise](PROMISE.md) spells out exactly where that line sits.
|
[Our Promise](docs/PROMISE.md) spells out exactly where that line sits.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). We use a lightweight
|
PRs welcome — see [CONTRIBUTING.md](docs/CONTRIBUTING.md). We use a lightweight
|
||||||
DCO sign-off (`git commit -s`), no CLA.
|
DCO sign-off (`git commit -s`), no CLA.
|
||||||
|
|
||||||
## Acknowledgments
|
## Acknowledgments
|
||||||
|
|||||||
79
docs/FOOTPRINT.md
Normal file
79
docs/FOOTPRINT.md
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# 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) |
|
||||||
|
| `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`) |
|
||||||
|
| `/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
|
||||||
|
sudo rm -rf /libreportal-system /libreportal-containers /libreportal-backups
|
||||||
|
# optional: the backup-engine binaries and the two users
|
||||||
|
```
|
||||||
6
init.sh
6
init.sh
@ -858,7 +858,7 @@ initUsers()
|
|||||||
# op the manager can't modify), and a fixed system-binary set. Excluded:
|
# op the manager can't modify), and a fixed system-binary set. Excluded:
|
||||||
# bash/su + tee/cp/chmod/chown/sed/mv/rm/install (each root-equivalent). Also
|
# bash/su + tee/cp/chmod/chown/sed/mv/rm/install (each root-equivalent). Also
|
||||||
# clears legacy broad grants (a NOPASSWD: ALL in the main /etc/sudoers, sudo-group
|
# clears legacy broad grants (a NOPASSWD: ALL in the main /etc/sudoers, sudo-group
|
||||||
# membership). See FOOTPRINT.md.
|
# membership). See docs/FOOTPRINT.md.
|
||||||
initScopedSudoers()
|
initScopedSudoers()
|
||||||
{
|
{
|
||||||
local sudoers_dropin="/etc/sudoers.d/${sudo_user_name}"
|
local sudoers_dropin="/etc/sudoers.d/${sudo_user_name}"
|
||||||
@ -1544,7 +1544,7 @@ completeInitMessage()
|
|||||||
# containers run AS the docker-install user and the rootless daemon is that user's
|
# containers run AS the docker-install user and the rootless daemon is that user's
|
||||||
# systemd --user service, so stop those BEFORE removing the users. Self-contained:
|
# systemd --user service, so stop those BEFORE removing the users. Self-contained:
|
||||||
# uses only init.sh's inline helpers, so it still works as it deletes /docker.
|
# uses only init.sh's inline helpers, so it still works as it deletes /docker.
|
||||||
# Keep in sync with FOOTPRINT.md.
|
# Keep in sync with docs/FOOTPRINT.md.
|
||||||
runFullUninstall()
|
runFullUninstall()
|
||||||
{
|
{
|
||||||
local mgr="${sudo_user_name:-libreportal}"
|
local mgr="${sudo_user_name:-libreportal}"
|
||||||
@ -1618,7 +1618,7 @@ runFullUninstall()
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 3. Remove the out-of-/docker footprint (see 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
|
||||||
rm -rf /usr/local/lib/libreportal
|
rm -rf /usr/local/lib/libreportal
|
||||||
rm -f "/etc/sudoers.d/$mgr"
|
rm -f "/etc/sudoers.d/$mgr"
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
"installUrl": "https://get.libreportal.org",
|
"installUrl": "https://get.libreportal.org",
|
||||||
"installCmd": "bash <(curl -fsSL https://get.libreportal.org) init",
|
"installCmd": "bash <(curl -fsSL https://get.libreportal.org) init",
|
||||||
"repo": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal",
|
"repo": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal",
|
||||||
"promiseUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/PROMISE.md",
|
"promiseUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/docs/PROMISE.md",
|
||||||
"contributingUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/CONTRIBUTING.md",
|
"contributingUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/docs/CONTRIBUTING.md",
|
||||||
"initUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/init.sh",
|
"initUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/init.sh",
|
||||||
"inspiration": "https://gitlab.com/bmcgonag/docker_installs"
|
"inspiration": "https://gitlab.com/bmcgonag/docker_installs"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user