Commit Graph

172 Commits

Author SHA1 Message Date
shuki
2379c2fdeb Add Kill Job button to Running Tasks screen
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:10:19 +02:00
shuki
8a83812584 Add background jobs system with Running Tasks screen
Backup and restore operations now run as background jobs instead of
blocking modal screens. Users can navigate away and check progress
from a dedicated Running Tasks screen. OperationLog supports attaching
to running jobs with live output polling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:07:34 +02:00
shuki
18af43936c Treat rsync exit codes 23/24 as warnings, not failures
Exit 23 (partial transfer, permission denied) and 24 (vanished files)
are expected in non-root backups. These no longer trigger retries or
fail the backup — they log a warning and continue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:51:13 +02:00
shuki
3e4b906f7e Only create log files for backup/restore/retention commands
Utility commands (schedule, snapshots, remotes, etc.) were creating
empty 0 B log files on every invocation. Now init_logging only runs
for commands that produce meaningful log output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:48:14 +02:00
shuki
0b0204dada Format log filenames as readable date/time columns in logs screen
Show '2026-03-06' and '14:45:16' instead of 'gniza-20260306-144516.log'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:46:10 +02:00
shuki
f9f7ae6ad3 Format snapshot timestamps as readable dates in snapshots browser
Display '2026-03-06 14:07:06' instead of raw '2026-03-06T140706'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:42:41 +02:00
shuki
99774efe52 Show 'never' instead of '--' for empty last/next run in schedule table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:09:55 +02:00
shuki
feeea07b56 Fix cron backups failing due to minimal PATH environment
Cron runs with a very limited PATH that may not include sshpass, rsync,
etc. Add explicit PATH to generated cron lines and log output to
cron.log instead of /dev/null for debugging.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:07:14 +02:00
shuki
04044eda83 Fix installer exit when WEB_USER not found in config
grep returns exit 1 when no match, which with set -eo pipefail kills
the script. Add || true to the grep pipeline in credential extraction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:40:25 +02:00
shuki
5d8764ad25 Fix installer crash when enabling web dashboard as non-root user
The grep -v pipeline combined with set -eo pipefail caused the entire
installer to exit silently when the user answered "y" to web dashboard.
Replace with proper if/else and add user-level systemd service support
(systemctl --user) for non-root installs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:38:28 +02:00
shuki
e863d9a478 Fix shell injection in snapshot, retention, and restore remote_exec calls
Apply shquote() to all remaining remote_exec paths that interpolate
variables into single-quoted shell strings. Covers list/resolve/clean
snapshots, symlink updates, retention pruning, and restore file listing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 08:17:05 +02:00
shuki
63cc7f842e Fix security and correctness bugs found in code review
- Add shquote() to escape single quotes in paths passed to remote_exec,
  preventing shell injection via REMOTE_BASE containing single quotes
- Apply shquote to remote_exec calls in remotes.sh, backup.sh, transfer.sh, ssh.sh
- Add DISK_USAGE_THRESHOLD validation in config.sh
- Export SMTP_PASSWORD (was missing from export list)
- Fix WEB_PORT default mismatch: use 2323 consistently in from_conf and settings save
- Narrow exception catch in remotes.py disk info fetch to KeyError/LookupError
- Quote REMOTE_KEY in build_rsync_ssh_cmd for paths with spaces

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 08:13:20 +02:00
shuki
1c21e7a9df Update docs for include/exclude filters, MySQL, disk threshold, web dashboard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 08:01:14 +02:00
shuki
c68e93fc89 Fix disk info when remote base directory doesn't exist yet
Fall back to df / when REMOTE_BASE path doesn't exist on the remote.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:17:42 +02:00
shuki
0eb4dc00ed Fix remote_disk_info_short with robust df parsing
Parse df output locally using awk to find the % field and extract
the 3 size fields before it. Handles wrapped lines and CR chars.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:14:59 +02:00
shuki
ccae8451c3 Fix remote_disk_info_short — parse df on remote side
Move awk parsing to the remote to avoid SSH output encoding issues
that caused empty fields when parsing locally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:13:46 +02:00
shuki
279b05b5e4 Fix disk usage parsing — use grep instead of df --output
df --output=pcent is not available on all systems. Use grep -oP to
extract the percentage field from standard df output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:12:18 +02:00
shuki
604437bed2 Fix remote disk usage check returning empty percentage
Use df --output=pcent for reliable single-column output instead of
parsing multi-column df output through awk over SSH.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:11:18 +02:00
shuki
590b87843d Add configurable disk usage threshold setting
Disk usage threshold (default 95%) can now be controlled from
Settings. Set to 0 to disable the check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:08:42 +02:00
shuki
993a66d8c6 Add include/exclude filter support and disk space pre-check
- Add TARGET_INCLUDE field for rsync include patterns (comma-separated)
- Pass TARGET_INCLUDE and TARGET_EXCLUDE to rsync in transfer_folder
- Include mode uses --include='*/' + patterns + --exclude='*' + --prune-empty-dirs
- Abort backup if remote disk usage >= 95%

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:04:52 +02:00
shuki
eb9dda416b Remove Speed Test and Disk Info buttons from remotes screen
Disk info is now shown directly in the table. Speed test and detailed
disk info buttons/commands are no longer needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:47:05 +02:00
shuki
8b3d6ede4f Show disk usage in remotes table with async loading
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:44:27 +02:00
shuki
c70fb1991c Add Disk Info and Speed Test buttons to Remotes screen
- Disk Info: runs df -h and df -i on remote via SSH (or locally)
- Speed Test: uploads/downloads 10MB test file via rsync, measures Mbps
- Both available as CLI commands: gniza remotes disk-info/speed-test --name=NAME

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:38:15 +02:00
shuki
f7c5836db0 Show system clock in top right corner of all screens
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:35:51 +02:00
shuki
5c1fa04657 Add Last Run and Next Run columns to Schedules screen
- Last Run: timestamp of most recent backup log file
- Next Run: calculated from schedule type, time, and day settings
- Handles hourly, daily, weekly, monthly schedule types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:31:49 +02:00
shuki
220d30e515 Change default web port from 8080 to 2323
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:27:16 +02:00
shuki
907c77feb4 Remove username prompt, default to admin (configurable in gniza.conf)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:26:16 +02:00
shuki
343b49d245 Move web credentials to post-install summary section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:25:08 +02:00
shuki
a7c50e4b0b Always regenerate web credentials on install, prompt for username
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:21:03 +02:00
shuki
ebe5645fb9 Fix auth middleware: use insert(0) on FrozenList before app starts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:18:05 +02:00
shuki
1800babbc2 Add HTTP Basic Auth to textual-serve web dashboard
Browser prompts for username/password before showing the TUI.
Credentials from gniza.conf: WEB_USER (default: admin) + WEB_API_KEY.

- Monkey-patches textual-serve's aiohttp app with auth middleware
- Uses secrets.compare_digest for timing-safe comparison
- Install script generates credentials and prints them
- Skips auth if no WEB_API_KEY configured

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:14:51 +02:00
shuki
fa7eb14369 Fix textual-serve web: robust IP detection for WebSocket URL
The landing page wasn't interactive because public_url resolved to
localhost, making WebSocket connections fail from remote browsers.

- Added multiple IP detection methods (socket, hostname -I, gethostbyname)
- Support --port= and --host= flag formats
- Print actual serving URL on startup
- Switch web start back to textual-serve (TUI in browser)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:12:29 +02:00
shuki
133ae1e7a4 Restore Flask dashboard with redesigned UI and API key auth
- Revert from textual-serve back to Flask (textual-serve had WebSocket issues)
- Completely redesigned dashboard: modern dark theme, stat cards, clean tables
- Redesigned login page to match
- Restored API key generation in install script
- Keep API key field in TUI settings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:09:39 +02:00
shuki
1a24371446 Replace Flask web dashboard with textual-serve
Serves the exact same TUI in the browser via textual-serve.
No more separate Flask app, API keys, or login page needed.

- gniza web start now runs textual-serve instead of Flask
- Simplified systemd service to use python3 -m tui --web
- Removed web_enabled and web_api_key from settings/models
- Simplified install script web setup (no API key generation)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:05:29 +02:00
shuki
97918f259e Read web dashboard prompt from /dev/tty for curl|bash support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 06:01:00 +02:00
shuki
3464a0d19f Fix web dashboard config path and install script robustness
- Fix GNIZA_CONFIG_DIR in systemd service: /usr/local/gniza/etc -> /etc/gniza
- Add LOG_DIR and PYTHONPATH to systemd environment
- Fix default CONFIG_DIR in web/app.py and web/__main__.py
- Refactor install.sh web setup into function for robustness
- Replace Unicode box-drawing chars with ASCII in install.sh
- Read from /dev/tty to prevent stdin issues

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:55:33 +02:00
shuki
a868143eca Fix install web setup: use if/else instead of grep&&sed||echo chain
The && || chain with set -e caused syntax errors on some systems.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:44:48 +02:00
shuki
0bce1bc194 Simplify install web setup for maximum bash compatibility
Use POSIX [ ] tests instead of [[ ]], avoid case statement,
replace em-dash with ASCII, use simple if/then/fi structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:43:52 +02:00
shuki
29948d454a Fix install script web setup to avoid bash compatibility issues
Replace nested if/fi with case statement and inline sed calls
instead of helper function. Add error handling for service install.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:42:55 +02:00
shuki
ea3533ac49 Fix web login: use consistent API key instead of re-reading config
The login handler was re-reading the config on each attempt, which
returned empty when no key was set, causing all logins to fail.
Now uses the key resolved at startup (from config or generated).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:40:39 +02:00
shuki
cf00ecdd4b Add web dashboard with systemd service support
- Flask web dashboard with dark theme matching TUI
- Login with API key authentication
- Dashboard shows targets, remotes, schedules, last backup status
- Trigger backups from web UI per target
- View logs via /api/logs endpoint
- systemd service: gniza web install-service / remove-service / status
- CLI: gniza web start [--port=PORT] [--host=HOST]
- TUI settings: web enabled, port, host, API key fields
- Install script: optional web dashboard setup with auto-generated API key
- Uninstall script: removes systemd service

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:34:02 +02:00
shuki
0d5977ab22 Rename Snapshots to Snapshots Browser in main menu
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:15:37 +02:00
shuki
d32f98a8c1 Rename screen title to Snapshots Browser
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:14:16 +02:00
shuki
011a2cee8c Start snapshot browser tree collapsed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:13:04 +02:00
shuki
5b4bf33520 Add tree-based file browser for snapshot contents
Replace flat file list with a Tree widget that shows directory
structure. Strips remote path prefix to show relative paths only.
Folders shown in bold with trailing /, sorted dirs-first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:11:53 +02:00
shuki
98fc263a40 Fix snapshot selection using row key instead of get_cell
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:09:49 +02:00
shuki
e73f38df53 Add Browse Files button to snapshots screen
Select a snapshot and click Browse Files to see all files in that
snapshot on the remote. Also adds 'gniza snapshots browse' CLI command.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:08:45 +02:00
shuki
d6032d2547 Remove Retention from main menu
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:06:36 +02:00
shuki
152ef61734 Fix menu separator for older Textual versions
Use None separator instead of Separator class which isn't available
in older Textual.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:04:30 +02:00
shuki
3ac1d77e47 Add separator after Restore in main menu
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 05:03:53 +02:00