feat: add pos system health, lib/notify.sh, and daily Telegram digest timer
- bin/pos-system-health: host dashboard (disk, RAM, failed units, backup age,
fail2ban, docker); exits 1 on any FAIL; --send/--markdown via Telegram
- lib/notify.sh: self-contained opt-in alerting helper; silent-fails, wired
into pos-system-backup (success + ERR trap) and pos-system-firewall
- systemd/pos-health.{service,timer}: 08:00 digest as installing user;
postinstall enables timer once telegram.env exists, now copies *.timer
- AGENT_TODO.md: worklist with Now/Next/Later/Done history; linked from AGENTS.md
This commit is contained in:
@@ -10,19 +10,19 @@
|
||||
|
||||
<!-- GEN:START docmap -->
|
||||
| ## 1. Project Overview | 28–43 |
|
||||
| ## 2. Directory Structure | 44–164 |
|
||||
| ## 3. Installation Flow | 165–216 |
|
||||
| ## 4. The `pos` CLI System | 217–273 |
|
||||
| ## 5. Shared Library — `lib/common.sh` | 274–304 |
|
||||
| ## 6. Docker Compose / ScaleTail | 305–347 |
|
||||
| ## 7. Optional Apps (`apps/`) | 348–377 |
|
||||
| ## 8. Entertainment Module | 378–391 |
|
||||
| ## 9. Systemd Services | 392–402 |
|
||||
| ## 10. Configuration Files | 403–426 |
|
||||
| ## 11. Coding Conventions | 427–459 |
|
||||
| ## 12. Development Workflow | 460–511 |
|
||||
| ## 13. Key File Quick Reference | 512–553 |
|
||||
| ## 14. Common Tasks for Agents | 554–578 |
|
||||
| ## 2. Directory Structure | 44–165 |
|
||||
| ## 3. Installation Flow | 166–217 |
|
||||
| ## 4. The `pos` CLI System | 218–275 |
|
||||
| ## 5. Shared Library — `lib/common.sh` | 276–306 |
|
||||
| ## 6. Docker Compose / ScaleTail | 307–349 |
|
||||
| ## 7. Optional Apps (`apps/`) | 350–379 |
|
||||
| ## 8. Entertainment Module | 380–393 |
|
||||
| ## 9. Systemd Services | 394–404 |
|
||||
| ## 10. Configuration Files | 405–428 |
|
||||
| ## 11. Coding Conventions | 429–461 |
|
||||
| ## 12. Development Workflow | 462–513 |
|
||||
| ## 13. Key File Quick Reference | 514–556 |
|
||||
| ## 14. Common Tasks for Agents | 557–581 |
|
||||
<!-- GEN:END docmap -->
|
||||
|
||||
## 1. Project Overview
|
||||
@@ -76,6 +76,7 @@ Linux_post_install/
|
||||
│ ├── pos-ssh-load-keys # Load all SSH keys into the agent
|
||||
│ ├── pos-system-backup # Encrypted (AES-256) folder snapshots (tar + gpg)
|
||||
│ ├── pos-system-firewall # Interactive UFW management
|
||||
│ ├── pos-system-health # Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL
|
||||
│ ├── pos-usb-server # USB Redirector server control (--ls, --share; prompts when args omitted)
|
||||
<!-- GEN:END tree -->
|
||||
│ ├── flag-reader # Inspect feature flags (list/status/--raw)
|
||||
@@ -252,6 +253,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
|
||||
| ssh | load-keys | `pos-ssh-load-keys` | Load all SSH keys into the agent |
|
||||
| system | backup | `pos-system-backup` | Encrypted (AES-256) folder snapshots (tar + gpg) |
|
||||
| system | firewall | `pos-system-firewall` | Interactive UFW management |
|
||||
| system | health | `pos-system-health` | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
|
||||
| usb | server | `pos-usb-server` | USB Redirector server control (--ls, --share; prompts when args omitted) |
|
||||
<!-- GEN:END dispatch -->
|
||||
|
||||
@@ -542,10 +544,11 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
||||
| `bin/pos-network-ip` | 69 | Show interfaces, routes, public IP + location |
|
||||
| `bin/pos-network-scan` | 271 | Parallel ping sweep of CIDR |
|
||||
| `bin/pos-ssh-load-keys` | 31 | Load all SSH keys into the agent |
|
||||
| `bin/pos-system-backup` | 117 | Encrypted (AES-256) folder snapshots (tar + gpg) |
|
||||
| `bin/pos-system-firewall` | 285 | Interactive UFW management |
|
||||
| `bin/pos-system-backup` | 121 | Encrypted (AES-256) folder snapshots (tar + gpg) |
|
||||
| `bin/pos-system-firewall` | 291 | Interactive UFW management |
|
||||
| `bin/pos-system-health` | 230 | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
|
||||
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
|
||||
| `completions/pos.bash` | 188 | Dynamic bash completion |
|
||||
| `completions/pos.bash` | 189 | Dynamic bash completion |
|
||||
<!-- GEN:END filetable -->
|
||||
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
|
||||
|
||||
|
||||
+12
@@ -275,6 +275,18 @@ Place it in `apps/<category>/<name>.sh`. It auto-appears in the picker — no re
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Alerting
|
||||
|
||||
To notify on events (Telegram), source the shared helper instead of calling the telegram tool directly:
|
||||
|
||||
```bash
|
||||
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
||||
notify_send "Backup completed"
|
||||
notify_send "**disk full**" --markdown
|
||||
```
|
||||
|
||||
`notify_send` is deliberately dependency-free (defines only itself, so it never clobbers a tool's own `log`/`warn`/`err`) and **silent-fails**: if Telegram is missing or not configured it warns and returns 0, never breaking the caller's flow or exit code. Source it opt-in in any tool that should alert; for failure alerts use `trap 'notify_send "..." ERR'`.
|
||||
|
||||
### Idempotency
|
||||
|
||||
Check before creating, use `>>` with grep guards, don't overwrite user configs.
|
||||
|
||||
+5
-2
@@ -151,9 +151,12 @@ The standalone `vbox` command still works and forwards to `pos docker vbox` (see
|
||||
|
||||
| Command | File | Purpose | Configuration |
|
||||
|---------|------|---------|---------------|
|
||||
| `sudo pos system firewall` | `bin/pos-system-firewall` | Interactive UFW ("UFW POWER") menu: add/delete rules, status, enable/disable/reset, default policies | Must run as root. Every command is previewed and confirmed before execution; supports `--dry-run`; keeps a history of executed commands |
|
||||
| `pos system backup <folder-path>` | `bin/pos-system-backup` | Create a gpg-encrypted (AES-256) `tar.gz` snapshot of a folder and verify it | Prompts twice for a password (never stored). Uses `sudo tar`; needs `gnupg` (in `preinstall.sh` PACKAGES). Artifact `<name>_<date>.tar.gz.gpg` in the current directory, `chmod 600` |
|
||||
| `sudo pos system firewall` | `bin/pos-system-firewall` | Interactive UFW ("UFW POWER") menu: add/delete rules, status, enable/disable/reset, default policies | Must run as root. Every command is previewed and confirmed before execution; supports `--dry-run`; keeps a history of executed commands. Executed mutating changes are announced via `lib/notify.sh` |
|
||||
| `pos system backup <folder-path>` | `bin/pos-system-backup` | Create a gpg-encrypted (AES-256) `tar.gz` snapshot of a folder and verify it | Prompts twice for a password (never stored). Uses `sudo tar`; needs `gnupg` (in `preinstall.sh` PACKAGES). Artifact `<name>_<date>.tar.gz.gpg` in the current directory, `chmod 600`. Success/failure are announced via `lib/notify.sh` |
|
||||
| `pos system backup --service` | `bin/pos-system-backup` | Lists folders under `/srv` and `~/srv`, lets you pick one, then runs the same backup | Roots via `BACKUP_SERVICE_ROOTS` (space-separated, default `/srv $HOME/srv`) |
|
||||
| `pos system health [--send] [--markdown]` | `bin/pos-system-health` | Host health dashboard: disk per mount, RAM/swap, failed systemd units, backup age, fail2ban, docker containers. Exits 1 if any check FAILs | `--send`/`--markdown` send the summary via Telegram (`lib/notify.sh`). Backup age threshold via `HEALTH_BACKUP_MAX_AGE_DAYS` (default 2); backup search roots via `BACKUP_SERVICE_ROOTS` |
|
||||
|
||||
`systemd/pos-health.service` + `systemd/pos-health.timer` run `pos system health --send --markdown` daily at 08:00 as the installing user. `postinstall.sh` enables the timer automatically once `~/.config/linux_post_install/telegram.env` exists — re-run postinstall after configuring Telegram to pick it up.
|
||||
|
||||
### ssh
|
||||
|
||||
|
||||
+32
-3
@@ -5,6 +5,7 @@ The units installed and enabled by `postinstall.sh`, plus the `pos` bash complet
|
||||
- [Services](#services)
|
||||
- [`autostart.service`](#autostartservice)
|
||||
- [`ssh-agent.service`](#ssh-agentservice)
|
||||
- [`pos-health.service`](#pos-healthservice)
|
||||
- [Feature-flag gating](#feature-flag-gating)
|
||||
- [Bash completion](#bash-completion)
|
||||
|
||||
@@ -12,7 +13,7 @@ The units installed and enabled by `postinstall.sh`, plus the `pos` bash complet
|
||||
|
||||
## Services
|
||||
|
||||
`postinstall.sh` copies every `systemd/*.service` to `/etc/systemd/system/`, runs `systemctl daemon-reload`, then enables each one (see the gating rule below).
|
||||
`postinstall.sh` copies every `systemd/*.service` (and `systemd/*.timer`) to `/etc/systemd/system/`, runs `systemctl daemon-reload`, then enables each one (see the gating rule below).
|
||||
|
||||
### autostart.service
|
||||
|
||||
@@ -59,20 +60,48 @@ WantedBy=multi-user.target
|
||||
|
||||
**Configuration:** socket at `/run/ssh-agent/socket` (world-readable/writable). `~/.bashrc` (set by `postinstall.sh`) exports `SSH_AUTH_SOCK` to it. Not gated on any feature flag.
|
||||
|
||||
### pos-health.service
|
||||
|
||||
**Purpose:** daily "health digest" — runs `pos system health --send --markdown` at 08:00 and sends the report to Telegram.
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=POS Health digest (daily report via Telegram)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=__POS_USER__
|
||||
ExecStart=/usr/local/bin/pos system health --send --markdown
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-* 08:00:00
|
||||
Persistent=true
|
||||
```
|
||||
|
||||
The service is `Type=oneshot` and is driven **only** by its companion `pos-health.timer` (`WantedBy=timers.target`); the service itself is never enabled directly.
|
||||
|
||||
**Configuration:** `postinstall.sh` substitutes `__POS_USER__` with the installing user (`${SUDO_USER:-$USER}`) so the digest uses that user's real Telegram config. The timer is enabled only when `~/.config/linux_post_install/telegram.env` already exists — otherwise postinstall warns and skips; re-run postinstall after configuring Telegram (`pos communication telegram config set TELEGRAM_*`) to install it.
|
||||
|
||||
---
|
||||
|
||||
## Feature-flag gating
|
||||
|
||||
The systemd loop in `postinstall.sh` special-cases `autostart.service`:
|
||||
The systemd loop in `postinstall.sh` special-cases two units:
|
||||
|
||||
```bash
|
||||
if [ "$svc_name" = "autostart.service" ] && ! flag_is_set autostart; then
|
||||
warn "autostart feature not installed — skipping autostart.service (run ./install.sh --feature)"
|
||||
continue
|
||||
fi
|
||||
if [ "$svc_name" = "pos-health.service" ]; then
|
||||
# substitute User= and enable pos-health.timer only if Telegram is configured
|
||||
fi
|
||||
```
|
||||
|
||||
Set the flag with `./install.sh --feature` (or `flag-set autostart`). See [SCRIPTS.md → lib/flags.sh](SCRIPTS.md#libflagssh--feature-flags).
|
||||
- `autostart.service` is **enabled** only when the `autostart` feature flag is set (`./install.sh --feature` or `flag-set autostart`). See [SCRIPTS.md → lib/flags.sh](SCRIPTS.md#libflagssh--feature-flags).
|
||||
- `pos-health.service` is **not** enabled at all — `postinstall.sh` enables `pos-health.timer` instead, and only when a Telegram config already exists.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user