Tray state icon and window picture; firewall rules without the comment match; macOS app bundle
The tray icon is dark red with no connection (or a lost exit node), blue when connected and green while an exit node is in use; the windows get the logo and an app id that matches the desktop entry, and the exit icon moves to the bottom left of the tile. Exit-node and broadcast firewall rules fall back to being recognised by their shape on kernels that have no `comment` match, as small router builds do. The macOS archive carries Tsunagi.app for the Homebrew cask, and the daemon plist opens the control socket to the admin group. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
c9c653023d
commit
0cfc1cbafc
14 files changed
+692
-90
No files matched your search
Vendored
+1
@@ -9,3 +9,4 @@ Terminal=false
|
||||
Categories=Network;Utility;
|
||||
Keywords=mesh;vpn;overlay;network;
|
||||
StartupNotify=false
|
||||
StartupWMClass=tsunagi-tray
|
||||
Vendored
+14
@@ -27,6 +27,20 @@ shell started `sudo`:
|
||||
| disposable cache | `/var/db/tsunagi/cache` |
|
||||
| control socket | `/var/run/tsunagi/agent.sock` |
|
||||
|
||||
## Homebrew
|
||||
|
||||
```sh
|
||||
brew tap house-of-vanity/tap
|
||||
brew install --cask tsunagi-gui # the tray app, and the agent it needs
|
||||
# or just the command line agent:
|
||||
brew install tsunagi
|
||||
sudo brew services start tsunagi # the agent, as a root daemon at boot
|
||||
```
|
||||
|
||||
The cask starts the service for you. The agent runs as root, and its control
|
||||
socket is open to the `admin` group, so the CLI and the tray work without
|
||||
`sudo` for an administrator.
|
||||
|
||||
## Native deployment — root LaunchDaemon
|
||||
|
||||
For an always-on agent that starts at boot, install the bundled
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Wrap the tray GUI in a macOS application bundle, so it can be installed as an
|
||||
# app (a Homebrew cask, or dragging it to /Applications) instead of being a bare
|
||||
# executable.
|
||||
#
|
||||
# Usage: build-app.sh <tray_binary> <version> <output.app>
|
||||
# <tray_binary> the built tsunagi-tray executable
|
||||
# <version> the release version (the tag without its leading v)
|
||||
# <output.app> the bundle to create; replaced if it exists
|
||||
#
|
||||
# It is a menu-bar app: LSUIElement keeps it out of the Dock and the app
|
||||
# switcher, and the tray starts the window as a second process of the same
|
||||
# executable, which inherits that. The bundle is signed ad hoc where `codesign`
|
||||
# exists (the macOS runner), because arm64 will not run unsigned code; it is not
|
||||
# notarised, so a downloaded copy needs its quarantine flag cleared, which the
|
||||
# cask does.
|
||||
set -euo pipefail
|
||||
|
||||
tray="$1"
|
||||
version="$2"
|
||||
app="$3"
|
||||
|
||||
# CFBundleShortVersionString is dotted numbers only; 0.1.0-rc.22 becomes 0.1.0.
|
||||
short="${version%%-*}"
|
||||
|
||||
rm -rf "$app"
|
||||
mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources"
|
||||
install -m 0755 "$tray" "$app/Contents/MacOS/tsunagi-tray"
|
||||
|
||||
cat > "$app/Contents/Info.plist" <<PLIST
|
||||
<?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>CFBundleName</key>
|
||||
<string>Tsunagi</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Tsunagi</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>cy.hexor.tsunagi.tray</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>tsunagi-tray</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${short}</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${short}</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.0</string>
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
PLIST
|
||||
|
||||
if command -v codesign >/dev/null 2>&1; then
|
||||
codesign --force --deep --sign - "$app"
|
||||
fi
|
||||
|
||||
echo "built $app"
|
||||
Vendored
+9
@@ -36,6 +36,15 @@
|
||||
<key>ThrottleInterval</key>
|
||||
<integer>10</integer>
|
||||
|
||||
<!-- The control socket belongs to the admin group, so the CLI and the tray
|
||||
work without sudo for any administrator. A plain account is not in it
|
||||
and cannot manage the agent. -->
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>TSUNAGI_CONTROL_GROUP</key>
|
||||
<string>admin</string>
|
||||
</dict>
|
||||
|
||||
<!-- Logs. launchd creates these as root; rotate them with newsyslog if you
|
||||
keep the daemon around. -->
|
||||
<key>StandardOutPath</key>
|
||||
|
||||
Reference in new issue
Block a user