docs: add docs/USER.md + docs/DEVELOPMENT.md (+ README pointer)
Two guides covering what wasn't written down:
- USER.md: install (the install.sh one-liner), placing the three roots on separate
disks/external drives, channels, updating, backups (REQUIRE_MOUNT), uninstall.
- DEVELOPMENT.md: the install-mode/roots/users model + key files; running a dev copy
(local/git); cutting stable/edge releases (bump VERSION -> make_release.sh ->
dist/<channel>/{tarball,.sha256,latest.json} -> publish); testing a release
locally via LP_RELEASE_BASE_URL + python3 -m http.server (incl. checksum-refusal);
how release updates work; conventions.
README Quick start updated to the release flow + a docs pointer. docs/ is
export-ignored so it doesn't bloat release tarballs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
89049864a6
commit
a48a241fbe
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -4,6 +4,7 @@
|
||||
scripts/unused export-ignore
|
||||
scripts/release export-ignore
|
||||
site export-ignore
|
||||
docs export-ignore
|
||||
.claude export-ignore
|
||||
.gitignore export-ignore
|
||||
.gitattributes export-ignore
|
||||
|
||||
17
README.md
17
README.md
@ -34,11 +34,22 @@ telemetry. See [our Promise](PROMISE.md) for exactly what that means.
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
git clone https://gitea.scottwebstar.co.uk/Webstar/LibrePortal.git
|
||||
cd LibrePortal
|
||||
./init.sh
|
||||
curl -fsSL https://get.libreportal.org/install.sh | sudo bash
|
||||
```
|
||||
|
||||
This installs a versioned, checksum-verified release (Debian/Ubuntu, root). Put
|
||||
data on separate disks with `--system-dir=` / `--containers-dir=` / `--backups-dir=`.
|
||||
|
||||
> The `get.libreportal.org` host is still being set up — until it's live, build a
|
||||
> release and install from it locally (see the docs below).
|
||||
|
||||
## Documentation
|
||||
|
||||
- **[docs/USER.md](docs/USER.md)** — install, place data on separate disks/drives,
|
||||
update, back up, uninstall.
|
||||
- **[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md)** — run a dev copy, cut stable/edge
|
||||
releases, and test them before publishing.
|
||||
|
||||
## LibrePortal Connect (optional)
|
||||
|
||||
Self-hosting is free and complete. If you'd rather not fiddle with the tricky
|
||||
|
||||
128
docs/DEVELOPMENT.md
Normal file
128
docs/DEVELOPMENT.md
Normal file
@ -0,0 +1,128 @@
|
||||
# LibrePortal — Development & Releases
|
||||
|
||||
How to run a development copy, cut stable/edge releases, and test them before they
|
||||
go out. For installing/using LibrePortal, see [USER.md](USER.md).
|
||||
|
||||
## Mental model (read this first)
|
||||
|
||||
**Install modes** — `CFG_INSTALL_MODE` decides where the code comes from:
|
||||
|
||||
| Mode | Source | Use |
|
||||
|---|---|---|
|
||||
| `release` (default) | a checksum-verified `.tar.gz` over HTTPS | end users / stable |
|
||||
| `git` | `git clone` of the repo | contributors tracking a branch |
|
||||
| `local` | a copy of a local folder | hacking on the code on the box |
|
||||
|
||||
**Three roots** (each relocatable at install, then fixed):
|
||||
`<system>` (manager-owned: configs/db/logs/install) · `<containers>` (container
|
||||
user: app data) · `<backups>` (container user: repos). Defaults `/libreportal-*`.
|
||||
|
||||
**Two users:** the **manager** (`sudo_user_name`, default `libreportal`) owns the
|
||||
control plane and runs the runtime; the **container user** (`CFG_DOCKER_INSTALL_USER`,
|
||||
default `dockerinstall`) owns app data + runs rootless Docker. Genuine-root actions
|
||||
go through fixed, root-owned helpers in `/usr/local/lib/libreportal/` (paths +
|
||||
manager name are *baked* into them at install — never read from runtime config).
|
||||
|
||||
**Key files:**
|
||||
- `init.sh` — the installer (self-contained; creates users/folders/helpers, bakes things).
|
||||
- `install.sh` — the thin bootstrap (download+verify+extract a release, then run init.sh).
|
||||
- `scripts/source/paths.sh` — resolves the three roots + manager user.
|
||||
- `scripts/source/fetch.sh` — `lpFetchRelease` / `lpVersionGt` (runtime fetch + version compare).
|
||||
- `scripts/release/make_release.sh` — builds release artifacts.
|
||||
- `VERSION` — the single source of the version number.
|
||||
|
||||
## Run a development copy
|
||||
|
||||
From a clone of the repo, on a **throwaway Debian/Ubuntu host** (install is
|
||||
destructive — it creates system users and dirs):
|
||||
|
||||
**Local mode** (install from the working tree — best for hacking):
|
||||
```bash
|
||||
sudo ./init.sh --random-password --local init
|
||||
# custom locations work in dev too:
|
||||
sudo ./init.sh --random-password --local --system-dir=/srv/lp --manager-user=lpadmin init
|
||||
```
|
||||
|
||||
**Git mode** (track a branch):
|
||||
```bash
|
||||
# via the bootstrap:
|
||||
sudo ./install.sh --git-url=https://example.com/you/LibrePortal.git \
|
||||
--git-user=USER --git-token=TOKEN
|
||||
# or directly: ./init.sh init <password> <git_user> <git_token> <git_url> true git
|
||||
```
|
||||
|
||||
**Iterating:** re-run the installer to redeploy after changes (local mode re-copies
|
||||
the tree). To wipe and start over:
|
||||
```bash
|
||||
sudo ./init.sh uninstall # removes the three roots + users + footprint
|
||||
sudo ./init.sh --skip-docker-images uninstall # keep the Docker layer for a fast reinstall
|
||||
```
|
||||
|
||||
> This repo's CI/hook setup may auto-deploy on commit (commit on a branch →
|
||||
> auto-merge → redeploy). That's environment-specific; the commands above are the
|
||||
> portable way to stand up and refresh a dev box.
|
||||
|
||||
## Cut a release (stable or edge)
|
||||
|
||||
1. **Bump the version** in `VERSION` (semver, e.g. `0.2.0` → `0.3.0`). Commit it.
|
||||
2. **Build the artifact** (uses `git archive`, so it ships only committed files and
|
||||
honours `.gitattributes export-ignore` — `scripts/unused`, `site`, `docs`,
|
||||
`.claude`, the release tooling, etc. never ship):
|
||||
```bash
|
||||
scripts/release/make_release.sh stable # or: edge [git-ref]
|
||||
```
|
||||
Produces, under `dist/<channel>/`:
|
||||
- `libreportal-<version>.tar.gz` — the release
|
||||
- `libreportal-<version>.tar.gz.sha256` — its checksum
|
||||
- `latest.json` — `{ version, channel, url, sha256, notes }` (the channel pointer)
|
||||
3. **Publish** by copying `dist/<channel>/*` to the host so they're served at
|
||||
`https://get.libreportal.org/<channel>/…` (Phase E — the `getlibreportal`
|
||||
container; not built yet). `latest.json` is what makes a version "the latest".
|
||||
|
||||
**Channels:** `stable` is the default users get; `edge` is for early/testing
|
||||
builds. Same tooling, different `<channel>`. To promote an edge build to stable,
|
||||
rebuild with `make_release.sh stable` at that ref (or copy its artifacts into the
|
||||
`stable/` path and update `stable/latest.json`).
|
||||
|
||||
## Test a release locally before publishing
|
||||
|
||||
No hosting needed — serve `dist/` and point an install at it:
|
||||
|
||||
```bash
|
||||
# build, then serve the artifacts
|
||||
scripts/release/make_release.sh stable
|
||||
( cd dist && python3 -m http.server 8000 )
|
||||
|
||||
# on a throwaway host, install from your local server:
|
||||
LP_RELEASE_BASE_URL=http://<your-ip>:8000 \
|
||||
sudo ./install.sh --channel=stable --system-dir=/libreportal-system
|
||||
```
|
||||
|
||||
`LP_RELEASE_BASE_URL` overrides the release host everywhere (installer, updater,
|
||||
recovery). Quick non-destructive checks:
|
||||
|
||||
```bash
|
||||
# fetch + verify + stage only (no install):
|
||||
LP_RELEASE_BASE_URL=http://<ip>:8000 ./install.sh --dry-run
|
||||
# tamper with the tarball and confirm it's refused:
|
||||
echo x >> dist/stable/libreportal-*.tar.gz
|
||||
LP_RELEASE_BASE_URL=http://<ip>:8000 ./install.sh --dry-run # => CHECKSUM MISMATCH
|
||||
```
|
||||
|
||||
## How updates work (so you can reason about them)
|
||||
|
||||
In `release` mode the WebUI badge + `libreportal update apply` compare the local
|
||||
`VERSION` against the channel's `latest.json` (`lpVersionGt`); if newer, they
|
||||
`lpFetchRelease` the new tarball (verified) and redeploy. Because the install tree
|
||||
is *code only* (configs/logs/backups live in the other roots), the update just
|
||||
replaces it — no backup/restore dance. `git`/`local` modes keep their existing
|
||||
git-based update path.
|
||||
|
||||
## Conventions
|
||||
|
||||
- **Versioning:** semver in `VERSION`. Bump before building; `latest.json` carries it.
|
||||
- **New runtime script?** Add it under `scripts/<area>/…` and run
|
||||
`scripts/source/files/generate_arrays.sh run` so it's sourced (build/standalone
|
||||
tooling under `scripts/release` and `scripts/system` is intentionally excluded).
|
||||
- **Don't** make the OS footprint (`/etc/*`, `/usr/local/*`) relocatable — it's
|
||||
fixed by design for the privilege model.
|
||||
97
docs/USER.md
Normal file
97
docs/USER.md
Normal file
@ -0,0 +1,97 @@
|
||||
# LibrePortal — Install & Use
|
||||
|
||||
How to install, place, update, and remove LibrePortal. For building releases or
|
||||
running a dev copy, see [DEVELOPMENT.md](DEVELOPMENT.md).
|
||||
|
||||
> **Note:** the `get.libreportal.org` host isn't live yet. Until it is, install
|
||||
> from a local release artifact or a git/local checkout — see
|
||||
> [DEVELOPMENT.md](DEVELOPMENT.md). The commands below are the intended public flow.
|
||||
|
||||
## Requirements
|
||||
|
||||
- A **Debian** or **Ubuntu** host.
|
||||
- **root** (run with `sudo`).
|
||||
- `curl` (or `wget`) and `tar`.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
curl -fsSL https://get.libreportal.org/install.sh | sudo bash
|
||||
```
|
||||
|
||||
This downloads a versioned, **checksum-verified** release tarball (no git, no
|
||||
login), installs LibrePortal, and prints the WebUI address + a generated password
|
||||
(also saved to the install log). To choose the password yourself add
|
||||
`--password=…`.
|
||||
|
||||
### Put data where you want it (separate disks, external drives)
|
||||
|
||||
LibrePortal uses **three independent roots**, each can be its own path/disk:
|
||||
|
||||
| Flag (default) | Holds | Owner |
|
||||
|---|---|---|
|
||||
| `--system-dir=/libreportal-system` | configs, database, logs, install | the manager user |
|
||||
| `--containers-dir=/libreportal-containers` | live app data | the container user |
|
||||
| `--backups-dir=/libreportal-backups` | backup repositories | the container user |
|
||||
|
||||
```bash
|
||||
curl -fsSL https://get.libreportal.org/install.sh | sudo bash -s -- \
|
||||
--system-dir=/mnt/ssd/libreportal \
|
||||
--containers-dir=/mnt/ssd/libreportal-apps \
|
||||
--backups-dir=/mnt/bigdisk/libreportal-backups
|
||||
```
|
||||
|
||||
Notes:
|
||||
- Defaults are top-level dirs on purpose — they avoid the permission/encryption
|
||||
pitfalls of living inside a user's home. To put `containers`/`backups` inside
|
||||
`/home/<user>` you must add `--allow-home` (it needs the container user to
|
||||
traverse that home — a small privacy trade-off).
|
||||
- Other flags: `--manager-user=NAME` (default `libreportal`),
|
||||
`--channel=stable|edge` (default `stable`), `--version=X.Y.Z` (pin a version).
|
||||
|
||||
## Where things end up
|
||||
|
||||
```
|
||||
<system-dir>/ configs/ logs/ install/ database.db ssl/ ssh/
|
||||
<containers-dir>/ one folder per installed app (+ the libreportal WebUI)
|
||||
<backups-dir>/ one folder per backup location
|
||||
```
|
||||
|
||||
The locations are chosen at install and fixed afterward (changing them is a
|
||||
deliberate reinstall, not a setting — this is part of the security model).
|
||||
|
||||
## Update
|
||||
|
||||
LibrePortal checks its channel for a newer version and shows a badge in the WebUI
|
||||
when one is available. Apply it from the dashboard, or on the host:
|
||||
|
||||
```bash
|
||||
libreportal update apply # update now if a newer version exists
|
||||
libreportal update check # just re-check the channel
|
||||
```
|
||||
|
||||
Updates download + verify the new release tarball and redeploy. Your data,
|
||||
configs, and backups are untouched (they live outside the replaced install tree).
|
||||
|
||||
## Backups on an external / removable drive
|
||||
|
||||
Point a backup location at the drive's mount path. For a removable disk, set
|
||||
**Require Mounted Drive** on the location (config key
|
||||
`CFG_BACKUP_LOC_<n>_REQUIRE_MOUNT=true`): LibrePortal then **refuses to back up
|
||||
when the drive isn't mounted**, so an unplugged disk never silently fills your
|
||||
system disk. Use a Linux filesystem (ext4/xfs/btrfs) — FAT/exFAT/NTFS can't hold
|
||||
the required ownership and will warn.
|
||||
|
||||
## Uninstall
|
||||
|
||||
```bash
|
||||
sudo /libreportal-system/install/init.sh uninstall
|
||||
```
|
||||
|
||||
This removes the three roots, the system users, and the small out-of-tree
|
||||
footprint (`/usr/local/lib/libreportal`, the `/etc` integration files). Add
|
||||
`--skip-docker-images` to keep the rootless Docker layer + image cache for a fast
|
||||
reinstall.
|
||||
|
||||
> ⚠️ Uninstall permanently deletes all app data, configs, and the database. Take a
|
||||
> backup first if you want to keep anything.
|
||||
Loading…
x
Reference in New Issue
Block a user