2026-10-21 14:54:07 +01:00
2026-10-21 14:50:13 +01:00
2026-10-21 14:34:16 +01:00
2026-10-21 14:54:07 +01:00
2026-10-21 14:54:07 +01:00
2026-10-21 14:54:07 +01:00
2026-10-21 14:34:16 +01:00
2026-10-21 14:54:07 +01:00
2026-10-21 14:07:45 +01:00
2026-10-21 14:34:16 +01:00

Pegasus Monitor

Native macOS SwiftUI menu-bar health monitor for Pegasus.

Setup on Pegasus (Ubuntu)

The existing /usr/local/bin/pegasus-health must support --verbose and use the updated checks (no Time Machine, Domino at 192.168.1.50, Cockpit at 192.168.1.2, and saturn.absdev.net). The adapter does not replace or modify that existing script.

Copy server/pegasus-health-json to Pegasus then install:

sudo install -o root -g root -m 755 pegasus-health-json /usr/local/bin/pegasus-health-json
sudo /usr/local/bin/pegasus-health-json | python3 -m json.tool | head -30

For the app to poll automatically, configure restricted passwordless sudo for the JSON command only. Run sudo visudo -f /etc/sudoers.d/pegasus-health-monitor and enter:

mag ALL=(root) NOPASSWD: /usr/local/bin/pegasus-health-json

Both /usr/local/bin/pegasus-health-json and /usr/local/bin/pegasus-health must be root-owned and not writable by mag or any other non-root user. Do not grant NOPASSWD to arbitrary commands or to python3 globally. The adapter executes only the fixed health command and accepts no user-controlled command strings.

From your Mac confirm:

ssh -o BatchMode=yes mag@192.168.1.2 'sudo -n /usr/local/bin/pegasus-health-json' | python3 -m json.tool | head -35

Use SSH keys and trust the host key from an interactive SSH login before first running the app. The macOS app uses BatchMode=yes and StrictHostKeyChecking=yes, and will not present password prompts.

Build on macOS

Open PegasusMonitor.xcodeproj in Xcode and choose the PegasusMonitor scheme. Set your signing team as appropriate, then Build & Run. The app requires macOS 14.0 or newer. No third-party dependencies are required.

The app appears as a status icon in the macOS menu bar, not the Dock. It polls every five minutes by default (configurable), shows 14 aggregated categories and per-check diagnostics, and sends notifications when a previously healthy server becomes unhealthy. The server JSON adapter is read-only; it never restarts services.

Diagnostics

  • ssh -v mag@192.168.1.2: confirm SSH key authentication.
  • sudo -n /usr/local/bin/pegasus-health-json: confirm restricted sudo.
  • A non-zero SSH command exit code of 1/2 can indicate warnings/failures; the tool still emits JSON.
  • A missing required check is classified as fail, not green.
  • VM NRPC checks confirm TCP reachability; backup checks do not validate Borg archive integrity.

Design

PegasusMonitorApp.swift: MenuBarExtra entry and Settings scene. ServerMonitor.swift: async SSH runner, JSON decoding, polling and notifications. MonitorMenuView.swift: summary and drill-down details. SettingsView.swift: SSH configuration and interval. server/pegasus-health-json: read-only JSON adapter for the existing health script.

Build and release scripts

Run from the project root:

./Scripts/build.sh                     # Debug build; launches the app
LAUNCH_AFTER_BUILD=0 ./Scripts/build.sh # Debug build without launching
./Scripts/release.sh                   # Signed Release DMG in dist/
NOTARY_PROFILE=your-profile ./Scripts/release.sh # Notarize + staple DMG
ALLOW_UNSIGNED=1 ./Scripts/release.sh # Local testing only

Release automatically selects the first Developer ID Application identity from the login keychain, or honors SIGNING_IDENTITY. It requires an identity unless ALLOW_UNSIGNED=1. Signing and notarization do not happen in build.sh. Script-built artifacts are written to .build/ and dist/. The DMG is assembled after successful compilation and signing. These scripts do not change Xcode project version numbers; change MARKETING_VERSION and CURRENT_PROJECT_VERSION in Xcode before a release.

S
Description
No description provided
Readme
141 MiB
Languages
Makefile 71.6%
C++ 10.7%
Swift 9.8%
Python 6.9%
Shell 0.9%