Skip to content

Settings

Every owner choice in Oarbank, from how much memory a node keeps for its user to whether a module runs on laptops, is a setting. There is one list of settings, one store of the values you set, and one rule that says, for every node, which value is in effect and where it comes from. The console and the oarbank settings command show the same thing.

This page covers Oarbank 2.11.1. In 2.8 and earlier, policy and caps were stored per node (oarbank node policy, oarbank node limits); 2.9 converts them once, on upgrade, and those commands are gone (Upgrading).

A value can be set at three scopes. A value you do not set is inherited from the scope above it.

Scope Set where Reaches
Fleet Settings → Node defaults in the console; oarbank settings set <key> <value> every node
Group the group’s page under Groups; --group <group> the group’s members
Node the node’s Settings tab; --node <node> that node only

On top of those, two layers apply only in special cases: a campaign may override a few keys for its own jobs while it runs (Campaign overrides), and a machine’s managed policy may make settings stricter on that machine (Managed on this machine).

How a node’s value is found. Oarbank starts from the key’s default (a fixed one, or one computed from the machine: the memory kept for the system depends on how much RAM the machine has, and says so), then applies the fleet’s value, each group the node belongs to (lowest rank first, so the highest rank wins), then the node’s own value. For most keys the most specific value wins. Caps work differently: every scope’s cap applies and the lowest one binds, so a group or node can only tighten a fleet cap (enforce takes the strictest: hard over soft). Protection rules add up from every scope (Host protection).

Reset means inherit. A value exists only where you set one. Reset to inherited (or oarbank settings reset) deletes it, so a later fleet change reaches that node again. A value equal to today’s default is still your choice, and stays.

Every save is one change. A save gets one revision number and one audit entry with who, when, each value before and after, and the reason. A change that reaches more than one node shows its preview first: which nodes’ value changes (old and new), which keep theirs and why, then a button that says what it does (“Save for 4 nodes”).

On a node’s Settings tab, every row shows the value in effect, where it comes from (Default · 24 GB RAM, Fleet, Group: Laptops, This node, On this machine (managed)), whether the node has applied it, and an Explain disclosure with the whole chain. Override sets a value for that node; Reset to inherited removes it.

From a terminal:

Terminal window
oarbank settings get --node build-07 # every key in effect on the node, with its source
oarbank settings explain run_on_battery --node build-07 # the whole chain: default, fleet, groups, node
oarbank settings overrides user_present_slots # who overrides the fleet value, and with what
oarbank settings schema # every key: type, unit, scopes, default, help

oarbank node show <node> lists what the node sets itself, each with the command that resets it.

Section Keys
Memory os_reserve_gb (memory kept for the system; computed from RAM), user_reserve_gb (kept for the person using it), job_mem_gb (memory per job slot), mem_in_use_bound (fit jobs into the memory free now)
When someone is using it user_present_slots, user_idle_s, screen_sharing_present, run_on_battery
Jobs threads_per_job, max_slots (CPU slots for jobs: the node’s CPU budget in cores, see below), workloads (assigned workloads may run; on by default); advanced: nice (not applied by agents yet), hard_limits
Caps (off by default) cpu_cores, mem_gb, jobs, schedule, enforce (soft or hard); advanced: vm_mem_gb, vm_cpus (the container VM’s size, applied from 2.11, and a module VM service’s), disk_gb (the node’s dataset cache: above it, the least recently used datasets no job holds or waits for go; enforced from 2.11), staging_mbps (the rate of dataset staging and result and checkpoint uploads, enforced from 2.10)
Containers (2.11) containers (always, the default; on_demand, recommended; off); advanced: containers_idle_stop_s (600) (Containers on nodes)
Module data module_retention_days (from 2.11): how long a node keeps what a module left there after the module is turned off on it, 7 by default; 0 deletes it at once (When a module leaves a node)
Protection protection.mode, protection.rules, protection.node (Host protection), delegated_processes (off by default: Delegated processes)
Network inbound_listeners (assigned listeners may open; on by default); advanced: listener_port_range (the internal ports listeners bind, default 41000-41999). Fleet only: listener_probe_endpoint (an https:// probe endpoint you run elsewhere), listener_stun_server (host:port; none by default) (Make a node reachable)
Host tools tool.<id>.path (Host tools)
Fleet only ntfy.url, ntfy.click_base (notifications), console_listen (where the console listens: localhost, tailscale, IP addresses, all), console_https (off or tailscale: https on the machine’s MagicDNS name, for passkeys), console_hosts (extra console host names) (Open the console from another device), replica_rate (0 to 1), new_node_state and new_node_modules (what a machine you approve starts as: Adding machines)
Every module enabled, services.disabled, pipeline, replica_rate, set with --module <module> (Module settings)

Each node card says in one line how much work the node takes and why, for example “2 slots while someone is using this Mac (14 when idle) · 9.2 GB free for jobs (apps and the system use 46 GB)”. A slot is a performance core, or two efficiency cores; hardware threads never count. Jobs get only memory the machine has free now, less a margin that keeps the memory guard from stepping in, and never more than the memory kept for the system and for the person using it allows. The settings behind that line are on the node’s Settings tab.

max_slots is a CPU budget, not a job count. Every running job takes its stage’s resources.cpu from the node’s slots, so with max_slots 1 a stage that declares cpu = 2 never runs on that node. To run one job at a time, set jobs 1 (Concurrent jobs) and leave max_slots alone. When max_slots is below the cpu of a stage of a module enabled on the node, Oarbank 2.10.4 and later say so in the module’s readiness, the job’s Explain and the oarbank settings set preview.

The ntfy token is not a setting: it is a write-only secret, set with oarbank settings set-secret ntfy_token (it asks twice, hidden) and removed with clear-secret ntfy_token.

Terminal window
oarbank settings set user_present_slots 1 # the fleet
oarbank settings set user_present_slots 3 --node build-07 # one node
oarbank settings set run_on_battery false --group Laptops # a group
oarbank settings reset user_present_slots --node build-07 # back to inherited
oarbank settings set jobs 2 --node build-07 --dry-run # what it would change, nothing saved

A value is JSON (true, 2, 1.5, null, ["a"]) or plain text; a list setting also takes a,b. set and reset always show the per-node impact first, then apply (--yes skips the question). Without a scope they act on the fleet. --comment TEXT is kept with the value; --reason TEXT goes to the audit log.

A save is refused, with every problem at once, when a key cannot be set at that scope, a value has the wrong type or range, a lock holds above it, or the merged values would not work on a node it reaches (the system reserve must leave memory for jobs, a job slot must fit in RAM, a node’s own cap may not exceed its hardware). A save is refused only for problems it introduces, so an existing problem never blocks an unrelated change.

When nodes get it. The coordinator sends each node its complete settings with the next heartbeat. Each row shows “Applied on the node · rev 41”, “Pending: the node applies rev 42 at its next heartbeat”, “Pending: node offline” or “Refused by the node: …”. A node agent older than 2.9 shows “Pending: this agent does not report what it applied (update it)”.

A group is a set of nodes chosen by a rule (a selector) over the nodes’ facts and labels, plus any nodes you list by name. Every group has a unique rank: where groups disagree about a key, the highest rank wins.

The built-in groups are macOS, Linux, Windows and Coordinator host (the coordinator’s own machine, which runs every module service). They have the lowest ranks and fixed membership, and you can set values on them. Your own groups rank above them; a new group goes on top.

Selector term A node matches when
--os darwin|linux|windows its OS is this one (repeat for any of several)
--arch arm64|amd64 its architecture is this one
--label <label> it carries the label (repeat: every one)
--hostname <glob> its name matches, ignoring case (mac-*)
--battery / --no-battery it has a system battery (a laptop), or not
--ram-min, --ram-max, --cores-min its RAM is at least / at most, its cores at least
Terminal window
oarbank groups create Laptops --battery
oarbank groups create "Render boxes" --label render --ram-min 64
oarbank groups create Lab --member build-07 --member build-08
oarbank groups list # by rank, with members and labels
oarbank groups show Laptops # its members and why each is in
oarbank groups rank Laptops top # up, down, top or bottom
oarbank groups update Laptops --description "Every laptop"
oarbank groups delete Lab # deletes its values and its secrets' values too

Membership is worked out whenever values are resolved, so a node whose facts change moves at once and nothing keeps a stale copy. The console’s new-group form shows a live preview: each node, and why it is in or not (“Laptops because has a battery”).

Labels are short owner words on a node (1 to 63 of a-z 0-9 _ . : -): oarbank node label build-07 render,gpu, or --remove. Oarbank also adds labels from facts, such as laptop for a node with a battery; you can match them but not remove them. Facts come from the node itself, so a group that locks a safety value should select on your own labels, listed members or the OS. Removing a label that takes a node out of a group with a lock needs the admin role, so a label is never a way around a lock.

A lock is a fleet or group value that lower scopes may not change: --enforce on set, or the lock toggle beside a fleet or group value in the console. Adding a lock is a high-tier change that asks you to type a confirmation.

Terminal window
oarbank settings set run_on_battery false --group Laptops --enforce

While the lock holds, it wins outright. Values set below it are kept but ignored (and apply again when the lock goes); the preview of a new lock lists them. A node or lower group that tries to set the key is refused (“locked by the group Laptops: change it there”); a node can still reset its own value. The fleet’s lock comes before any group’s, and a higher-ranked group’s before a lower one’s. Locks hold for campaign overrides too.

One key set or reset on many nodes is one change with one revision and one preview listing every node’s old and new value:

Terminal window
oarbank settings set jobs 2 --nodes build-07,build-08,build-09
oarbank settings reset jobs --label render

The console’s Bulk changes page (filtered by group or label) does the same, and adds or removes labels. Resetting to inherited is the safer default it offers. A change to more than ten nodes’ own values is one tier higher.

To try a change on a few nodes first, set it on a small group, watch those nodes, then promote it:

Terminal window
oarbank groups create Canary --member build-07
oarbank settings set user_idle_s 600 --group Canary
oarbank settings promote user_idle_s --group Canary # to the fleet; --to <group> for a wider group

Promotion is one change: the value is set at the fleet (or the wider group) and deleted from the canary group, so the canary nodes see no change and the rest get it. Protection rules join the target’s rules instead of replacing them, and a lock moves with its value. A group page has Promote to fleet… on each value set there. A module version’s canary can target a group too: oarbank module canary <module>@<version> --group Canary.

A campaign may override a few settings for its own jobs while it runs or is paused:

  • the core keys replica_rate (it can only raise verification), jobs, run_on_battery and user_present_slots;
  • a module’s own keys that its manifest marks overridable by campaigns.

Safety keys only tighten: a campaign value looser than the fleet’s is refused (“a campaign may only tighten Run jobs on battery (off is stricter)”), and a node whose own value is already stricter keeps it. A lock ignores the campaign’s value. A job held back by its campaign’s settings waits with CAMPAIGN_SETTING_HOLDS.

Terminal window
oarbank settings get --campaign <campaign>
oarbank settings set replica_rate 0.2 --campaign <campaign>
oarbank settings reset jobs --campaign <campaign>

The campaign’s page has a While this campaign runs section with the same rows. Once the campaign is done or cancelled its values are kept and shown as inactive, but apply to nothing. A campaign’s priority, weight and placement stay campaign properties (oarbank campaign priority|weight|placement), not settings.

Every module has the same four core keys, set with --module:

Key Scopes What it does
enabled fleet (lockable), group, node; on by default Off for the fleet is the module’s kill switch (oarbank module disable writes it): nothing is dispatched, running attempts are released and its services stop. Off for a group or node does the same there only
services.disabled fleet, group, node The module’s services a node does not run. A change re-doctors and re-certifies that module on the nodes whose value changed
pipeline fleet single or split (a module whose stages form a chain); switching to split splits its queued jobs. Replaces oarbank pipeline
replica_rate fleet The module’s own replica rate; it can only raise the fleet’s

A module can also declare its own settings (a VM size, a threshold). The module’s Settings tab shows them under Its settings, with the readiness checklist on top; the node’s Settings tab ends with a section per module. A setting the module marks required has no default: until it has a value for a node, the module’s work there waits with SETTINGS_NOT_SET, and its checklist step Required settings says which nodes miss what.

Terminal window
oarbank settings get --module reel # all of the module's keys and where they come from
oarbank settings set vm_mem_gb 12 --module reel --node build-07
oarbank settings set enabled false --module reel --group Laptops
oarbank settings set pipeline split --module reel

When a new module version stops declaring a key, its values are kept but unused, listed under Values the module no longer declares with a Delete each; a value the new version’s schema refuses is dropped and named in the module’s event. Module authors: Declare module settings.

Module secrets resolve the same way: a node’s own value, else the highest-ranked group’s, else the module’s (oarbank secret set <module> <name> --group <group>). They stay write-only.

An organization can make settings stricter on a machine through its managed policy (MDM, Group Policy or a file), and the machine’s agent enforces it. A managed value applies only where it is stricter than what the coordinator sends; a looser one has no effect. So an organization can guarantee, for example, that a laptop never runs jobs on battery, while the owner can still tighten caps from the console.

Key Type Stricter
run_on_battery, inbound_listeners, workloads, delegated_processes boolean off
screen_sharing_present, mem_in_use_bound, hard_limits boolean on
user_present_slots, max_slots, jobs, vm_cpus integer lower
cpu_cores, mem_gb, vm_mem_gb, disk_gb, staging_mbps number lower
os_reserve_gb, user_reserve_gb, user_idle_s number higher
enforce soft or hard hard
containers (2.11) always, on_demand or off off

Any other key (job_mem_gb, a schedule, protection) is refused and reported; protection has its own local file on the node (Host protection).

Where
macOS a configuration profile for the preference domain dev.codonic.oarbank.agent, with a Settings dictionary keyed by the setting’s key
Windows values under HKLM\SOFTWARE\Policies\Codonic\Oarbank\Agent\Settings (REG_DWORD, or REG_SZ for a decimal number); the release’s ADMX template has one policy per key under Codonic › Oarbank › Node › Node settings (tighten-only)
Linux a "Settings" object in /etc/oarbank/policy.json

A macOS profile payload:

<dict>
<key>PayloadType</key><string>dev.codonic.oarbank.agent</string>
<key>ManagedByOrganizationName</key><string>Example Org</string>
<key>Settings</key>
<dict>
<key>run_on_battery</key><false/>
<key>jobs</key><integer>2</integer>
<key>os_reserve_gb</key><real>8</real>
</dict>
</dict>

On Windows, from an elevated prompt or through Group Policy:

Terminal window
reg add HKLM\SOFTWARE\Policies\Codonic\Oarbank\Agent\Settings /v run_on_battery /t REG_DWORD /d 0
reg add HKLM\SOFTWARE\Policies\Codonic\Oarbank\Agent\Settings /v os_reserve_gb /t REG_SZ /d 8.5

On Linux, /etc/oarbank/policy.json:

{"Settings": {"run_on_battery": false, "jobs": 2}}

The agent re-reads the policy at most once a minute. On the node, oarbank-agent policy prints what the machine’s policy sets (a managed join code shows as (set), never its value). In the console, a row the policy tightens carries “Managed on this machine: off (applies)”, its source badge names the organization, and Settings → Applied drift lists the machines whose policy tightens settings. These keys need a 2.9 agent and, on Windows, the 2.9 ADMX template. The other managed policy keys (the join code, ShowStatusIcon and so on) are in Adding machines.

Export a scope’s settings as YAML, keep the file in version control, and import it into this or another fleet:

Terminal window
oarbank settings export --out fleet.yaml # the fleet, every group, node labels and values, tool definitions
oarbank settings export --scope group:Laptops --out laptops.yaml
oarbank settings export --scope node:build-07 --module reel
oarbank settings import fleet.yaml --dry-run # exit 0: no changes; exit 2: there are changes
oarbank settings import fleet.yaml
oarbank: settings/v1
scope: fleet
fleet:
settings:
job_mem_gb: 2
user_idle_s: !locked 600 # a lock at this scope
groups:
laptops: {name: Laptops, rank: 100, selector: {"battery": true}, members: [], settings: {run_on_battery: !locked false}}
nodes:
build-07: {node_id: n_…, labels: ["render"], settings: {jobs: 3}}

An import applies only the differences, as one operation: groups, node labels (a node’s labels list is its whole set of owner labels), host tool definitions, then every value as one change, checked and previewed as usual. A key the file leaves out is never touched; key: !reset deletes a value. Nodes match by node_id, then by name; a node or group the file names that this fleet does not have refuses the import. Secrets are exported as fingerprints, never values, and are never written by an import; the folder registry and dataset origins are reported, not written. Importing needs the admin role, and a file that adds or changes a lock asks for a typed confirmation. The console has the same under Settings → Export and import.

  • Shadowed values (oarbank settings shadowed, Settings → Shadowed values): values that change no node’s effective value, because a lock holds above them, they equal what the scope inherits, or they have no effect (a node cap above a stricter fleet cap). Each has a Reset; --yes (or Reset all) resets them all as one change. Nothing is reset by itself.
  • Applied drift (oarbank settings drift, Settings → Applied drift): per node, the revision the coordinator sent and the one the agent applied, how long it has lagged, the keys it refused, and what the machine’s managed policy tightens.

Neither report raises an alert.