--containers-dir has existed for a while and nobody running the curl|bash
installer ever learned it existed, so a box with a 4 TB disk beside a
small system SSD quietly put everything on the SSD. The installer now
asks, once, in the shape an OS installer asks it.
Deliberately narrow, because a question you answer badly is worse than no
question:
* app data only. The control plane is ~20 MB and never grows; the thing
worth placing is the data. Offering all three roots would be three
questions nobody can answer at that moment.
* a SUBDIRECTORY on the chosen disk, never its mount point — that keeps
the "root only ever takes an empty directory" rule intact and leaves
whatever is already on the disk alone.
* candidates exclude anything on the same filesystem as /, since placing
data there gains nothing.
It stays out of the way: skipped when unattended, when --containers-dir
was passed, when there is no TTY, and when the scan finds nothing else —
a prompt with one possible answer is not a question. Self-contained
(findmnt only), since scripts/ is not necessarily loadable that early.
Verified all six paths under a pty: default, valid pick, out-of-range,
non-numeric, no TTY, unattended, explicit flag, and no candidates.
Docs updated: the installer prompt is shown, and the section that said
locations are fixed after install now explains what actually is fixed
(the three roots) versus what isn't (per-app placement, storage add, and
CFG_STORAGE_DEFAULT).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
136 lines
5.1 KiB
Markdown
136 lines
5.1 KiB
Markdown
# LibrePortal — Install & Use
|
|
|
|
How to install, place, update, and remove LibrePortal. For building releases or
|
|
running a dev copy, see [development guide](../contributing/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 guide](../contributing/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)
|
|
|
|
**The installer just asks.** If it finds a second drive, it offers it for app
|
|
data before installing anything:
|
|
|
|
```
|
|
Where should app data live?
|
|
|
|
1) This disk (default) 911.9G 808.4G free
|
|
2) /mnt/bigdisk 3.6T 3.6T free
|
|
|
|
LibrePortal itself stays on this disk either way — only app data moves.
|
|
|
|
Choose [1]:
|
|
```
|
|
|
|
It picks a subdirectory on the drive you choose, never the mount point itself,
|
|
and skips the question entirely when there is nothing else to choose, when you
|
|
passed `--containers-dir`, or when running unattended.
|
|
|
|
The three roots below are still there for scripted installs:
|
|
|
|
| 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 three roots are chosen at install and fixed afterward — changing *them* is a
|
|
deliberate reinstall, not a setting, and that is part of the security model.
|
|
|
|
What is **not** fixed is where each app's data lives. You can register extra
|
|
drives at any time and place apps on them individually:
|
|
|
|
```bash
|
|
libreportal storage scan # what else could hold app data
|
|
libreportal storage add /mnt/bigdisk # register it (must be an empty directory)
|
|
libreportal app move nextcloud bigdisk
|
|
```
|
|
|
|
New apps follow `CFG_STORAGE_DEFAULT` (General → Basic), so one setting sends
|
|
everything to the big disk without touching each app. An app whose drive is not
|
|
mounted refuses to start rather than being rebuilt empty on the bare mount
|
|
point.
|
|
|
|
## 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).
|
|
|
|
Some releases carry a fix that an already-installed app only picks up on its next
|
|
install — see [upgrade notes](upgrade-notes.md) for the versions that need a
|
|
manual step.
|
|
|
|
## 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-uninstall
|
|
# keep the rootless Docker layer + image cache for a fast reinstall:
|
|
sudo libreportal-uninstall --skip-docker-images
|
|
```
|
|
|
|
`libreportal-uninstall` is a fixed command on `$PATH` (no data path to type — it
|
|
reads the real install locations from the installed service, so it works even with
|
|
custom roots). It removes the three roots, the system users, and the small
|
|
out-of-tree footprint (`/usr/local/lib/libreportal`, the `/etc` integration files).
|
|
|
|
> ⚠️ Uninstall permanently deletes all app data, configs, and the database. Take a
|
|
> backup first if you want to keep anything.
|