Added
--health(boxed),--health --listand--health --json: CPU, memory and disk usage, uptime
and a health level per local VM/CT, read frompvesh get /cluster/resources; templates and guests
on other cluster nodes are skipped.--filterand--nameapply.- Main menu key
hopens the health overview; the status action prints an extraHealth:line. --checkfor cron: alerts only on changes (new, escalated, improved, resolved) for resource
thresholds (CPU afterHEALTH_CPU_RUNSconsecutive runs; resolved when the guest stops), guests
stopped withonboot=1, guests whose latest lifecycle task does not explain a stop (stop, shutdown,
suspend, migrate, destroy, backup), and failed node tasks (read with--source all).
Nagios-style summary and exit codes 0 OK, 1 WARN, 2 CRIT, 3 UNKNOWN (also for usage errors).--dry-run(with--check) prints the result and the composed message without sending or
writing state;--test-notifysends a test message.- Notifications via ntfy (
NTFY_URL, optionalNTFY_TOKEN_FILE) and e-mail through the local
sendmail(HEALTH_MAIL_TO,HEALTH_MAIL_FROM); one combined message per run. - New config keys
HEALTH_{CPU,MEM,DISK}_{WARN,CRIT}(0disables a level),HEALTH_CPU_RUNS,
HEALTH_IGNORE_IDS,HEALTH_STATE_DIR(default/var/lib/pman) and the notification keys above. - CI runs the test suite (
tests/run.sh); shell completions gained--name,--health,
--check,--dry-runand--test-notify.
Changed
STOP_TIMEOUTandPROXMOX_MANAGER_SPICE_ADDRare validated after the command line is parsed.- With
--jsonthe--forcewarning goes to stderr, so the JSON output stays valid. - Outbound traffic is now possible, but only when notifications are configured (opt-in).
Security
- The ntfy access token is read from a
0600file owned by the caller in a directory nobody else can
write; the open descriptor is verified before reading (no swap between check and use). An inline
NTFY_TOKENin a config file and a token with anhttp://URL are configuration errors. - The token, URL and headers reach
curlonly via its stdin config, never argv;curl -qignores
~/.curlrc, redirects are not followed, a token forceshttpsonly, and requests are not retried. - Logs name only the ntfy host, never the topic path or the token.
- Mail headers are built from validated single-line values (no header injection).
- JSON output escapes all control characters;
_truncatenever cuts inside a UTF-8 character. qm/pctconfig fallbacks run with a timeout; the--checklock descriptor is not inherited by
child processes and the lock file is never truncated; the state directory's parent must not be
group/world-writable.- The
--checkstate lives in a0700directory, is written atomically with mode0600, is parsed
as validated data (never sourced), and parallel runs are prevented withflock.