feat: multi-platform alerting + shared system.env config with dynamic help values
- lib/notify.sh: route notify_send to every platform in NOTIFY_PLATFORM (notify.env, default telegram; comma-separated = send to all). New platforms need only a bin/pos-communication-<p> sender implementing 'send <value> [--markdown]' (Matrix/Synapse ready) - pos-communication-telegram: add --markdown as alias for --parse-mode markdown to match the sender contract - lib/common.sh: load_system_env() — shared ~/.config/linux_post_install/ system.env for pos-system-* tools (env exported > file > default) - pos-system-health/backup: load system.env and show effective dynamic values (NOTIFY_PLATFORM, HEALTH_BACKUP_MAX_AGE_DAYS, BACKUP_SERVICE_ROOTS) in --help - config/system.env + config/notify.env templates copied by postinstall - systemd/pos-health.service: EnvironmentFile for both configs so the daily digest honors them
This commit is contained in:
@@ -49,6 +49,10 @@ summary (newest last).
|
|||||||
|
|
||||||
## Done (summary, newest last)
|
## Done (summary, newest last)
|
||||||
|
|
||||||
|
- 2026-08-06: Multi-platform alerting — `lib/notify.sh` routes via `NOTIFY_PLATFORM`
|
||||||
|
(`notify.env`, default telegram; sender contract for Matrix/Synapse later),
|
||||||
|
`system.env` shared config for health/backup, dynamic effective values in
|
||||||
|
`--help`, telegram `--markdown` alias.
|
||||||
- 2026-08-06: Tier 1 — `pos system health` (dashboard + `--send`), `lib/notify.sh`
|
- 2026-08-06: Tier 1 — `pos system health` (dashboard + `--send`), `lib/notify.sh`
|
||||||
(wired into backup + firewall), daily digest timer via postinstall.
|
(wired into backup + firewall), daily digest timer via postinstall.
|
||||||
- 2026-08-06: Document Map index + Entertainment section in AGENT_Context (cf36780).
|
- 2026-08-06: Document Map index + Entertainment section in AGENT_Context (cf36780).
|
||||||
|
|||||||
@@ -527,7 +527,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
| `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
||||||
<!-- GEN:START filetable -->
|
<!-- GEN:START filetable -->
|
||||||
| `bin/pos` | 213 | CLI dispatcher with smart arg matching + logging + category help |
|
| `bin/pos` | 213 | CLI dispatcher with smart arg matching + logging + category help |
|
||||||
| `bin/pos-communication-telegram` | 270 | Send Telegram messages/files/links/stickers via Bot API (send, test, config set) |
|
| `bin/pos-communication-telegram` | 274 | Send Telegram messages/files/links/stickers via Bot API (send, test, config set) |
|
||||||
| `bin/pos-docker-compose` | 364 | Docker Compose service manager (ls/up/down/restart/logs/update/config) |
|
| `bin/pos-docker-compose` | 364 | Docker Compose service manager (ls/up/down/restart/logs/update/config) |
|
||||||
| `bin/pos-docker-health` | 110 | One-glance container health dashboard (exits 1 if unhealthy) |
|
| `bin/pos-docker-health` | 110 | One-glance container health dashboard (exits 1 if unhealthy) |
|
||||||
| `bin/pos-docker-ps` | 128 | Enhanced container overview (health, IPs, ports, uptime) |
|
| `bin/pos-docker-ps` | 128 | Enhanced container overview (health, IPs, ports, uptime) |
|
||||||
@@ -544,9 +544,9 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| `bin/pos-network-ip` | 69 | Show interfaces, routes, public IP + location |
|
| `bin/pos-network-ip` | 69 | Show interfaces, routes, public IP + location |
|
||||||
| `bin/pos-network-scan` | 271 | Parallel ping sweep of CIDR |
|
| `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-ssh-load-keys` | 31 | Load all SSH keys into the agent |
|
||||||
| `bin/pos-system-backup` | 121 | Encrypted (AES-256) folder snapshots (tar + gpg) |
|
| `bin/pos-system-backup` | 125 | Encrypted (AES-256) folder snapshots (tar + gpg) |
|
||||||
| `bin/pos-system-firewall` | 291 | Interactive UFW management |
|
| `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-system-health` | 243 | 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) |
|
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
|
||||||
| `completions/pos.bash` | 189 | Dynamic bash completion |
|
| `completions/pos.bash` | 189 | Dynamic bash completion |
|
||||||
<!-- GEN:END filetable -->
|
<!-- GEN:END filetable -->
|
||||||
|
|||||||
+13
-3
@@ -148,7 +148,9 @@ PACKAGES=(
|
|||||||
Two kinds of config, don't mix them up:
|
Two kinds of config, don't mix them up:
|
||||||
|
|
||||||
- **Machine defaults shipped by the installer:** place the file in `config/` and add copy logic to `postinstall.sh`. If it contains secrets, add to `.gitignore` and document in `DOC/`.
|
- **Machine defaults shipped by the installer:** place the file in `config/` and add copy logic to `postinstall.sh`. If it contains secrets, add to `.gitignore` and document in `DOC/`.
|
||||||
- **Runtime tool config set by the user:** `~/.config/linux_post_install/<tool>.env` with `chmod 600`. Load it with env-var precedence (flags > environment > file). Patterns: `pos-docker-compose` (`compose.env`) and `pos-communication-telegram` (`telegram.env`, token masked in `config` output). Never store tokens in the repo.
|
- **Runtime tool config set by the user:** `~/.config/linux_post_install/<tool>.env` with `chmod 600`. Load it with env-var precedence (flags > environment > file). Patterns: `pos-docker-compose` (`compose.env`), `pos-communication-telegram` (`telegram.env`, token masked in `config` output), and the shared ones below. Never store tokens in the repo.
|
||||||
|
- `system.env` — shared "system" settings loaded by `pos-system-*` tools via `load_system_env()` in `lib/common.sh` (currently `BACKUP_SERVICE_ROOTS`, `HEALTH_BACKUP_MAX_AGE_DAYS`). Env already exported wins over the file.
|
||||||
|
- `notify.env` — alerting platform selection (`NOTIFY_PLATFORM=telegram,matrix`), read by `lib/notify.sh`.
|
||||||
|
|
||||||
### 5. Add SSH keys (if needed)
|
### 5. Add SSH keys (if needed)
|
||||||
|
|
||||||
@@ -277,7 +279,7 @@ Place it in `apps/<category>/<name>.sh`. It auto-appears in the picker — no re
|
|||||||
|
|
||||||
### Alerting
|
### Alerting
|
||||||
|
|
||||||
To notify on events (Telegram), source the shared helper instead of calling the telegram tool directly:
|
To notify on events, source the shared helper instead of calling a platform tool directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
||||||
@@ -285,7 +287,15 @@ notify_send "Backup completed"
|
|||||||
notify_send "**disk full**" --markdown
|
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'`.
|
`notify_send` is deliberately dependency-free (defines only itself, so it never clobbers a tool's own `log`/`warn`/`err`) and **silent-fails**: if no platform is 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'`.
|
||||||
|
|
||||||
|
**Multi-platform routing:** `notify_send` delivers to every platform listed in `NOTIFY_PLATFORM` (env or `~/.config/linux_post_install/notify.env`, default `telegram`, comma-separated to send to all). Adding a new platform (e.g. Matrix/Synapse) means creating a `bin/pos-communication-<platform>` tool that implements the **sender contract**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pos-communication-<platform> send <value> [--markdown] # exit 0 on delivery
|
||||||
|
```
|
||||||
|
|
||||||
|
then listing it in `NOTIFY_PLATFORM`. `pos-communication-telegram` already follows this (`--markdown` is an alias for `--parse-mode markdown`). No changes to `lib/notify.sh` are needed for a new platform.
|
||||||
|
|
||||||
### Idempotency
|
### Idempotency
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -153,10 +153,10 @@ The standalone `vbox` command still works and forwards to `pos docker vbox` (see
|
|||||||
|---------|------|---------|---------------|
|
|---------|------|---------|---------------|
|
||||||
| `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` |
|
| `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 <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 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`) or `~/.config/linux_post_install/system.env` |
|
||||||
| `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` |
|
| `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 `lib/notify.sh` to every platform in `NOTIFY_PLATFORM`. `HEALTH_BACKUP_MAX_AGE_DAYS` (default 2) and `BACKUP_SERVICE_ROOTS` come from `~/.config/linux_post_install/system.env`; `--help` shows the effective values. Platform list from `~/.config/linux_post_install/notify.env` |
|
||||||
|
|
||||||
`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.
|
`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 a notify platform to pick it up. The service also loads `system.env` + `notify.env` via `EnvironmentFile=`.
|
||||||
|
|
||||||
### ssh
|
### ssh
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -62,17 +62,19 @@ WantedBy=multi-user.target
|
|||||||
|
|
||||||
### pos-health.service
|
### pos-health.service
|
||||||
|
|
||||||
**Purpose:** daily "health digest" — runs `pos system health --send --markdown` at 08:00 and sends the report to Telegram.
|
**Purpose:** daily "health digest" — runs `pos system health --send --markdown` at 08:00 and sends the report to the configured notify platform(s).
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=POS Health digest (daily report via Telegram)
|
Description=POS Health digest (daily report via configured notify platforms)
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
User=__POS_USER__
|
User=__POS_USER__
|
||||||
|
EnvironmentFile=-%h/.config/linux_post_install/system.env
|
||||||
|
EnvironmentFile=-%h/.config/linux_post_install/notify.env
|
||||||
ExecStart=/usr/local/bin/pos system health --send --markdown
|
ExecStart=/usr/local/bin/pos system health --send --markdown
|
||||||
|
|
||||||
[Timer]
|
[Timer]
|
||||||
@@ -82,7 +84,7 @@ 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.
|
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.
|
**Configuration:** `postinstall.sh` substitutes `__POS_USER__` with the installing user (`${SUDO_USER:-$USER}`) so the digest uses that user's real notify config. The `EnvironmentFile=` lines load `system.env` (health/backup settings) and `notify.env` (`NOTIFY_PLATFORM`). The timer is enabled only when a Telegram config (`~/.config/linux_post_install/telegram.env`) already exists — otherwise postinstall warns and skips; re-run postinstall after configuring a notify platform to install it.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ Options:
|
|||||||
--type <type> Force a type: message|file|link|sticker|photo|video|audio|voice|animation
|
--type <type> Force a type: message|file|link|sticker|photo|video|audio|voice|animation
|
||||||
--caption <text> Caption for file/photo/video/audio/voice/animation
|
--caption <text> Caption for file/photo/video/audio/voice/animation
|
||||||
--parse-mode <mode> Format mode: plain (default), markdown, html (message/link/caption)
|
--parse-mode <mode> Format mode: plain (default), markdown, html (message/link/caption)
|
||||||
|
--markdown Alias for --parse-mode markdown (uniform notify_send contract)
|
||||||
--no-preview Disable the link's web page preview (message/link only)
|
--no-preview Disable the link's web page preview (message/link only)
|
||||||
--token <t> Override token for one send
|
--token <t> Override token for one send
|
||||||
--chat-id <id> Override chat id for one send
|
--chat-id <id> Override chat id for one send
|
||||||
@@ -143,6 +144,9 @@ cmd_send() {
|
|||||||
--caption)
|
--caption)
|
||||||
[ $# -ge 2 ] || err "--caption needs a value"
|
[ $# -ge 2 ] || err "--caption needs a value"
|
||||||
caption="$2"; shift 2 ;;
|
caption="$2"; shift 2 ;;
|
||||||
|
--markdown)
|
||||||
|
# Alias for --parse-mode markdown (uniform notify_send contract)
|
||||||
|
parse_mode="markdown"; shift ;;
|
||||||
--parse-mode)
|
--parse-mode)
|
||||||
[ $# -ge 2 ] || err "--parse-mode needs a value"
|
[ $# -ge 2 ] || err "--parse-mode needs a value"
|
||||||
case "$2" in
|
case "$2" in
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ set -euo pipefail
|
|||||||
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
||||||
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
||||||
|
|
||||||
|
load_system_env
|
||||||
|
EFF_ROOTS="${BACKUP_SERVICE_ROOTS:-/srv $HOME/srv}"
|
||||||
|
|
||||||
trap 'notify_send "Backup FAILED: ${FOLDER:-unknown}"' ERR
|
trap 'notify_send "Backup FAILED: ${FOLDER:-unknown}"' ERR
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
@@ -24,7 +27,8 @@ The final artifact <name>_<date>.tar.gz.gpg is written to the current directory.
|
|||||||
|
|
||||||
Environment:
|
Environment:
|
||||||
BACKUP_SERVICE_ROOTS Space-separated roots for --service
|
BACKUP_SERVICE_ROOTS Space-separated roots for --service
|
||||||
(default: /srv \$HOME/srv)
|
(effective: ${EFF_ROOTS})
|
||||||
|
(loaded from ~/.config/linux_post_install/system.env unless exported)
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-16
@@ -5,18 +5,14 @@ set -euo pipefail
|
|||||||
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
||||||
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
||||||
|
|
||||||
SEND=0
|
load_system_env
|
||||||
MARKDOWN=0
|
|
||||||
for arg in "$@"; do
|
|
||||||
case "$arg" in
|
|
||||||
-h|--help) usage_placeholder=1 ;;
|
|
||||||
--send) SEND=1 ;;
|
|
||||||
--markdown) MARKDOWN=1 ;;
|
|
||||||
*) err "Unknown option '$arg' (see --help)" ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "${usage_placeholder:-0}" -eq 1 ]; then
|
# Effective dynamic values (environment > system.env > defaults) shown in --help
|
||||||
|
EFF_PLATFORMS="$(notify_platforms)"
|
||||||
|
EFF_MAX_AGE="${HEALTH_BACKUP_MAX_AGE_DAYS:-2}"
|
||||||
|
EFF_ROOTS="${BACKUP_SERVICE_ROOTS:-/srv $HOME/srv}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: pos system health [--send] [--markdown]
|
Usage: pos system health [--send] [--markdown]
|
||||||
|
|
||||||
@@ -24,20 +20,37 @@ Host health dashboard: disk, RAM/swap, failed systemd units, backup age,
|
|||||||
fail2ban, docker containers. Exits 1 if any check FAILs.
|
fail2ban, docker containers. Exits 1 if any check FAILs.
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--send Send the summary via Telegram (uses lib/notify.sh)
|
--send Send the summary via the configured notify platform(s)
|
||||||
|
(uses lib/notify.sh; see NOTIFY_PLATFORM below)
|
||||||
--markdown Same as --send, with markdown parse mode
|
--markdown Same as --send, with markdown parse mode
|
||||||
-h, --help Show this help
|
-h, --help Show this help
|
||||||
|
|
||||||
Environment:
|
Environment (effective values):
|
||||||
HEALTH_BACKUP_MAX_AGE_DAYS Max backup age before a WARN (default: 2)
|
NOTIFY_PLATFORM ${EFF_PLATFORMS}
|
||||||
BACKUP_SERVICE_ROOTS Where to look for backups (default: /srv \$HOME/srv)
|
HEALTH_BACKUP_MAX_AGE_DAYS ${EFF_MAX_AGE}
|
||||||
|
BACKUP_SERVICE_ROOTS ${EFF_ROOTS}
|
||||||
|
|
||||||
|
Loaded from ~/.config/linux_post_install/system.env (health/backup settings)
|
||||||
|
and ~/.config/linux_post_install/notify.env (NOTIFY_PLATFORM) unless already
|
||||||
|
exported. Defaults apply when neither is set.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
pos system health
|
pos system health
|
||||||
pos system health --send
|
pos system health --send
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
}
|
||||||
|
|
||||||
|
SEND=0
|
||||||
|
MARKDOWN=0
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
-h|--help) usage ;;
|
||||||
|
--send) SEND=1 ;;
|
||||||
|
--markdown) MARKDOWN=1 ;;
|
||||||
|
*) err "Unknown option '$arg' (see --help)" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
if [ "$MARKDOWN" -eq 1 ]; then
|
if [ "$MARKDOWN" -eq 1 ]; then
|
||||||
SEND=1
|
SEND=1
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# ~/.config/linux_post_install/notify.env — alerting platform selection
|
||||||
|
#
|
||||||
|
# Comma-separated list of platforms that lib/notify.sh delivers to (all of
|
||||||
|
# them). Each platform must have a bin/pos-communication-<platform> tool that
|
||||||
|
# implements the sender contract:
|
||||||
|
# pos-communication-<platform> send <value> [--markdown]
|
||||||
|
# Default: telegram
|
||||||
|
#NOTIFY_PLATFORM=telegram,matrix
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# ~/.config/linux_post_install/system.env — shared "system" tool config
|
||||||
|
#
|
||||||
|
# Loaded by `pos system health` and `pos system backup` via load_system_env()
|
||||||
|
# with precedence: already-exported environment > this file > defaults.
|
||||||
|
# Commented lines are defaults — uncomment to override.
|
||||||
|
|
||||||
|
# Roots scanned by `pos system backup --service` and by the backup-age check
|
||||||
|
# in `pos system health`. Default: /srv $HOME/srv
|
||||||
|
#BACKUP_SERVICE_ROOTS=/srv /home/you/srv
|
||||||
|
|
||||||
|
# Max backup age in days before `pos system health` raises a WARN. Default: 2
|
||||||
|
#HEALTH_BACKUP_MAX_AGE_DAYS=3
|
||||||
@@ -117,5 +117,24 @@ confirm() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── system.env loader ──────────────────────────────────────────
|
||||||
|
# Shared "system" tool config (~/.config/linux_post_install/system.env).
|
||||||
|
# Fills only variables that are not already exported — an explicitly-set
|
||||||
|
# environment variable always wins (flags > environment > file).
|
||||||
|
load_system_env() {
|
||||||
|
local f="$HOME/.config/linux_post_install/system.env" k v
|
||||||
|
[ -f "$f" ] || return 0
|
||||||
|
while IFS='=' read -r k v; do
|
||||||
|
[ -n "$k" ] || continue
|
||||||
|
case "$k" in
|
||||||
|
\#*) continue ;;
|
||||||
|
esac
|
||||||
|
v="${v%\"}"; v="${v#\"}"; v="${v%\'}"; v="${v#\'}"
|
||||||
|
if [ -z "${!k:-}" ]; then
|
||||||
|
export "$k"="$v"
|
||||||
|
fi
|
||||||
|
done < <(grep -E '^[A-Z_]+=' "$f" || true)
|
||||||
|
}
|
||||||
|
|
||||||
# ── Source guard ───────────────────────────────────────────────
|
# ── Source guard ───────────────────────────────────────────────
|
||||||
return 0 2>/dev/null || true
|
return 0 2>/dev/null || true
|
||||||
|
|||||||
+53
-23
@@ -1,16 +1,39 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# lib/notify.sh — optional alerting helper. Self-contained by design:
|
# lib/notify.sh — optional MULTI-PLATFORM alerting helper. Self-contained by
|
||||||
# defines ONLY notify_send() so it can be sourced by tools that define
|
# design: defines ONLY notify_send() + notify_platforms() (plus internal
|
||||||
# their own log/warn/err (e.g. pos-system-firewall) without clobbering.
|
# helpers) so it can be sourced by tools that define their own log/warn/err
|
||||||
|
# (e.g. pos-system-firewall) without clobbering.
|
||||||
#
|
#
|
||||||
# Usage (opt-in — source it, do NOT auto-load from common.sh):
|
# Usage (opt-in — source it, do NOT auto-load from common.sh):
|
||||||
# source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
# source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
|
||||||
# notify_send "Backup completed: $ARCHIVE"
|
# notify_send "Backup completed: $ARCHIVE"
|
||||||
# notify_send "⚠ disk full" --markdown
|
# notify_send "**disk full**" --markdown
|
||||||
#
|
#
|
||||||
# Delegates to `pos communication telegram send`; silent-fail if the
|
# Platform routing — ~/.config/linux_post_install/notify.env:
|
||||||
# telegram sender is missing or not configured (warns, never breaks the
|
# NOTIFY_PLATFORM=telegram,matrix
|
||||||
# caller and never changes its exit code).
|
# Comma-separated = send to every listed platform (default: telegram).
|
||||||
|
#
|
||||||
|
# Sender contract — each platform is a bin/pos-communication-<platform> tool
|
||||||
|
# that MUST implement:
|
||||||
|
# pos-communication-<platform> send <value> [--markdown]
|
||||||
|
# (exit 0 on delivery; non-zero on failure)
|
||||||
|
# To add a platform (e.g. Matrix/Synapse), add `bin/pos-communication-matrix`
|
||||||
|
# implementing that interface and put `matrix` in NOTIFY_PLATFORM.
|
||||||
|
#
|
||||||
|
# Silent-fails per platform: a missing sender or a failed send only warns and
|
||||||
|
# never changes the caller's exit code.
|
||||||
|
|
||||||
|
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/linux_post_install"
|
||||||
|
|
||||||
|
# Effective platform list (env > notify.env > "telegram").
|
||||||
|
notify_platforms() {
|
||||||
|
local p="${NOTIFY_PLATFORM:-}"
|
||||||
|
if [ -z "$p" ] && [ -f "$CONFIG_DIR/notify.env" ]; then
|
||||||
|
p="$(grep -E '^NOTIFY_PLATFORM=' "$CONFIG_DIR/notify.env" | tail -1 | cut -d= -f2-)"
|
||||||
|
p="${p%\"}"; p="${p#\"}"; p="${p%\'}"; p="${p#\'}"
|
||||||
|
fi
|
||||||
|
printf '%s' "${p:-telegram}"
|
||||||
|
}
|
||||||
|
|
||||||
notify_send() {
|
notify_send() {
|
||||||
local msg="" markdown=0
|
local msg="" markdown=0
|
||||||
@@ -26,22 +49,29 @@ notify_send() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local tg
|
local -a plist
|
||||||
tg="$(command -v pos-communication-telegram 2>/dev/null)" || \
|
IFS=',' read -r -a plist <<< "$(notify_platforms)"
|
||||||
tg="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/../bin/pos-communication-telegram"
|
|
||||||
|
|
||||||
if [ ! -x "$tg" ]; then
|
local p sender
|
||||||
warn "notify_send: pos-communication-telegram not found, notification skipped" 2>/dev/null || true
|
for p in "${plist[@]}"; do
|
||||||
return 0
|
p="${p// /}"
|
||||||
fi
|
[ -n "$p" ] || continue
|
||||||
|
sender="$(command -v "pos-communication-${p}" 2>/dev/null)" || \
|
||||||
|
sender="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/../bin/pos-communication-${p}"
|
||||||
|
|
||||||
if [ "$markdown" -eq 1 ]; then
|
if [ ! -x "$sender" ]; then
|
||||||
"$tg" send "$msg" --parse-mode markdown >/dev/null 2>&1 || {
|
warn "notify_send: pos-communication-${p} not found, notification skipped" 2>/dev/null || true
|
||||||
warn "notify_send: telegram send failed, notification skipped" 2>/dev/null || true
|
continue
|
||||||
}
|
fi
|
||||||
else
|
|
||||||
"$tg" send "$msg" >/dev/null 2>&1 || {
|
if [ "$markdown" -eq 1 ]; then
|
||||||
warn "notify_send: telegram send failed, notification skipped" 2>/dev/null || true
|
"$sender" send "$msg" --markdown >/dev/null 2>&1 || {
|
||||||
}
|
warn "notify_send: ${p} send failed, notification skipped" 2>/dev/null || true
|
||||||
fi
|
}
|
||||||
|
else
|
||||||
|
"$sender" send "$msg" >/dev/null 2>&1 || {
|
||||||
|
warn "notify_send: ${p} send failed, notification skipped" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,21 @@ else
|
|||||||
warn "config/entertainment.env not found, skipping"
|
warn "config/entertainment.env not found, skipping"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── system + notify config templates ───────────────────────────
|
||||||
|
# Copied only if the user has not already created their own (no clobber).
|
||||||
|
mkdir -p "$ENT_DIR"
|
||||||
|
for tpl in system.env notify.env; do
|
||||||
|
if [ -f "config/$tpl" ]; then
|
||||||
|
if [ -f "$ENT_DIR/$tpl" ]; then
|
||||||
|
log "$tpl already exists, keeping it"
|
||||||
|
else
|
||||||
|
cp "config/$tpl" "$ENT_DIR/$tpl"
|
||||||
|
chmod 600 "$ENT_DIR/$tpl"
|
||||||
|
log "Installed $tpl — edit $ENT_DIR/$tpl"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# ── Ensure all bin dirs are in PATH ────────────────────────────
|
# ── Ensure all bin dirs are in PATH ────────────────────────────
|
||||||
PATH_LINE='export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$HOME/.local/bin:$PATH"'
|
PATH_LINE='export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$HOME/.local/bin:$PATH"'
|
||||||
BASHRC="$HOME/.bashrc"
|
BASHRC="$HOME/.bashrc"
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=POS Health digest (daily report via Telegram)
|
Description=POS Health digest (daily report via configured notify platforms)
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
User=__POS_USER__
|
User=__POS_USER__
|
||||||
|
EnvironmentFile=-%h/.config/linux_post_install/system.env
|
||||||
|
EnvironmentFile=-%h/.config/linux_post_install/notify.env
|
||||||
ExecStart=/usr/local/bin/pos system health --send --markdown
|
ExecStart=/usr/local/bin/pos system health --send --markdown
|
||||||
|
|||||||
Reference in New Issue
Block a user