Extends the install-routing spike (e5273a4) to every long-running CLI
command, so CLI and WebUI now share one execution path everywhere:
app install ← already done
app uninstall
app start / stop / restart / up / down / reload
app backup
app restore
update apply
backup app create (matches `app backup` — same end target)
Each handler now has the same shape:
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
<inline call> # processor's recursive invocation
else
cliTaskRun "<cmd>" <type> <app> # user invocation: enqueue + follow
fi
Processor change — crontab_task_processor.sh:
Adds `export LIBREPORTAL_TASK_EXEC=1` next to LIBREPORTAL_NONINTERACTIVE.
Universal bypass: every task command the processor runs (CLI-queued OR
pre-existing WebUI-queued like `libreportal app install adguard`)
inherits the env var, so the inline branch fires and we never
re-enqueue. This also lets us drop the env-var prefix the install spike
was baking into the command string (e5273a4) — cleaner task files +
one place to think about the bypass.
`backup app schedule` (the cron-driven path that already enqueues via
createTaskFile in backup_app_schedule.sh) is left alone — different
entry point, different runtime context, already correctly task-routed.
Why route the fast ones too (start/stop/restart/up/down):
Consistency beats the ~1s task-roundtrip latency for a CLI button.
Locking now serialises a CLI `app stop foo` against a WebUI restart of
the same app; the audit trail covers every state change. Cheap to
revert any individually if the latency turns out to bother someone.
Validated live earlier with `libreportal app install dashy` — task file
written, processor dispatched, follower streamed install live, exit 0
propagated. Same machinery now powers the other 9 handlers.
Signed-off-by: librelad <librelad@digitalangels.vip>
Expose the system-config backup on demand (not just within 'backup all'):
- `libreportal backup system` -> backupSystemConfig (snapshot the system
config — settings, WebUI creds, backup-location creds — to all enabled locations)
- `libreportal restore system [loc_idx]` -> backupRestoreSystemConfig (restore the
latest system snapshot into a staging dir; never overwrites live config)
Distinct from the existing 'restore migrate system' (which restores all *apps*
from another host). Help text updated for both. Routing verified with stubs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
Expose the existing location_ssh.sh key store through the backup CLI:
'backup location ssh-key-set|ssh-key-generate|ssh-key-public|ssh-key-delete <idx>'
(the WebUI runs these as tasks). The locations generator now emits
ssh_key_exists + ssh_public_key (public key only — the private key never
leaves the per-location ssh.key file), so the editor can show the key state.
Also fix the stale SSH_AUTH label (~/.ssh/id_rsa -> managed per-location key).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
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>
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>