Download Latest Version remotepower-3.2.1.tar.gz (7.6 MB)
Email in envelope

Get an email when there's a new version of remotepower

Home / v3.0.2
Name Modified Size InfoDownloads / Week
Parent folder
README.md 2026-05-24 16.8 kB
v3.0.2 source code.tar.gz 2026-05-24 4.6 MB
v3.0.2 source code.zip 2026-05-24 4.7 MB
Totals: 3 Items   9.3 MB 0

v3.0.2 — multi-webhook, self-monitoring, IaC generator, mitigation, ACME, AI

Covers v2.6.1 → v3.0.2 (everything since v2.6.0 was tagged).

═══════════════════════════════════════════════════════════════════ NEW FEATURES ═══════════════════════════════════════════════════════════════════

Multi-webhook destinations (v3.0.2)

  • Up to 20 destinations, each with its own format adapter: Discord (severity-coloured embed), Slack (markdown), Pushover (form-encoded with token+user, internal priority mapped, critical stays at high not emergency), Microsoft Teams (MessageCard), ntfy.sh (plain body + Title/Priority/Tags headers), generic JSON.
  • Per-destination filters: event allowlist, min-priority threshold.
  • Pushover credentials write-once-and-redacted in UI + backup export.
  • Per-destination test button using a synthetic config (no persistence).
  • Legacy webhook_url still honoured, deduplicated against the array.

Server self-monitoring (v3.0.2)

  • New "Server status" sidebar entry + GET /api/self/status endpoint.
  • Reports: process RSS, devices freshness, webhook success rate (24h + 7d), DATA_DIR disk usage + top 20 largest files, audit log size, scheduled backup state, fleet events archive size.

Scheduled backup (v3.0.2)

  • Daily gzipped tarball of /var/lib/remotepower triggered via heartbeat hook with 24h sentinel + stale-lock recovery.
  • Retention configurable (default 14 days). Excludes the backups directory itself, in-flight .tmp.* writes, existing .gz archives.
  • Owner/group stripped so restoring on a different host works.
  • Manual "Run backup now" button (POST /api/self/backup-now).

Bulk operations (v3.0.2)

  • Modal on the Devices page next to "Enroll device".
  • Filter by all monitored / by group / by tag.
  • Operations: package upgrade, reboot, shutdown, force package scan, force ACME rescan. Destructive ops require typing RUN.

Command palette + keyboard shortcuts (v3.0.2)

  • / and Ctrl-K open the global palette. Indexes pages, devices (cache primed on open), quick actions.
  • g-prefix navigation: g h/d/l/s/c/m/a/v.
  • ? shows the cheat sheet.

Settings search bar (v3.0.2)

  • Live filter across all setting sections. Per-tab match badges, dim tabs with zero matches, auto-switch when current tab has no hits. Re-indexes on every keystroke (handles dynamic sections).

Force ACME rescan (v3.0.2)

  • One-shot flag per device. Agent re-walks ~/.acme.sh on next heartbeat instead of waiting for the hourly cadence. Same flag-on-heartbeat-lock pattern as force-upgrade.

Exponential lockout ladder (v3.0.2)

  • Failed-login lockout escalates 10s → 1m → 5m → 30m → 2h per consecutive episode. Resets on successful login.

Audit log retention (v3.0.2)

  • Age-based eviction (default 90 days, configurable). Old entries moved to audit_log_archive.jsonl.gz instead of being dropped.

────────────────────────────────────────────────────────────────────

ACME / acme.sh integration (v3.0.1)

  • Agent walks ~/.acme.sh inventorying certs across the fleet.
  • Per-cert: domain, challenge type, provider, dates, status.
  • Issue/renew/remove via the Security → TLS / DNS expiry section.
  • acme.sh-not-installed devices hidden from the table; count surfaced as a discreet hint above (v3.0.2).

Mitigation runners with AI (v3.0.1)

  • 🩺 button on every Needs Attention card whose alert has a deterministic remediation. AI-generated playbook with operator sign-off; logged to mitigate_logs/<run_id>.json.

File-path log watching (v3.0.1)

  • Log rules can reference an arbitrary file path, not just a systemd unit. Useful for Tomcat, custom daemons, etc.
  • Dormant-file handling: fires once after 3 consecutive missing heartbeats then goes quiet — avoids alert fatigue.

IaC Generator (v3.0.0)

  • New top-level page generates Terraform/Ansible/Pulumi/Salt/ cloud-init from live host inventory.
  • 18 categories: OS & identity, packages, systemd, users, groups, SSH keys, networking, mounts, firewall, kernel modules, cron, timezone, etc. 5 output formats.
  • Server-side secret masking on env vars matching SECRET|TOKEN| PASSWORD|KEY patterns.

Security audits (v2.9.0)

  • Listening port audit — new ports fire new_port_detected.
  • SSH key audit — new authorized_keys fire ssh_key_added.
  • Brute-force detection — SSH + RemotePower-login fail tracking.
  • Disk-space items in Needs Attention.

Expanded log sources (v2.8.0)

  • Kernel log (dmesg), APT history, Proxmox snapshot ages.
  • snapshot_old webhook event (edge-triggered per VM).

TLS/DANE certificate monitoring (v2.6.1)

  • Cert expiry tracked across the fleet. tls_expiry webhook event fires once per cert when within the configurable threshold.
  • reboot_required webhook event fires once per host on first detection of /var/run/reboot-required (Debian/Ubuntu).
  • Stale-agent-version + Pending-reboot items in Needs Attention.

AI assistant (v2.7.0+)

  • Provider-agnostic chat: Anthropic, OpenAI, OpenAI-compatible, Ollama. Streaming responses. Custom system prompts per use case (free-form chat, explain command output, find problem in logs, mitigation playbook).
  • Privacy controls: send_hostnames, send_ips, send_journal, send_cmd_output. Project + fleet context injection.

Progressive Web App (v2.6.0 was first; ongoing iterations)

  • manifest.json + sw.js. Installable; cached shell.
  • sw.js CACHE_NAME versioned (current: remotepower-shell-v3.0.2) so activation cleans stale caches.

Host Configuration Management (v2.6.0)

  • Agent collects current host config snapshot.
  • Drift detection against baseline; config_drift webhook event.

═══════════════════════════════════════════════════════════════════ INFRASTRUCTURE / PERFORMANCE ═══════════════════════════════════════════════════════════════════

Per-request load() cache (v3.0.2)

  • CGI = fresh interpreter per request, but within one handler CONFIG_FILE was being parsed up to 4× per heartbeat. Cache deduplicates. Invalidated on save() and _save_held() (and on aborted _LockedUpdate exits).
  • Returns deep copies so caller mutations don't corrupt the cache.

Webhook delivery hardening (v3.0.2)

  • Per-device monitored=false suppresses webhooks for ALL events carrying a device_id, not just device_offline. Previously metric_warning/critical, service_, log_alert, cve_found, drift_detected, custom_script_, container_*, patch_alert, brute_force, ssh_key_added, tls_expiry, reboot_required, new_port_detected, snapshot_old, backup_stale, config_drift all bypassed the device's monitored flag.

═══════════════════════════════════════════════════════════════════ BUG FIXES ═══════════════════════════════════════════════════════════════════

Static-audit catches (v3.0.2):

  • _read_body() called in mitigation handlers but never defined — NameError, mitigation modal hit 500 on every click. Fixed to get_json_body().
  • chat_anthropic / chat_openai_compatible called bare from _call_ai_with_prompts but defined in ai_provider module. Prefixed.
  • current_username() referenced in three audit-log call sites but never defined; ACME Ignore/Cancel buttons appeared dead.
  • _get_disk_thresholds called at line 9193 but never defined, guarded by always-false callable(globals().get(...)) — per- mount disk threshold overrides silently ignored. Replaced with canonical _resolve_metric_thresholds.
  • server_url typo in agent force-upgrade path.
  • pacman --disable-sandbox probe was checking pacman --help instead of pacman -S --help. CachyOS silently failed.
  • Four undefined CSS variables (--bg-card, --bg-hover, --ok, --bg2, --bg3, --border2, --font-body) rendered with default browser colours in dark mode. Caught by a CSS-var sweep test; locked in via TestCssVarsDefined.

UI/UX fixes:

  • URL bar stuck at #settings/<tab> when navigating other pages (showPage didn't write history.replaceState; switchSettingsTab used location.hash directly).
  • Webhook test route mismatch (frontend /webhook-test, backend /webhook/test). Both aligned on the slash form.
  • Bulk modal rendered transparent (var(--bg-card) undefined).
  • Logs Search button silently froze on bad-regex 400 responses (TypeError reading data.results.length on {error: ...}).
  • Settings search bar cached the section index once on first call, missing dynamic sections like the webhook destinations list.
  • Command palette didn't have devices until you visited the Devices page first.
  • Pending updates dashboard tile counted unmonitored devices.
  • Drift + CVE dashboard tiles aggregated unmonitored devices.
  • Dashboard empty-state message clarified ("no critical CVE findings" instead of "no CVE findings").
  • ACME table no longer renders one row per device without acme.sh installed; suppressed count surfaced above.

Earlier fixes (v2.6.1 → v3.0.0):

  • CVE tile always showed 0 (dashboard read non-existent devices[].findings field).
  • Reboot/shutdown icon flash on mobile refresh (stale sw cache).
  • HTML structure errors from injected panes landing outside their parent containers.
  • JSON.stringify embedded in HTML attributes without escaping.
  • Three duplicate /devices GETs on the Monitor page (one per loader). Request coalescing added.

Security fixes (v2.3.2+):

  • PBKDF2-HMAC-SHA256 at 600k iterations replaced bare unsalted SHA-256 for password fallback.
  • must_change_password flag on default admin with persistent banner.
  • Backup export redacts secrets: Proxmox token, SMTP password, LDAP bind password, Pushover token + user.

═══════════════════════════════════════════════════════════════════ INTERNALS ═══════════════════════════════════════════════════════════════════

  • 1422 tests passing (up from ~1000 at v2.6.0).
  • AST audits: zero called-but-undefined names in any scope, zero respond() inside broad-Exception try blocks.
  • CSS-var coverage: zero undefined var(--xxx) across .js/.html/.css.
  • HTML balance: 1396
    /
    .
  • Make targets: test, lint, typecheck, check (test + lint), dist (runs full suite against staged tarball, fails on missing files).
  • .gitignore hardened: dist/, *.swp, .DS_Store, IDE dirs, build caches.
  • Demo seeder (packaging/seed-demo-data.py) updated to v3.0.2 schema: multi-webhook example with Pushover destination, audit retention, session TTLs, scheduled backup config, one unmonitored device to demonstrate the suppression behaviour.

Lint scope (make check): cmdb_vault.py, openapi_spec.py, test_v190.py, test_v1100.py. Expanding to api.py deliberately deferred — single reformat would produce an unreviewable diff.

═══════════════════════════════════════════════════════════════════ SECURITY AUDIT (completed in v3.0.2) ═══════════════════════════════════════════════════════════════════

End-to-end audit covering api.py + nginx config + agent + extended modules (WebTerm handshake, cmdb_vault, ldap_auth, TOTP, API keys, AI provider, Proxmox client). Findings + fixes:

Server:

  • CSRF defense-in-depth: _enforce_same_origin() runs before route dispatch. State-changing methods (POST/PUT/PATCH/DELETE) must carry no Origin/Referer (CLI/agents) or one matching Host. X-Token header was already CSRF-safe by CORS preflight; this is belt-and-suspenders against future regressions.
  • XSS in toast(): rendered msg via innerHTML without escape. Fixed with escHtml(msg). AI markdown renderer was already escape-first.
  • Optional SSRF guard: webhook_block_local config flag refuses POST to loopback/link-local/unspecified IPs (AWS metadata at 169.254.169.254 etc). RFC1918 deliberately allowed (homelab Gotify legitimate). Off by default.

Agent (client/remotepower-agent.py):

  • MEDIUM /tmp/ symlink attack on three marker files (last-cmd, poll-interval, pending-cmd.json). Moved to STATE_DIR = /var/lib/remotepower (mode 0700) with _safe_state_write/read/ unlink helpers using O_NOFOLLOW. /tmp/ fallback for non-root deploys uses O_NOFOLLOW + pre-unlink.
  • MEDIUM credentials write race in save_credentials: write_text then chmod left file world-readable in the window. Replaced with os.open(O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0o600) + pre-unlink + CONF_DIR forced to 0700.
  • MEDIUM server-controlled log_watch paths: could exfiltrate /etc/shadow etc via heartbeat-back. Added _file_log_path_allowed() with deny list (/etc/shadow, /etc/gshadow, /etc/sudoers, /root/.ssh/, /home//.ssh/, /proc/, /sys/, /dev/) using os.path.realpath() to defeat symlink bypass.
  • LOW URL scheme strip bug: lstrip('http://').lstrip('https://') strips characters not prefix. 'httpserver.com' → 'server.com'. Fixed with _strip_url_scheme() helper.
  • LOW AI provider dead code: insecure_ssl flag documented but never honored. Now implements documented behaviour matching proxmox_client.py pattern.

Confirmed safe (no changes needed):

  • shell=True on exec: commands — BY DESIGN, the product feature.
  • TLS: CERT_REQUIRED + check_hostname=True; http_post() rejects non-HTTPS.
  • Self-update: SHA-256 + hmac.compare_digest, atomic via mkstemp + shutil.move.
  • All other subprocess: argv-list, no shell injection.
  • WebTerm handshake: admin re-auth required, 32-byte tokens, one-shot use, source IP captured, fully audit-logged.
  • cmdb_vault: AES-GCM + PBKDF2 600k iter (OWASP 2023 min), key never persisted server-side, no log leakage.
  • LDAP: TLS verification on by default (CERT_REQUIRED).
  • TOTP: 160-bit secret via secrets.token_bytes(20), RFC 4226.
  • API keys: secrets.token_urlsafe(40) = 320 bits, never returned after creation, hmac.compare_digest verification, 50-key cap.
  • Audit log + debug log: no secrets leaked.

Audit scope NOT covered (out of scope or low risk, deferred):

  • remotepower-webterm daemon binary (separate repo).
  • PowerShell client (install-client.ps1) — separate platform.
  • prometheus_export, smtp_notifier, cve_scanner, containers, tls_monitor, openapi_spec, ai_context — data processing, no external attack surface.

Tests added: 19 for the audit (10 agent + 4 NA coverage + 2 multi- webhook suppression parity + 2 uptime seeder + 1 sentinel). Full posture, threat model, operator hardening checklist: docs/security.md

═══════════════════════════════════════════════════════════════════ KNOWN ISSUES (deferred to v3.1.x) ═══════════════════════════════════════════════════════════════════

  • Mobile layout collapse on some viewports — blocked on a Chrome Console error trace.
Source: README.md, updated 2026-05-24