4 Commits

Author SHA1 Message Date
librelad
179b895cac fix(backup): resolve docker_install_user for every CLI command
WebUI-driven commands (`setup finalize`, `backup`, restore) ran with an
empty $docker_install_user because cliInitialize only called
checkInstallTypeRequirement for the `app` category. The backup engine then
ran `sudo -E -u "" restic init`, which sudo rejects with a usage dump —
surfacing as "Failed to initialize Local disk" in the setup wizard.

Factor the user resolution out of checkInstallTypeRequirement into a
side-effect-free resolveDockerInstallUser (rooted -> sudo_user_name,
rootless -> CFG_DOCKER_INSTALL_USER, with fallbacks so it is never empty)
and call it at the cliInitialize chokepoint so all command categories get a
valid install user, not just app.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-23 12:33:19 +01:00
librelad
4ce0340ef8 refactor(backup): replace per-app cron stagger with task-queue scheduler
Application backups were driven by one crontab entry per app, each offset by
id * CFG_BACKUP_CRONTAB_APP_INTERVAL minutes. That minute offset is written
straight into cron's 0-59 minute field, so past ~20 apps it overflowed into
an invalid entry that silently never fired, and the fixed spacing could not
serialize backups that ran longer than the gap.

Replace it with a single daily entry (`libreportal backup scheduled`) that
enqueues a backup task per enabled app. The existing systemd task processor
drains them serially — no minute overflow, real serialization, and backups
are now visible/cancellable in the Tasks UI. Per-app enable is read from
CFG_<APP>_BACKUP at schedule time instead of being mirrored into crontab.

Removes the stagger machinery (timing/setup/check/remove scripts), the
now-unused cron_jobs table + insert, and the CFG_BACKUP_CRONTAB_APP_INTERVAL
config knob and its WebUI field.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-22 14:34:35 +01:00
librelad
d5fe1bc56b feat(webui): out-of-date detection + one-click update
Surface when LibrePortal is behind upstream and let users update from the
WebUI, reusing the proven git-update path instead of reinventing it.

Detection (host): webuiSystemUpdateCheck writes
frontend/data/system/update_status.json from a throttled git fetch +
behind-count + VERSION compare, off the existing per-minute
`webui generate system` cron. A new /VERSION file is the canonical version.

Display (frontend): update-notifier.js/.css render a global topbar badge
(every page) and a dashboard banner (prominent when behind, subtle "up to
date" with a manual check otherwise), plus a details panel.

Actions go through the task pipeline:
- `libreportal update apply` -> webuiRunUpdate (non-interactive: guards,
  forced check, gitPerformUpdate, then dockerInstallApp libreportal)
- `libreportal update check` -> forced recheck

gitFolderResetAndBackup's body is extracted into gitPerformUpdate (no exit)
so the WebUI path can reuse it; the interactive CLI flow is unchanged.

Detection JSON verified against the repo (up-to-date and behind cases).
webuiRunUpdate's re-clone + redeploy still needs validation on a live host.

The latest-version source is git for now and is the single swap point for
get.libreportal.org later — the JSON contract and frontend stay unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-21 23:33:43 +01:00
librelad
875a60f90f LibrePortal v0.1.0 — initial release
A free, open, self-hosted app platform (GNU AGPLv3): one-click app deploys,
Traefik reverse proxy with automatic SSL, rootless Docker support, gluetun
VPN routing, and a web dashboard to manage it all.

Free & open forever to self-host; optional paid hosted services fund it.
See PROMISE.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-21 20:37:54 +01:00