github preston-peterson/aerodrome v3.3.1

latest releases: v3.4.136, v3.4.135, v3.4.134...
5 months ago

Two fixes to keep ntfy from ending up in silent-failure states, plus polish. Surfaced during the v3.3.0 prod migration (backup → uninstall → fresh install at /opt/aerodrome → restore): the restore correctly identified that the backup contained an Aerodrome-managed ntfy server but stashed the config to ntfy-server.yml.from-backup.<timestamp> and printed a "saved for manual review" message instead of actually re-installing ntfy. The user-visible result was a working dashboard but broken push notifications, with no clear pointer to the recovery step. v3.3.1 fixes this end-to-end and also tightens the related UX so users can't enable notifications in a state where they'd silently fail.

Fix #1 — auto-install ntfy during restore when the backup contains it. Previous behavior: restore checked install_status() and only wrote the ntfy server config when state was already aerodrome_managed. Anything else (including not_installed on a fresh install) stashed the config to a .from-backup sidecar and left the user to figure out the recovery. New behavior: when the backup contains ntfy/server.yml AND current state is not_installed, the restore calls install() from ntfy_installer.py first (idempotent, same install path the in-UI button uses), then overwrites the freshly-written default config with the backup's config, then restarts ntfy. Same outcome as the "already aerodrome_managed" path, just with one extra silent step at the front. Other non-managed states (external — user installed ntfy themselves via apt/dnf; system_managed — distro shipped it) still stash the config without auto-installing, because we never take over a user's own ntfy install. Warning message in the restore summary tells the user what happened: "Re-installed Aerodrome-managed ntfy server (was not present in the new install — restored from backup automatically)."

Fix #2 — gate the "Notifications enabled" checkbox when local ntfy is required but missing. Previous behavior: the Notifications tab let users check "Notifications enabled" regardless of whether the configured notifications.url was reachable. The most common silent-failure pattern: notifications.url points at http://localhost:2586/... but no local ntfy is installed yet. The checkbox saves fine, the UI looks correct, and every notification attempt POSTs into the void. New behavior: client-side, the checkbox disables and shows an inline warning ("⚠ Local ntfy not installed. Notifications would silently fail with this URL. Install local ntfy below, then re-check this box.") whenever the URL points at localhost/127.0.0.1 AND install_status() reports not_installed or partial. The check re-runs live when the user edits the URL field — switching the URL to https://ntfy.sh/your-topic immediately re-enables the checkbox. Server-side, the PUT /api/config endpoint runs the same check post-validation and rejects the save with a clear error message — defense in depth for raw API callers and stale browser tabs. Users with external ntfy URLs (ntfy.sh, custom servers, Tailscale tunnels) are unaffected; the gate only fires for the specific localhost-without-local-ntfy combination.

Polish items bundled along:

  • uninstall.sh step numbering. Three [N/5] labels were left over from when uninstall had five steps; the script grew to six (the ntfy-cleanup step + the synthetic-feeder service cleanup) but the labels weren't renumbered. Fixed to [1/6] through [6/6]. Cosmetic but jarring — visible in every uninstall output.
  • Python version-check error message. When python3 -c '...' failed entirely (broken interpreter, stale bytecode, bad site hooks — surfaced during v3.3.0 Arch dogfood on a VM with a corrupted Python 3.14 install), the bootstrap printed "Python 3.10+ required; found Python 3.14.4" and pointed at the deadsnakes PPA — none of which helped. v3.3.1 distinguishes the two failure modes: if python3 --version works but the version is too old → keep the existing deadsnakes hint. If python3 -c fails outright → show the actual error output (which previously was suppressed with 2>/dev/null), and offer a family-aware reinstall command (sudo apt-get install --reinstall python3 / sudo dnf reinstall python3 / sudo pacman -S python / sudo zypper install --force python3). The bootstrap detects the broken interpreter early, so the install never gets far enough to crash later in a more confusing way.

Why this matters operationally. The pattern across all four items is the same: a state where the system looks correct but functionally isn't, and where the user has no clear pointer to the recovery step. The fix in each case is either auto-recovery (ntfy on restore), prevention (gate the checkbox), or actionable diagnostics (Python error message). The architectural principle: when a check fails, the message should tell the user what to do, not just what's wrong.

Scope:

  • server.py — restore endpoint auto-install branch (~50 lines); PUT /api/config post-validation ntfy check (~30 lines)
  • templates/config.html — loadNtfyStatus() updated to call new _updateNotificationsEnabledGate() helper; live input event listener on the URL field; gate enforces the disable/re-enable based on URL + ntfy state (~70 lines of new JS, no removal)
  • scripts/bootstrap.sh — Python version check rewritten to distinguish broken-interpreter from old-version, family-aware reinstall hint
  • uninstall.sh — three [N/5] labels corrected to [N/6]
  • No data-plane changes, no config schema changes, no sudoers changes — purely UX hardening on the migration + setup paths.

Operational note: the v3.3.0 prod migration hit the exact restore-stashes-ntfy pattern this fix addresses. The forward path on existing prod installs is unchanged — click "Install local ntfy" on the Notifications tab once, then the test notification button to verify the topic + base_url. After v3.3.1 deploys, future restores will auto-install ntfy if it ever needs to be re-installed.

Don't miss a new aerodrome release

NewReleases is sending notifications on new releases.