Merge claude/1

This commit is contained in:
librelad 2026-05-25 18:27:59 +01:00
commit 846936617e
4 changed files with 240 additions and 3 deletions

1
.gitattributes vendored
View File

@ -4,6 +4,7 @@
scripts/unused export-ignore scripts/unused export-ignore
scripts/release export-ignore scripts/release export-ignore
site export-ignore site export-ignore
docs export-ignore
.claude export-ignore .claude export-ignore
.gitignore export-ignore .gitignore export-ignore
.gitattributes export-ignore .gitattributes export-ignore

View File

@ -34,11 +34,22 @@ telemetry. See [our Promise](PROMISE.md) for exactly what that means.
## Quick start ## Quick start
```bash ```bash
git clone https://gitea.scottwebstar.co.uk/Webstar/LibrePortal.git curl -fsSL https://get.libreportal.org/install.sh | sudo bash
cd LibrePortal
./init.sh
``` ```
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) ## LibrePortal Connect (optional)
Self-hosting is free and complete. If you'd rather not fiddle with the tricky Self-hosting is free and complete. If you'd rather not fiddle with the tricky

128
docs/DEVELOPMENT.md Normal file
View 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
View 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.