Update documentation and features
This commit is contained in:
105
DOCUMENTATION.md
105
DOCUMENTATION.md
@@ -23,6 +23,7 @@ Complete reference for gniza, a Linux backup manager that works as a stand-alone
|
||||
- [CLI Reference](#cli-reference)
|
||||
- [Global Settings](#global-settings)
|
||||
- [Security](#security)
|
||||
- [Development](#development)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
@@ -647,9 +648,19 @@ gniza --cli schedule remove
|
||||
|
||||
Cron entries are tagged with `# gniza4linux:<name>` for clean management. Running `schedule install` replaces existing entries cleanly.
|
||||
|
||||
### How Scheduled Backups Run
|
||||
|
||||
Each cron entry calls `gniza scheduled-run --schedule=<name>`. This internal command:
|
||||
|
||||
1. Reads the schedule config to determine which sources and destinations to back up.
|
||||
2. Runs the backup (same as `gniza --cli backup`).
|
||||
3. On success, stamps `LAST_RUN="YYYY-MM-DD HH:MM"` in the schedule config file.
|
||||
|
||||
The `LAST_RUN` timestamp is displayed in the Schedules screen of the TUI.
|
||||
|
||||
### Cron Logs
|
||||
|
||||
Scheduled backups log output to `<log_dir>/cron.log`.
|
||||
Scheduled backups log output to `<log_dir>/cron.log`. Each run also creates a timestamped log file in the log directory (using local time).
|
||||
|
||||
---
|
||||
|
||||
@@ -750,6 +761,19 @@ Notification emails include:
|
||||
- Log file path
|
||||
- Hostname and timestamp
|
||||
|
||||
### Test Email
|
||||
|
||||
Verify your SMTP settings by sending a test email:
|
||||
|
||||
**TUI**: Settings > Send Test Email (automatically saves settings first).
|
||||
|
||||
**CLI**:
|
||||
```bash
|
||||
gniza --cli test-email
|
||||
```
|
||||
|
||||
Requires `NOTIFY_EMAIL` and `SMTP_HOST` to be configured.
|
||||
|
||||
### Fallback
|
||||
|
||||
If SMTP is not configured, gniza falls back to the system `mail` or `sendmail` command.
|
||||
@@ -783,16 +807,32 @@ gniza web start --port=8080 # Custom port
|
||||
gniza web start --host=127.0.0.1 # Bind to localhost only
|
||||
```
|
||||
|
||||
### Authentication
|
||||
### Configuration
|
||||
|
||||
Credentials are configured in `gniza.conf`:
|
||||
Web dashboard settings are in `gniza.conf`:
|
||||
|
||||
```ini
|
||||
WEB_USER="admin"
|
||||
WEB_API_KEY="generated-during-install"
|
||||
WEB_PORT="2323" # Dashboard port
|
||||
WEB_HOST="0.0.0.0" # Bind address (0.0.0.0 = all interfaces)
|
||||
WEB_USER="admin" # HTTP Basic Auth username
|
||||
WEB_API_KEY="generated-during-install" # HTTP Basic Auth password
|
||||
```
|
||||
|
||||
The API key is generated automatically during installation if you enable the web dashboard. You can change it manually.
|
||||
The API key is generated automatically during installation if you enable the web dashboard. You can change it in Settings or directly in `gniza.conf`.
|
||||
|
||||
After changing web settings, restart the service:
|
||||
```bash
|
||||
systemctl --user restart gniza-web.service # user mode
|
||||
sudo systemctl restart gniza-web.service # root mode
|
||||
```
|
||||
|
||||
### Mobile Access
|
||||
|
||||
The web dashboard works on mobile browsers. On small screens:
|
||||
- Font size auto-adjusts to fit approximately 50 columns
|
||||
- Button rows scroll horizontally
|
||||
- The documentation panel hides automatically on narrow screens
|
||||
- Touch scrolling is supported in all scrollable areas
|
||||
|
||||
### Root vs User Mode
|
||||
|
||||
@@ -814,10 +854,25 @@ Launch with `gniza` (no arguments). Requires Python 3 and Textual.
|
||||
| **Backup** | Select sources and destinations, run backups |
|
||||
| **Restore** | Browse snapshots, restore to original or custom location |
|
||||
| **Running Tasks** | Monitor active jobs with live log output and progress |
|
||||
| **Schedules** | Create and manage cron schedules |
|
||||
| **Schedules** | Create and manage cron schedules, view last run time |
|
||||
| **Snapshots** | Browse stored snapshots |
|
||||
| **Logs** | View backup history with pagination |
|
||||
| **Settings** | Configure global options |
|
||||
| **Settings** | Configure global options in organized sections |
|
||||
|
||||
### Navigation
|
||||
|
||||
Every screen has a **← Back** button in the top-left corner next to the screen title. Press `Escape` or click the button to return to the previous screen.
|
||||
|
||||
### Settings Screen
|
||||
|
||||
The Settings screen organizes options into four bordered sections:
|
||||
|
||||
| Section | Contents |
|
||||
|---------|----------|
|
||||
| **General** | Log level, log retention, retention count, bandwidth limit, disk threshold, rsync options |
|
||||
| **Email Notifications** | Email address, notify mode, SMTP host/port/user/password/from/security, Send Test Email button |
|
||||
| **SSH** | SSH timeout, SSH retries |
|
||||
| **Web Dashboard** | Port, host, API key |
|
||||
|
||||
### Features
|
||||
|
||||
@@ -826,7 +881,7 @@ Launch with `gniza` (no arguments). Requires Python 3 and Textual.
|
||||
- **Remote Folder Browser**: Browse SSH destination directories
|
||||
- **Connection Testing**: Test destination connectivity from the edit screen
|
||||
- **Documentation Panel**: Inline help on wide screens, help modal on narrow ones
|
||||
- **Responsive Layout**: Adapts to terminal width
|
||||
- **Responsive Layout**: Adapts to terminal width; button rows scroll horizontally on narrow screens
|
||||
- **Job Manager**: Run backups/restores in background with live log streaming
|
||||
|
||||
### Keyboard Shortcuts
|
||||
@@ -912,6 +967,7 @@ gniza --cli retention --destination=NAME # One destination
|
||||
gniza --cli schedule install # Install cron entries
|
||||
gniza --cli schedule show # Show current entries
|
||||
gniza --cli schedule remove # Remove all entries
|
||||
gniza scheduled-run --schedule=NAME # Run a schedule (used by cron)
|
||||
```
|
||||
|
||||
### Logs
|
||||
@@ -932,6 +988,12 @@ gniza web remove-service # Remove service
|
||||
gniza web status # Check status
|
||||
```
|
||||
|
||||
### Notifications
|
||||
|
||||
```bash
|
||||
gniza --cli test-email # Send a test email
|
||||
```
|
||||
|
||||
### System
|
||||
|
||||
```bash
|
||||
@@ -967,9 +1029,11 @@ All global settings are in `gniza.conf` in the config directory.
|
||||
|
||||
| Setting | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| `LOG_LEVEL` | `info` | `info` or `debug` |
|
||||
| `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, or `error` |
|
||||
| `LOG_RETAIN` | `90` | Days to keep log files |
|
||||
|
||||
Log files are named using local time (e.g., `gniza-20260307-040001.log`) to match cron schedules which also run in local time.
|
||||
|
||||
### Notifications
|
||||
|
||||
| Setting | Default | Description |
|
||||
@@ -1019,6 +1083,23 @@ All global settings are in `gniza.conf` in the config directory.
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
### Deploy Script
|
||||
|
||||
For developers, `scripts/deploy.sh` automates the deploy workflow:
|
||||
|
||||
```bash
|
||||
bash scripts/deploy.sh "commit message"
|
||||
```
|
||||
|
||||
This script:
|
||||
1. Commits and pushes all changes to git
|
||||
2. Syncs updated files to the local install directory (`~/.local/share/gniza`)
|
||||
3. Restarts the web dashboard service if running
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Checking Logs
|
||||
@@ -1048,11 +1129,11 @@ Create at least one destination in `<config_dir>/remotes.d/`.
|
||||
**Backup aborted due to disk space**
|
||||
The destination disk usage exceeds the threshold. Free space or adjust `DISK_USAGE_THRESHOLD` in `gniza.conf`.
|
||||
|
||||
**Cron not running**
|
||||
**Cron not running or using stale flags**
|
||||
- Check that cron entries are installed: `gniza --cli schedule show`
|
||||
- Verify the cron daemon is running: `systemctl status cron`
|
||||
- Check cron logs: `<log_dir>/cron.log`
|
||||
- Re-install entries: `gniza --cli schedule install`
|
||||
- Re-install entries: `gniza --cli schedule install` (this regenerates all entries with current flags)
|
||||
|
||||
**rclone required**
|
||||
S3 and Google Drive sources/destinations require rclone. Install from https://rclone.org/install/.
|
||||
|
||||
@@ -213,3 +213,35 @@
|
||||
{"timestamp": "2026-03-07 01:23:59.732166+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered documentation tools", "module": "server", "function": "_register_tools", "line": 65, "taskName": null}
|
||||
{"timestamp": "2026-03-07 01:23:59.732197+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Documentation search will be indexed on first use", "module": "server", "function": "__init__", "line": 41, "taskName": null}
|
||||
{"timestamp": "2026-03-07 01:23:59.732219+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Textual MCP Server initialized", "module": "server", "function": "__init__", "line": 47, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.277593+00:00", "level": "INFO", "logger": "textual_mcp.validation_tools", "message": "Registered validation tools: validate_tcss, validate_tcss_file, validate_inline_styles, check_selector", "module": "validation_tools", "function": "register_validation_tools", "line": 360, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.277653+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered validation tools", "module": "server", "function": "_register_tools", "line": 53, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.278141+00:00", "level": "INFO", "logger": "textual_mcp.analysis_tools", "message": "Registered analysis tools: analyze_selectors, extract_css_variables, detect_style_conflicts", "module": "analysis_tools", "function": "register_analysis_tools", "line": 99, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.278173+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered analysis tools", "module": "server", "function": "_register_tools", "line": 56, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.279706+00:00", "level": "INFO", "logger": "textual_mcp.widget_tools", "message": "Registered widget tools: generate_widget, list_widget_types, list_event_handlers, validate_widget_name", "module": "widget_tools", "function": "register_widget_tools", "line": 343, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.279741+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered widget tools", "module": "server", "function": "_register_tools", "line": 59, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.280789+00:00", "level": "INFO", "logger": "textual_mcp.layout_tools", "message": "Registered layout tools: generate_grid_layout", "module": "layout_tools", "function": "register_layout_tools", "line": 139, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.280843+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered layout tools", "module": "server", "function": "_register_tools", "line": 62, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.284105+00:00", "level": "INFO", "logger": "textual_mcp.documentation_tools", "message": "Registered documentation tools: search_textual_docs, index_textual_docs, search_textual_code_examples, get_css_property_info, list_css_properties", "module": "documentation_tools", "function": "register_documentation_tools", "line": 613, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:21.284143+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered documentation tools", "module": "server", "function": "_register_tools", "line": 65, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:26.899447+00:00", "level": "INFO", "logger": "faiss.loader", "message": "Loading faiss with AVX2 support.", "module": "loader", "function": "<module>", "line": 125, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:26.918799+00:00", "level": "INFO", "logger": "faiss.loader", "message": "Successfully loaded faiss with AVX2 support.", "module": "loader", "function": "<module>", "line": 127, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:26.921141+00:00", "level": "INFO", "logger": "faiss", "message": "Failed to load GPU Faiss: name 'GpuIndexIVFFlat' is not defined. Will not load constructor refs for GPU indexes. This is only an error if you're trying to use GPU Faiss.", "module": "__init__", "function": "<module>", "line": 174, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.175775+00:00", "level": "INFO", "logger": "textual_mcp.textual_docs_memory", "message": "Initialized VectorDB with embeddings: BAAI/bge-base-en-v1.5, persisting to: data/textual_docs.db", "module": "memory", "function": "__init__", "line": 45, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.175846+00:00", "level": "INFO", "logger": "textual_mcp.documentation_tools", "message": "Auto-indexing documentation on first use", "module": "documentation_tools", "function": "get_docs_memory", "line": 45, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.175887+00:00", "level": "WARNING", "logger": "textual_mcp.server", "message": "Failed to initialize documentation search: no running event loop", "module": "server", "function": "__init__", "line": 45, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.177468+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Textual MCP Server initialized", "module": "server", "function": "__init__", "line": 47, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.183325+00:00", "level": "INFO", "logger": "textual_mcp.validation_tools", "message": "Registered validation tools: validate_tcss, validate_tcss_file, validate_inline_styles, check_selector", "module": "validation_tools", "function": "register_validation_tools", "line": 360, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.183371+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered validation tools", "module": "server", "function": "_register_tools", "line": 53, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.183789+00:00", "level": "INFO", "logger": "textual_mcp.analysis_tools", "message": "Registered analysis tools: analyze_selectors, extract_css_variables, detect_style_conflicts", "module": "analysis_tools", "function": "register_analysis_tools", "line": 99, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.183823+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered analysis tools", "module": "server", "function": "_register_tools", "line": 56, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.185413+00:00", "level": "INFO", "logger": "textual_mcp.widget_tools", "message": "Registered widget tools: generate_widget, list_widget_types, list_event_handlers, validate_widget_name", "module": "widget_tools", "function": "register_widget_tools", "line": 343, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.185446+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered widget tools", "module": "server", "function": "_register_tools", "line": 59, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.186426+00:00", "level": "INFO", "logger": "textual_mcp.layout_tools", "message": "Registered layout tools: generate_grid_layout", "module": "layout_tools", "function": "register_layout_tools", "line": 139, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.186465+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered layout tools", "module": "server", "function": "_register_tools", "line": 62, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.189657+00:00", "level": "INFO", "logger": "textual_mcp.documentation_tools", "message": "Registered documentation tools: search_textual_docs, index_textual_docs, search_textual_code_examples, get_css_property_info, list_css_properties", "module": "documentation_tools", "function": "register_documentation_tools", "line": 613, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.189708+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Registered documentation tools", "module": "server", "function": "_register_tools", "line": 65, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.189753+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Documentation search will be indexed on first use", "module": "server", "function": "__init__", "line": 41, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.189784+00:00", "level": "INFO", "logger": "textual_mcp.server", "message": "Textual MCP Server initialized", "module": "server", "function": "__init__", "line": 47, "taskName": null}
|
||||
{"timestamp": "2026-03-07 14:46:29.202417+00:00", "level": "INFO", "logger": "mcp.server.lowlevel.server", "message": "Processing request of type ListToolsRequest", "module": "server", "function": "_handle_request", "line": 625, "taskName": "mcp.server.lowlevel.server.Server._handle_message"}
|
||||
{"timestamp": "2026-03-07 14:46:29.204064+00:00", "level": "INFO", "logger": "mcp.server.lowlevel.server", "message": "Processing request of type ListPromptsRequest", "module": "server", "function": "_handle_request", "line": 625, "taskName": "mcp.server.lowlevel.server.Server._handle_message"}
|
||||
{"timestamp": "2026-03-07 14:46:29.204920+00:00", "level": "INFO", "logger": "mcp.server.lowlevel.server", "message": "Processing request of type ListResourcesRequest", "module": "server", "function": "_handle_request", "line": 625, "taskName": "mcp.server.lowlevel.server.Server._handle_message"}
|
||||
|
||||
Reference in New Issue
Block a user