+ Global settings, WebUI login & backup-location credentials
+
+
+ Snapshot the LibrePortal system config to every enabled location so a bare-metal
+ restore is self-sufficient — without it, the credentials needed to reach your own
+ backups live only on this box. Runs automatically with “Backup all apps” too.
+
+
+
+
+
+
diff --git a/containers/libreportal/frontend/js/components/backup/backup-page.js b/containers/libreportal/frontend/js/components/backup/backup-page.js
index 6cb8fec..bc90606 100644
--- a/containers/libreportal/frontend/js/components/backup/backup-page.js
+++ b/containers/libreportal/frontend/js/components/backup/backup-page.js
@@ -176,6 +176,16 @@ class BackupPage {
return;
}
+ if (e.target.closest('[data-action="backup-system"]')) {
+ this.runBackupSystem();
+ return;
+ }
+
+ if (e.target.closest('[data-action="restore-system"]')) {
+ this.confirmRestoreSystem();
+ return;
+ }
+
const restoreBtn = e.target.closest('[data-action="restore-snapshot"]');
if (restoreBtn) {
this.openRestoreModal(restoreBtn.dataset.app, restoreBtn.dataset.loc, restoreBtn.dataset.snapshot);
@@ -1724,6 +1734,15 @@ class BackupPage {
await this.runTask(`libreportal backup all`, 'backup', null);
}
+ async runBackupSystem() {
+ await this.runTask(`libreportal backup system`, 'backup', null);
+ }
+
+ async confirmRestoreSystem() {
+ if (!confirm('Restore the latest system-config snapshot?\n\nIt is restored into a staging folder (not applied) — review it, then copy what you need (e.g. backup-location credentials, login, settings) into the live config. Your running config is NOT overwritten.')) return;
+ await this.runTask(`libreportal restore system`, 'restore', null);
+ }
+
async runTask(command, type, app) {
if (!this.taskManager) {
this.notify('Task system unavailable', 'error');