- Runner.pm: extract _validate()/_build_cmd_line(), add run_async() that
forks a detached child via setsid() to run commands in background
- restore.cgi: handle_step4() builds commands array and uses run_async()
instead of blocking synchronous execution, redirects to logs.cgi
- logs.cgi: add auto-refresh JS (10s list view, 5s file view with
auto-scroll) that polls index.cgi?action=status while gniza is running
- index.cgi: add live status card with AJAX polling and JSON endpoint
- Cron/schedule: redirect cron output to /dev/null (gniza has own logs)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add lib/sysbackup.sh and lib/sysrestore.sh for system-level
backup and restore of WHM/cPanel config, packages, and cron jobs
- Wire cmd_sysbackup and cmd_sysrestore into bin/gniza
- Add --sysbackup flag to cmd_backup: runs system backup after all
account backups complete
- Add SYSBACKUP schedule config key so cron jobs can include
--sysbackup automatically via build_cron_line()
- Add "Include system backup" toggle to WHM schedule form
- Revert sysbackup toggle from remotes.cgi (belongs in schedules)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
REMOTE_HOST, REMOTE_PORT, REMOTE_USER, REMOTE_BASE, BWLIMIT,
RETENTION_COUNT, and RSYNC_EXTRA_OPTS were referenced without
defaults in _save_remote_globals(), causing "unbound variable"
errors under set -u when called before any remote was loaded
(e.g., gniza remote list).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Send email via curl SMTP when SMTP_HOST is configured, falling back
to system mail/sendmail when empty. NOTIFY_EMAIL now accepts
comma-separated addresses. WHM Settings page gets an SMTP card
with Send Test Email button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full-featured cPanel backup tool with SSH, S3, and Google Drive support.
Includes WHM plugin with Tailwind/DaisyUI UI, multi-remote management,
decoupled schedules, and account restore workflows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>