Skip to content

Host protection

Nodes are computers people use. Every few seconds, host protection decides how much fleet work a node may run without harming its owner’s own work: it holds new jobs back, lowers or pauses fleet jobs, or evicts them, and it only ever touches processes the agent started itself, or processes you delegated to it. You set it; a module can never declare or loosen it. This page covers Oarbank 2.11.1.

From 2.9 protection lives on the settings chain, at fleet, group or node scope:

Setting What it is How scopes combine
protection.mode fleet_first, moderate (the default) or strict_yield: how strongly the node yields to the person using it The most specific value wins; a fleet or group value may lock it
protection.rules Protected-process rules Every scope’s rules apply together: the fleet’s, each group’s and the node’s. A rule only ever protects more
protection.node The rest of the node section: memory guard, timing, GPU jobs, longest pause (advanced) The most specific value wins
Terminal window
oarbank settings set protection.mode strict_yield --group Laptops
oarbank node mode build-07 fleet_first # a node's own mode
oarbank protection show build-07 # its effective rules, and where each comes from
oarbank protection preview fleet rules.toml # what replacing the fleet's rules would change, per node
oarbank protection set fleet rules.toml # replace the fleet's own rules
oarbank protection set group:Laptops laptop-rules.toml
oarbank protection set build-07 node-rules.toml # a node's own section

set replaces one scope’s own section (a node, fleet or group:<group>) from a JSON or TOML file, as one change with a per-node review. Rule ids must be unique on a node: a change that would bring the same id from two scopes is refused. A rule the node’s OS cannot run (a code-signing matcher on Linux) is refused when set on that node, and skipped, by name, when it comes from the fleet or a group.

In the console, a node’s Protection page shows its effective rules with their source and the rules skipped there, and edits the node’s own section. The fleet’s section is on Settings, a group’s on its page.

The per-node canary, promote and restore of 2.8 are gone. Instead, put new rules on a small group, watch those nodes, then promote:

Terminal window
oarbank groups create Canary --member build-07
oarbank protection set group:Canary new-rules.toml
oarbank settings promote protection.rules --group Canary

Promoting joins the group’s rules to the fleet’s (a rule with the same id becomes the group’s version) and removes them from the group in one change, so the canary nodes see no change. Each change to a node’s effective rules is kept in its protection history.

A rule has a matcher, a tree scope, an activity condition, actions and timing:

[[rule]]
id = "xcode-builds"
match = { requirement = 'anchor apple and identifier "com.apple.dt.Xcode"' }
tree = "descendants"
active_when = { cpu_cores_gt = 1.0, for_s = 4 }
lower_fleet = { to = "background" }
[[rule]]
id = "calls"
match = { bundle_id = ["us.zoom.xos", "com.apple.FaceTime"] }
active_when = "present"
pause_fleet = { scope = "all" }
exit_after_s = 120
  • Matchers: a code-signing identity (Team ID and signing identifier, or a designated requirement), a bundle id, a path prefix or substring, and an argument pattern. A signature survives updates and moves; a path does not.
  • Trees: self, descendants, or same_team (helpers signed by the same team).
  • Activity: present, or thresholds on CPU cores, memory footprint or GPU activity, or frontmost, held for for_s seconds.
  • Actions include lower_fleet, cap_fleet, reserve and pause_fleet (scope all, cpu, gpu or io).
  • Protect (protect) names what to keep from harm, for example metric = "progress_rate" with a source the program writes, and max_slowdown.
  • During blocks ([[rule.during]]) act only while a phase of the program is on, read from a source; tags label the phase (uplink reaches the node’s site).
  • immediate = true makes the rule’s phases act the moment they begin, between protection’s two-second ticks.
  • delegate names a program of your own that protection may pause and lower as fleet work (Delegated processes).

From 2.9, while a pause_fleet rule is active the node also takes none of the work it pauses: its capacity names the paused scopes (paused, paused_by), and the coordinator grants it no job the rule would pause at once (all and io: no job; gpu: no GPU job; cpu: the others). Before, such a job was paused, released after the longest pause and granted straight back to the same node. Explain shows the job or the node as PROTECTION_ACTIVE, naming the rule.

A process that runs a new program (an exec) is identified by that new program, so a path or argument rule matches the app a launcher turns into.

The console’s process picker writes a matcher from the processes a node reports, and previews what it matches.

The agent cannot always read another account’s process path or arguments. Such a process counts as matching, so a failed lookup never leaves one of your processes unprotected, and the rule’s report counts it as unreadable (PROTECTION_UNREADABLE). From 2.9, a process matched that way takes part from its second sighting on (the next check, a few seconds later). Almost always, a process whose details fail to read is one that is exiting between the listing and the read; on a busy machine those used to switch such rules on and off every few seconds.

  • Sources are watched. Progress and phase sources (an event file, a log, a program) are read as they change, a glob follows the newest file, and a source in a person’s home is read by that person’s session helper on a system install. A source that cannot be read holds fleet work back and the node says why (PROTECTION_SOURCE_UNREADABLE, PROTECTION_SOURCE_NEEDS_HELPER). Prove co-tenancy is safe lists the kinds of source.
  • A rule that protects progress_rate holds GPU work back while its program uses the GPU, as a gpu_share rule does (except under gpu_jobs = "always").
  • Measured co-tenancy. The paired on/off harness measures what fleet work costs a protected program; a passing run is a certificate, and gpu_jobs = "certified" lets cooperative GPU work run beside a protected GPU program up to the certified duty, under the GPU duty governor (Prove co-tenancy is safe).
  • Workloads are fleet work with their own ladder: throttled, lowered, paused only up to what they tolerate, then stopped and held (Workloads).
  • Delegated processes: with the node setting delegated_processes on, a delegate rule lets protection pause and lower a program of yours (Delegated processes).

Besides the rules from the coordinator, a node can carry a local file, protection.json beside the agent’s home. The agent combines both, and the stricter setting wins on every dimension, so the two never conflict. Managed policy cannot set protection; this file is how a machine’s administrator adds protection locally.

  • Memory guard, caps and “someone is using it” settings: Settings.
  • What each protection code means: Reason codes.
  • Measuring co-tenancy from a terminal: oarbank protection ab start|status|show|abort|sweep, oarbank protection certificates and oarbank protection duty (Command-line reference).