Skip to main content

Overview

Use this guide when you want a Jamf Pro policy to install Beacon for macOS users and forward both runtime and inventory telemetry to AWS S3 without asking end users to configure anything manually. The end state is:
  • Beacon is installed under /opt/beacon.
  • The system endpoint collector runs as a LaunchDaemon.
  • Claude Code hooks are installed for the logged-in console user.
  • Runtime activity is written to /var/log/beacon-agent/runtime.jsonl.
  • Agent config inventory is written to /var/log/beacon-agent/inventory_state.jsonl.
  • Vector forwards both JSONL streams to S3:
    • s3://<bucket>/<prefix>/runtime/date=YYYY-MM-DD/...
    • s3://<bucket>/<prefix>/inventory/date=YYYY-MM-DD/...

Prerequisites

Before creating the Jamf policy, prepare:
  • A signed and notarized Beacon endpoint .pkg that includes /opt/beacon/bin/vector.
  • A target AWS S3 bucket.
  • An S3 prefix root such as beacon, beacon-prod, or beacon-e2e.
  • AWS credentials or a role available to the Jamf policy at install time.
  • s3:PutObject permission for the selected bucket prefix.
  • Claude Code installed on the target Mac.
Use a root prefix. Do not include runtime or inventory in the value:
The helper normalizes old prefixes ending in /runtime or /inventory, but new deployments should use the root prefix.

AWS Permission

Use a bucket policy or IAM policy scoped to the Beacon prefix. Example:
Beacon does not store AWS credentials in endpoint configuration. The Jamf helper persists only the AWS provider-chain values it receives into a root-owned Vector environment file:
That file is mode 0600 and is sourced by the Vector LaunchDaemon wrapper.

Jamf Policy Setup

Jamf Pro separates package installation from script execution. Use the Packages payload to install the Beacon .pkg, then use a Scripts payload to run a small wrapper that calls Beacon’s packaged Jamf helper. For the most reliable rollout, use two policies:
  • Policy 1: Install Beacon package. Installs the signed .pkg.
  • Policy 2: Configure Beacon S3 forwarding. Runs after the package is installed and calls the packaged helper.
You can also combine package and script payloads in one policy if your Jamf workflow guarantees the package is installed before the script runs. The two-policy approach is easier to reason about and troubleshoot.

1. Upload The Beacon Package

Upload the signed Beacon endpoint package to Jamf Pro and add it to a policy using the Packages payload with the install action. The package installs:

2. Add A Jamf Script Wrapper

Add a script to Jamf Pro that invokes Beacon’s packaged helper. The script must exist in Jamf Pro before it can be added to a policy.
Use Jamf script parameter labels so policy editors know what each value means: Jamf script parameters are convenient for non-secret values such as bucket, region, and prefix. For AWS credentials, prefer your Jamf secret injection mechanism, device identity, AWS profiles, web identity, or managed credential files. Avoid putting long-lived access keys directly in ordinary policy parameter fields or policy logs.

3. Inject AWS Provider Settings

The Beacon helper persists any AWS provider-chain variables it receives. Use one of these patterns: For a local test, this is equivalent to:

4. Optionally Enable Endpoint Self-Updates

Beacon package self-updates are off by default. To let Beacon apply future signed package updates after the Jamf install, add a Jamf Files and Processes payload or post-install policy command:
Enable automatic package self-updates
For visibility without automatic package installation, enable check-only mode instead:
Enable check-only update monitoring
Both commands require root. auto mode downloads newer compatible signed packages from the release manifest after checksum, Developer ID signature, and Gatekeeper verification. check-only mode writes update status events to /var/log/beacon-agent/system.jsonl without downloading or applying packages.

What The Helper Does

The combined helper performs all endpoint and forwarding setup:
  • Repairs the Beacon system endpoint.
  • Starts com.beacon.endpoint.collector.
  • Prepares:
    • /var/log/beacon-agent/runtime.jsonl
    • /var/log/beacon-agent/inventory_state.jsonl
    • /var/log/beacon-agent/inventory-state.json
  • Grants the console user append access for hook-written logs.
  • Installs Claude Code hooks for the interactive console user.
  • Writes:
    • /Library/Application Support/Beacon/Forwarders/s3-vector.toml
    • /Library/Application Support/Beacon/Forwarders/s3-vector.env
    • /Library/LaunchDaemons/com.beacon.endpoint.s3-forwarder.plist
  • Starts com.beacon.endpoint.s3-forwarder.
End users do not need to run any Beacon command or edit any local config.

Expected S3 Layout

If you configure:
Beacon writes objects under:
Runtime objects contain agent activity from runtime.jsonl. Inventory objects contain inventory.heartbeat and inventory.snapshot events from inventory_state.jsonl.

Validate A Deployed Mac

Run these commands on a target Mac after the Jamf policy completes.

Check Services

Both services should be running.

Check Local Files

Check Vector Config

Expected:
Runtime forwarding starts at the end of the runtime log so historical session activity is not backfilled when Vector is first installed. Inventory forwarding starts at the beginning of inventory_state.jsonl so the first inventory snapshot is not missed if the file was created before Vector began watching it.

Generate Test Events

Runtime Event

Write a synthetic runtime validation event:

Inventory Event

Write an inventory heartbeat and snapshot:
Confirm both files have events:

Confirm S3 Delivery

Vector batches uploads. Production configs use timeout_secs = 300, so allow up to five minutes unless you lower the batch timeout for a demo.
Inspect the latest inventory object:

Live Demo Settings

For a live demo, reduce the inventory TTL:
Reduce Vector S3 batch timeout:
Restart the forwarder:
If launchd returns Bootstrap failed: 5, run Vector in the foreground for the demo:
Keep that terminal open while generating runtime and inventory events.

Test A Live Skill And MCP Change

Create a Claude Code skill:
Add a Claude Code MCP server to top-level mcpServers in ~/.claude.json:
Then force inventory:
Confirm the local inventory event includes both names:
After Vector flushes, the same names should appear in an object under the S3 inventory/ prefix.

Restore Production Settings

After a demo, restore the production TTL:
Regenerate the Vector config by rerunning the Jamf helper if you changed timeout_secs manually:

Troubleshooting

No S3 Objects

Check the forwarder:

Forwarder Is Not Loaded

If launchctl reports Could not find service "com.beacon.endpoint.s3-forwarder", first confirm the managed files are still present:
If the plist exists, load it:
If the LaunchDaemon files exist but you want an idempotent repair, rerun the packaged S3 installer using the saved environment. This rewrites the Vector config, environment file, and plist, then starts the forwarder:
For Jamf remediation, scope a policy to devices where the S3 forwarder is not loaded:
Then run this script on those devices, or on all Beacon devices if the original S3 env file should already exist everywhere:
If launchd remains opaque after the repair, run Vector in the foreground:

Credentials Are Missing

Check the env file without exposing secrets:

Inventory Is Empty

Force inventory and inspect the local file:

Claude Hooks Are Missing

Fully restart Claude Code after the Jamf policy runs. Then inspect the user’s Claude settings:
You should see commands that call the packaged Beacon hook binary.