Rune Gurd docs

Packages and device management

Platform support, MDM and package installs, enrollment, and retiring a device. For the one-command install, see [Install and enroll](install.md).

Install with your agent

An administrator can have their own AI agent CLI, such as Claude Code or Codex, install Guard on their computer. The Console's Deployment page offers Install with your agent: a prompt to paste into the agent, and the one-time enrollment token as a file to save in your Downloads folder.

The prompt tells the agent to check that the token file exists without reading it, verify the installer's signature against the release key the prompt carries, run the installer with --token-file (-TokenFile on Windows), delete the token file, install hooks and report what guard doctor and guard cloud status say. The token never goes into the prompt or the agent's transcript. If a transcript ever shows it, revoke the token in the Console.

Installing needs administrator rights. When the agent's shell can't answer a sudo prompt or isn't elevated, it stops and asks you to run that step. On macOS you still grant Full Disk Access by hand.

Enrollment records the agent CLI that ran it, if any, and the Console's install report and audit log show it. A local program can imitate an agent's name, so this is a record, not proof.

What the agent uses

The sensor aims to stay under 1% of one core and 50 MiB of memory when idle, and under 100 MiB under load.

In our tests, a settled idle sensor used under 1% of a core and about 30 MiB, on a Windows laptop (Core i5, 8 GB) and on a Linux virtual machine. Those are single test machines, not guarantees, and macOS isn't included.

Its first start after an install or upgrade costs more, once. Heavy file or network activity also costs more, and can slow that activity down.

Platform status

Guard supports macOS, Linux and Windows.

Platform Agent Status
macOS Rune Guard.app with the guard-sensor system extension Observes and reports; it does not block. Test Macs feed it Apple's eslogger.
Linux .deb and .rpm packages with a systemd service Debian 12 and 13, Ubuntu 24.04 and 26.04, Fedora 43 and 44, Rocky Linux 9 and 10, on x86_64 and arm64. APT and DNF repositories are not published yet.
Windows Zip with install.ps1, or an MSI, with the RunewardGuardSensor service Not yet qualified for production. x86_64 only.

Every platform also has per-user harness hooks, installed separately by each user. See hooks. For what each platform can and cannot see, see limits.

macOS

The native sensor is an Endpoint Security client shipped as a system extension inside Rune Guard.app. It reports metadata: process starts, forks and exits, credential file opens and Keychain requests. With the organization's document-label opt-in, it also reads bounded label properties in files, never document text. It never reads Keychain item values. The privacy statement lists each collector and its controls.

Requirements

Event Minimum macOS
Process, fork, exit and file open events 13
Keychain requests over XPC 14
Privacy permission grants (tcc_modify) 15.4
Legacy Keychain service look-ups 27

The sensor subscribes to what the running macOS supports and skips the rest. On macOS 14 to 26, Keychain requests that use only the legacy com.apple.SecurityServer path are not seen.

The sensor needs Full Disk Access, and macOS only activates system extensions from apps in /Applications.

Deploy with MDM

  1. Profile. Upload runeward-guard.mobileconfig to your MDM as a custom profile. It allows the sensor extension, stops users removing it in System Settings, and grants it Full Disk Access (SystemPolicyAllFiles). macOS honors these payloads only from a user-approved or automated MDM enrollment.
  2. Package. Deploy the .pkg. It installs /Applications/Rune Guard.app.
  3. Activate. Run this as the signed-in user, for example from an MDM script:
"/Applications/Rune Guard.app/Contents/MacOS/guard-es-install" activate

With the profile installed there is no prompt. Without it, the user approves the extension in System Settings > General > Login Items & Extensions (Privacy & Security before macOS 15) and grants Full Disk Access.

guard-es-install status reports whether the extension is enabled or awaiting approval. Installing a newer package and running activate again replaces the running version.

The extension runs as root and keeps its Guard home and findings in /Library/Application Support/Rune Guard.

Note: Network flow collection needs a separate content-filter profile, which this profile does not include, and the package does not contain that extension yet.

Development: the eslogger bridge

On macOS 13 and later, Guard can read Apple's own eslogger output. eslogger needs root and Full Disk Access for the terminal that starts it; the sensor itself runs as your user.

sudo /usr/bin/eslogger exec fork exit open xpc_connect tcc_modify bootstrap_look_up | guard-sensor eslogger

Leave out events your release doesn't list in eslogger --list-events. eslogger ignores its own process group, so start the AI tools you want to observe from a different terminal. Findings go to standard output and to findings/guard-YYYY-MM-DD.jsonl in the Guard home, kept 30 days. --no-store before the command turns storage off.

guard-sensor eslogger --spawn starts eslogger itself instead of reading a pipe, so a LaunchDaemon can run it with no shell. Full Disk Access then goes to the guard-sensor binary. The one-command install sets up test Macs this way.

Note: The bridge observes and reports; it does not block.

Linux

The sensor runs as root and uses the kernel's netlink process connector and fanotify, with no kernel module. It observes and reports. It denies a file open only when a signed catalog sets read_prevention to block on a credential rule; the built-in catalog sets none. Prevention fails open and has no retained live result.

Install the package

The runeward-guard package is built as .deb and .rpm for Debian, Ubuntu, Fedora and Rocky Linux. APT and DNF repositories are not published, and their repository signing key isn't provisioned yet. Signed staging releases with manifests, SBOMs and container images are published; see release verification.

The package depends on util-linux and acl, plus libpam-systemd (Debian) or systemd-pam (RPM). It recommends lsof for --network. There are no packages for Alpine, Arch or NixOS.

Until the repositories are published, test devices can use the one-command install instead. That installer refuses to run where the package is installed.

What the package installs

Path or unit Purpose
/usr/bin/guard, /usr/bin/guard-sensor The binaries
/usr/sbin/runeward-guardctl Runs guard as root against the system Guard home, for enrollment and status
/usr/sbin/runeward-guard-policy Shows or changes the AppArmor or SELinux policy mode
runeward-guard-sensor.service The live sensor, started at boot
runeward-guard-sync.service, .timer Guard Cloud sync every five minutes, once enrolled
runeward-guard-mcp-watch.service (user unit) Per-user MCP inventory, dropped off locally; no per-user enrollment
runeward-guard-mcp-receiver.service Queues those snapshots for the enrolled root sync to deliver
runeward-guard-hooks-repair.timer (user unit) Hourly hook repair; not enabled by the package
/etc/runeward-guard/sensor.env Sensor options; kept across upgrades
/var/lib/runeward-guard The system Guard home (mode 0700): identity, enrollment, findings, catalog

Configure the sensor

Edit GUARD_SENSOR_OPTIONS in /etc/runeward-guard/sensor.env, then run systemctl restart runeward-guard-sensor.

Option Effect Needs
--network Reports AI tools connecting to AI provider endpoints, by polling lsof lsof
--network ebpf The same from kernel flow events, with host, port and bytes sent, plus agent DNS lookups that look like encoded data; falls back to lsof Linux 5.8 or later with BTF
--watch-mount /home Marks a whole mount so project .env files are seen Linux 5.10 or later with BTF for the kernel open prefilter

Without the kernel open prefilter, a watched mount makes every open on it wait briefly for Guard. Measure the overhead before watching busy build or database mounts.

Findings go to the journal (journalctl -u runeward-guard-sensor) and to /var/lib/runeward-guard/findings/.

Permissions

The sensor runs as root with this capability bounding set:

Capability Used for
CAP_SYS_ADMIN fanotify
CAP_SYS_PTRACE, CAP_DAC_READ_SEARCH Reading other users' /proc entries
CAP_DAC_OVERRIDE fanotify opens files as the listener
CAP_NET_ADMIN The process connector
CAP_BPF, CAP_PERFMON eBPF programs, for --network ebpf and the prefilter (CAP_SYS_ADMIN on older kernels)
CAP_NET_RAW The packet socket that receives DNS answers; without it, flows are named by SNI and a startup lookup only

The sync service has no extra capabilities and can write only the state directory.

The sensor must run in the host's PID namespace to see other containers' processes. The process connector only works from the initial PID and network namespaces.

AppArmor and SELinux

The deb ships an AppArmor profile and the rpm an SELinux module for the sensor. Both start in complain or permissive mode, so a denial is logged but never stops detection. Enforcing is opt-in:

sudo runeward-guard-policy status
sudo runeward-guard-policy enforce
sudo runeward-guard-policy permissive   # back to complain/permissive, immediately

Check for denials before enforcing:

journalctl -k -g 'apparmor="ALLOWED".*profile="runeward-guard-sensor"'
sudo ausearch -m AVC,USER_AVC -ts this-week | grep runeward_guard_sensor_t

If you see a denial in enforcing mode, return to permissive mode first.

Other fanotify users, such as fapolicyd, endpoint detection agents or on-access antivirus, each answer their own permission events. Test with them running before you enforce. A fapolicyd host that trusts only its own file list must add /usr/bin/guard-sensor, the helpers in /usr/libexec/runeward-guard/ and lsof.

WSL2

The Windows sensor can't see inside WSL2's Linux VM, so install the Linux package in the distribution, as on any Linux host. On Ubuntu 24.04 under WSL2 with systemd on, the package's services start and every collector works on Microsoft's kernel, including the kernel open prefilter and --network ebpf. Install hooks on each side where a harness runs: guard hooks install inside WSL2, guard.exe hooks install in Windows. The browser monitor runs on the Windows side. Claude Code's hooks have run live on both sides. The WSL2 sensor hasn't yet been shown with a real harness, and no finding has yet been uploaded to Guard Cloud from WSL2.

Windows

Windows has its own page: Install on Windows covers the installers, the service, the audit settings and antivirus.

Enroll with Gurd Cloud

Each device enrolls with a single-use token from Guard Cloud. On Linux, as root:

sudo runeward-guardctl cloud enroll --server https://guard.example.com --token rge_… --catalog-key /path/to/catalog.pub
sudo systemctl start runeward-guard-sync.service

The timer then syncs every five minutes. When a sync installs a new catalog, the sensor restarts and loads it with the keys pinned at enrollment. If the installed catalog stops verifying, the sensor runs with the built-in catalog.

On macOS and Windows, the command is guard cloud enroll.

  • Token handling. Prefer --token-stdin, which reads the token from closed standard input. --token TOKEN still works but is visible in the process list. Never combine the two.
  • Signing key. Enrollment creates a separate, revocable Ed25519 device key. The default is a software key in an owner-only file, which any process running as that user, or root, can copy. --key-provider macos-keychain or --key-provider linux-secret-service (non-root enrollment only, with the user's Secret Service running and unlocked) stores the seed in the platform keystore instead. Both are still exportable software storage, with no hardware protection or attestation.
  • Check it. guard cloud status shows the enrollment and the key's capabilities without revealing the seed.
  • Interrupted enrollment. guard cloud recover-enrollment recovers the original device with its persisted key. It cannot re-enroll a revoked key or recover a missing Keychain secret.

Upgrade Guard Cloud before endpoints. See Self-hosting for the server.

Manage devices

Device identity

Each device has a local identity with a random installation identifier, kept in an owner-only device.json:

guard device-init --name "Developer Mac"
guard device-status --dir "$HOME/Desktop"

Re-running device-init returns the existing identity; it never rotates or replaces it. device-status prints metadata only: identity, Guard version, platform and coverage health. The identity file is not a credential; copying it doesn't authorize a device.

Retire a device

An administrator revokes a device in Guard Cloud. Device management tools can list devices, with each key's reported capabilities, at GET /v1/admin/devices.

  • Revocation blocks the device's future requests. It doesn't delete keys on the device, erase backups or remove the package.
  • A revoked or unknown device returns 404. Check the device inventory instead of re-enrolling.
  • To replace a device key, enroll the device again with a new authorized token, then revoke the old key.

Uninstall a package install

Remove per-user hooks first: each user runs guard uninstall as themselves, not elevated, before the package removes guard.

Platform Command Notes
macOS "/Applications/Rune Guard.app/Contents/MacOS/guard-es-install" deactivate Removes the system extension
Linux sudo guard-update uninstall, then remove the package Applied under the audit retention policy; package removal and purge keep the Guard state
Windows (zip) .\install.ps1 -Uninstall uninstall-policy.json if set, else -AuditRetention (Preserve, Export, Bundle with -AuditPath, or Delete), else Preserve
Windows (MSI) msiexec /x runeward-guard-0.1.0-windows-x86_64.msi /qn Always preserved; run guard-update.exe uninstall first for other policies. Also deletes the boot recovery task

For example, to bundle audit records on Windows:

.\install.ps1 -Uninstall -AuditRetention Bundle -AuditPath D:\guard-audit\device.tar

A managed Windows install also needs -AuditKey. On Linux, final removal of an enrolled device runs guard cloud retire so Guard Cloud shows an expected uninstall. It is best effort and is the device's own report, not a Cloud retirement. Don't delete the state directory just because the package is gone.

Note: A local root user or administrator can stop collection, copy software device keys or remove Guard. Guard reports health and tamper signals; it doesn't prevent this.

Written from docs/device-management.md, docs/endpoint-security.md, docs/macos-endpoint-security.md, docs/linux-sensor.md, docs/linux-packaging.md, docs/windows.md, docs/performance.md at commit fb79778d02f0. Rune Guard is in early access.