The master PNG was fully opaque, so its white corners showed as a square frame once macOS composited the icon onto its rounded plate. Swap in the auditor-mode artwork, which has transparent corners. Signed-off-by: Ludovic Vielle <ludovic@probo.com>
10 KiB
Release probo-agent
After confirming commits below, follow the common steps.
Track facts
- Tag pattern:
probo-agent/v* - Version source:
cmd/probo-agent/VERSION(singleX.Y.Zline) - Version bump: Edit
cmd/probo-agent/VERSIONdirectly - Changelog:
cmd/probo-agent/CHANGELOG.md - Files to stage:
cmd/probo-agent/VERSION,cmd/probo-agent/CHANGELOG.md - Workflow:
.github/workflows/release-probo-agent.yaml - Path filter:
cmd/probo-agent pkg/deviceagent
Detect commits
git log $(git describe --tags --abbrev=0 --match='probo-agent/v*')..HEAD --oneline \
-- cmd/probo-agent pkg/deviceagent
If empty or non-user-facing only, do not release this track.
Build
make bin/probo-agent
On macOS hosts, make enables CGO so the menu bar enrollment helper
is included. Windows tray support is pure Go (CGO_ENABLED=0). Linux
and FreeBSD builds stay pure Go (no tray).
Notes
CI builds binaries for linux, windows, and freebsd (amd64/arm64) on
Linux runners, and builds CGO-enabled darwin archives plus a
signed/notarized fat .pkg on a macOS runner. The GitHub
Release includes those archives, probo-agent_*_darwin.pkg,
install.sh, signed checksums, SBOM, and build attestations. The agent
auto-update path downloads the matching archive plus checksums.txt and
verifies the cosign bundle before installing.
The menu bar / tray enrollment flow is macOS and Windows only.
Linux and FreeBSD use probo-agent install --server … --enrollment-token … from the shell, or the curl-to-sh installer
documented below. Windows release binaries are cross-compiled from
Linux with CGO_ENABLED=0 (tray is pure Go). macOS release binaries
and the .pkg are built on macOS with CGO_ENABLED=1.
macOS .pkg (MDM / GUI install)
Release and local builds use
cmd/probo-agent/installer/macos/build.sh (requires macOS, a
pre-built fat binary via lipo, and the Swift toolchain).
Signing is mandatory: CODESIGN_IDENTITY and APPLE_TEAM_ID
must be set. The script compiles Probo Agent.app (the headless
probo:// URL handler + privileged helper) from
cmd/probo-agent/installer/macos/enroll-ui/, signs nested Mach-Os
then the app bundle, optionally signs the product with
INSTALLER_IDENTITY, and notarizes/staples when APPLE_ID and
APPLE_ID_PASSWORD are set (password is stored into a keychain
profile; submits use --keychain-profile so the secret is not on
notarytool submit argv).
The Finder/Dock icon for Probo Agent.app comes from a single master
PNG, cmd/probo-agent/installer/macos/enroll-ui/Resources/icon-original.png
(Probo square mark). At PKG build time build.sh pads/resizes it with
sips, compiles AppIcon.icns with iconutil under the build stage
directory, and installs it into Contents/Resources/. Info.plist
sets CFBundleIconFile to AppIcon. Do not commit generated
.icns / iconset PNGs.
The master PNG must have the rounded-square mark pre-baked with fully
transparent corners. macOS composites legacy .icns icons onto a light
rounded plate, so any opaque pixel outside the rounded square renders as
a visible square frame around the mark.
There is no unsigned PKG path and no osascript elevation fallback.
Local testing of browser enrollment requires a Developer ID–signed
build. CLI enrollment without the app uses sudo probo-agent install.
# Local signed pkg (example)
export CODESIGN_IDENTITY="Developer ID Application: Probo Inc (TEAMID)"
export INSTALLER_IDENTITY="Developer ID Installer: Probo Inc (TEAMID)"
export APPLE_TEAM_ID="TEAMID"
GOOS=darwin GOARCH=arm64 CGO_ENABLED=1 go build -o dist/probo-agent_arm64 ./cmd/probo-agent
GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 go build -o dist/probo-agent_amd64 ./cmd/probo-agent
lipo -create dist/probo-agent_arm64 dist/probo-agent_amd64 -output dist/probo-agent_universal
cmd/probo-agent/installer/macos/build.sh \
--binary dist/probo-agent_universal \
--version "$(cat cmd/probo-agent/VERSION)"
PKG postinstall always installs the global tray LaunchAgent, registers
probo://, and installs the privileged helper
(com.probo.agent.helper) under /Library/PrivilegedHelperTools as
root. The only admin authentication is the normal macOS Installer
prompt for the PKG itself. The LaunchDaemon for probo-agent run is
created only after enrollment (probo-agent install, deep link, or MDM
/tmp/probo-agent.conf).
Browser enrollment uses Probo Agent.app over XPC to the
PKG-installed helper — no SMJobBless and no admin prompt on the enroll
path. A missing or dead helper surfaces an error asking to reinstall
the package.
Manual QA checklist (macOS PKG):
- Fresh signed PKG: Installer may ask for admin once; deep link enrolls with no further prompt.
- Repeat deep link on an enrolled device: no prompt, immediate success.
- After
sudo make -C cmd/probo-agent uninstall, deep link fails with a clear “reinstall package” error (no osascript). sudo make -C cmd/probo-agent uninstallremoves daemon, tray, helper, app, and state.- MDM
/tmp/probo-agent.confpostinstall still enrolls without a browser prompt. - Notarized PKG passes Gatekeeper;
codesign --verify --deepsucceeds on the app bundle. - Unsigned
build.shexits with an error requiringCODESIGN_IDENTITY.
Apple signing secrets (GitHub)
The build-macos job in release-probo-agent.yaml expects the same
secret names as the auditor-mode release workflow. Configure these on
the probo GitHub repository (or org) before tagging a release:
| Secret | Purpose |
|---|---|
APPLE_CERTIFICATE |
Base64-encoded .p12 (Developer ID) |
APPLE_CERTIFICATE_PASSWORD |
.p12 password |
KEYCHAIN_PASSWORD |
Ephemeral CI keychain password |
CODESIGN_IDENTITY |
e.g. Developer ID Application: Probo Inc (TEAMID) |
INSTALLER_IDENTITY |
e.g. Developer ID Installer: Probo Inc (TEAMID) |
APPLE_ID |
Apple ID email for notarytool store-credentials |
APPLE_ID_PASSWORD |
App-specific password (stored into a keychain profile; not passed to submit) |
APPLE_TEAM_ID |
10-character Team ID |
Local notarization uses the same env vars as CI:
export APPLE_ID="you@example.com"
export APPLE_ID_PASSWORD="app-specific-password"
# optional: NOTARYTOOL_KEYCHAIN_PROFILE=probo-agent-notary (default)
Windows enrollment is browser-driven: the console issues a
probo://enroll?server=...&token=... deep link handled by
Probo Agent.app on macOS (PKG-installed helper + XPC) or
probo-agent enroll-url on Windows. After install, register the protocol for the
current user with
cmd/probo-agent/installer/windows/register-protocol.ps1 (per-user
HKCU handler pointing at probo-agent.exe). The system tray helper
(probo-agent tray) shows enrollment status; enrollment itself happens
in the browser.
Region labels and console URLs for the macOS installer HTML live in
cmd/probo-agent/installer/regions.json. A Go test keeps US/EU URLs in
sync with pkg/deviceagent/server_url.go.
Install script
cmd/probo-agent/installer/install.sh is published as install.sh on each
probo-agent/v* GitHub Release. It supports Darwin, Linux, and FreeBSD.
Each published install.sh pins one release: the release workflow injects
the tag and archive SHA-256 checksums into the script before upload.
# Interactive — curl install.sh from the target release
curl -fsSL "https://github.com/getprobo/probo/releases/download/probo-agent/vX.Y.Z/install.sh" | sudo sh
# Unattended / MDM
curl -fsSL "…/install.sh" | sudo \
PROBO_SERVER_URL=https://us.probo.com \
PROBO_ENROLLMENT_TOKEN='…' sh
# Mirror release assets (PROBO_AGENT_RELEASE_BASE must end with the embedded tag)
PROBO_AGENT_RELEASE_BASE="https://mirror.example/probo-agent/vX.Y.Z" \
curl -fsSL "…/install.sh" | sudo sh
The script downloads only the matching platform archive and verifies its
SHA-256 against checksums embedded in install.sh at release time. This
anchors trust to the script the user already obtained, rather than a
co-downloaded checksums.txt. Post-install upgrades still use cosign
bundle verification via the agent auto-update path.
The script installs the binary to /usr/local/bin/probo-agent, then runs
probo-agent install to enroll and start the OS service. Agent state defaults
to /var/lib/probo-agent (override with --dir or PROBO_AGENT_STATE_DIR).
Environment variables:
| Variable | Purpose |
|---|---|
PROBO_AGENT_RELEASE_BASE |
Override release download base URL (must match embedded tag) |
PROBO_AGENT_RELEASE_TAG |
Override embedded release tag (local dev) |
PROBO_AGENT_SKIP_CHECKSUM_VERIFY |
Skip SHA-256 verification (local dev only) |
PROBO_AGENT_STATE_DIR |
Agent state directory (--dir; default /var/lib/probo-agent) |
PROBO_SERVER_URL |
Probo server base URL (skip interactive prompt) |
PROBO_ENROLLMENT_TOKEN |
One-shot enrollment token (skip interactive prompt) |
PROBO_NO_AUTO_UPDATE |
Set to true to pass --no-auto-update |
Never pass the enrollment token in the curl URL.
Local install (macOS PKG)
Primary loop for testing browser enrollment (app + privileged helper):
export CODESIGN_IDENTITY="Developer ID Application: … (TEAMID)"
export INSTALLER_IDENTITY="Developer ID Installer: … (TEAMID)" # optional
export APPLE_TEAM_ID="TEAMID"
make -C cmd/probo-agent install # uninstall leftovers → build PKG → installer
make -C cmd/probo-agent uninstall # full system teardown (idempotent)
make -C cmd/probo-agent clean # uninstall + wipe dist/ caches / enroll-ui/.build
install always runs uninstall first so previous helpers, apps, and
Launch Services registrations cannot shadow the new build. Signing env
vars are required for pkg / install on Darwin.
CLI-only install (no app / helper)
Binary-only path via installer/install.sh (any Unix). State under
~/.local/share/probo-agent-dev; staging under ~/.cache/probo-agent-dev.
make -C cmd/probo-agent install-cli \
PROBO_SERVER_URL=https://us.probo.com \
PROBO_ENROLLMENT_TOKEN='…'
make -C cmd/probo-agent run