net-tools/tray/install-tray.sh
Natalie 6e6512abf6 fix(tray): own the menu-bar tray with a RunAtLoad+KeepAlive LaunchAgent
The tray's Quit handler already boots out com.wireguard.vpn-tray, but install-tray.sh
had retired that launchd job and relied on the fleet agent to nohup it — which never
ran the tray reliably at boot (no GUI session yet). Restore the LaunchAgent (same
pattern as com.lilith.mac-sync): RunAtLoad starts it at login in the GUI session,
KeepAlive relaunches on crash. ensure_tray() now defers to launchd when the agent is
installed (Popen path kept as fallback). Removes the dead standalone plist.
2026-06-22 22:39:11 -04:00

70 lines
2.9 KiB
Bash
Executable file

#!/bin/bash
# install-tray.sh — enable the menu-bar tray (darwin, user scope).
# Installs a per-user LaunchAgent (RunAtLoad + KeepAlive) that owns the tray —
# same pattern as com.lilith.mac-sync. launchd starts it at login (in the GUI
# session, so the menu-bar icon reliably appears) and relaunches it if it
# crashes. The tray's "Quit" handler boots out this same LABEL and drops the
# .tray-disabled flag, and the fleet agent's ensure_tray() is gated by that flag,
# so all three stay coherent. Run as the console USER (no sudo). Idempotent.
set -euo pipefail
if [ "$(uname -s)" != "Darwin" ]; then
echo "tray is darwin-only (menu bar app)" >&2
exit 1
fi
if [ "$EUID" -eq 0 ]; then
echo "run as the console user, not root (or let install-agent.sh call this via sudo -u)" >&2
exit 1
fi
TRAY_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_DIR="$(dirname "$TRAY_DIR")"
LABEL="com.wireguard.vpn-tray"
DISABLED="$REPO_DIR/data/.tray-disabled"
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
if [ ! -x "$TRAY_DIR/.venv/bin/python" ]; then
echo "==> bootstrapping venv"
python3 -m venv "$TRAY_DIR/.venv"
"$TRAY_DIR/.venv/bin/pip" install -q -r "$TRAY_DIR/requirements.txt"
fi
# Clear the user-quit flag — re-running this script means "bring the tray back".
rm -f "$DISABLED"
# Write the LaunchAgent. KeepAlive.SuccessfulExit=false → relaunch on crash but
# respect a clean menu Quit (exit 0). RunAtLoad → start at login.
mkdir -p "$HOME/Library/LaunchAgents"
cat > "$PLIST" <<PLISTEOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>$LABEL</string>
<key>EnvironmentVariables</key>
<dict><key>PATH</key><string>$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string></dict>
<key>ProgramArguments</key>
<array>
<string>$TRAY_DIR/.venv/bin/python</string>
<string>$TRAY_DIR/vpn_tray.py</string>
</array>
<key>WorkingDirectory</key><string>$TRAY_DIR</string>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key>
<dict><key>SuccessfulExit</key><false/></dict>
<key>ThrottleInterval</key><integer>30</integer>
<key>StandardOutPath</key><string>/tmp/vpn-tray.log</string>
<key>StandardErrorPath</key><string>/tmp/vpn-tray.err</string>
</dict>
</plist>
PLISTEOF
# Hand the single tray process to launchd: kill any ad-hoc instance, (re)bootstrap.
pkill -f vpn_tray.py 2>/dev/null || true
launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true
launchctl bootstrap "gui/$(id -u)" "$PLIST"
launchctl kickstart -k "gui/$(id -u)/$LABEL" 2>/dev/null || true
sleep 2
echo "==> $(pgrep -fl vpn_tray.py | head -1 || echo 'NOT RUNNING (see /tmp/vpn-tray.err)')"
echo "==> launchd-managed (RunAtLoad + KeepAlive). Menu Quit boots it out + sets .tray-disabled."