Skip to content

Runtime Configuration

R2Kernel™ is a configurable robotics runtime. Before choosing a CLI command or a browser tool, identify which part of the installed host you are configuring.

This page writes the install prefix as <prefix>; the default prefix is listed in Installation.

The active runtime config is this.

<prefix>/runtime/config.yaml

The installer also provides a convenience entry point.

<prefix>/config.yaml -> <prefix>/runtime/config.yaml

Configuration commands write overrides instead of rewriting the base file. Unmanaged installations use the sibling override:

<prefix>/runtime/config.override.yaml

Managed Linux service installations also prepare a private Control settings override under <prefix>/var/lib/control-config. Control resolves the base, system override, and then supported Control settings. The privileged resource and time-sync services do not load that private Control override. The GUI and management CLI use the same resolver. Relative paths still resolve beside the base configuration, not beside the private override.

For ordinary SDK and runtime commands, load the installed environment in the current shell, or opt into shell-profile integration during installation.

. <prefix>/env.sh

This is not administrator authentication, and the modified PATH does not carry over to sudo. System installations with Linux services provide a separate administrator entry that selects the actual configured base file:

sudo /usr/local/bin/r2kernel-config
sudo /usr/local/bin/r2kernel-config paths
sudo /usr/local/bin/r2kernel-config set product.name "Acme Robot Controller"

If /usr/local/bin is in sudo's search path, sudo r2kernel-config is equivalent. The entry does not depend on env.sh. User-home installs have no system-wide entry. On installations predating this entry, use sudo <prefix>/runtime/bin/r2kernel-config --config <prefix>/runtime/config.yaml.

System base and sibling override files remain root-owned and readable by the service group; do not make the whole installation group-writable. Supported operational settings are saved to the private Control override as the service user, even when the administrator CLI was invoked through sudo. System-owned fields are read-only in the GUI and CLI form. Use the administrator entry's set/unset commands for privileged system changes. Without safe write access, configuration surfaces report the restriction rather than changing ownership. Saves validate the resolved settings, reject stale revisions, back up an existing override, and replace it atomically. Runtime updates preserve existing base and override configuration.

Ways To Change Configuration

Use one of these surfaces depending on where you are operating from.

Surface Use
r2kernel config tui interactive form for common settings
r2kernel config get/set/unset scripted or SSH-based override changes by dotted key
Web Console Settings browser-based editing and apply actions
direct YAML editing site automation or reviewable base/override changes

Examples.

r2kernel config paths
r2kernel config print
r2kernel config get control.api_port
r2kernel config set product.name "Acme Robot Controller"
r2kernel config validate

When you edit YAML directly, validate before restarting services.

r2kernel config validate
sudo systemctl restart r2kernel-control.service

Some settings are read only at service startup. Saving through the configuration CLI never restarts services automatically: review the change, then schedule any required restart yourself. Browser apply actions are a separate operation.

Configuration Areas

The common operator-facing areas are these.

Area Representative keys What it controls
Product identity product.name, product.vendor, product.support_url names shown to product-facing clients and the Web Console
Host control control.api_host, control.api_port, control.ui_port, control.management_https.*, control.advertise_host canonical REST/WebSocket API, separate Console listeners, and peer reachability
System frontend control.frontend.mode, control.frontend.root bundled Console, custom product shell, or headless API mode
Package storage packages.install_dir, packages.additional_paths, packages.max_upload_bytes managed package storage, external package discovery, and upload limit
Resource authority resource_service.mode managed resource lease behavior
Web/API security security.enabled, security.network.allow_cidrs, security.api.*, security.web.* browser login, API auth, source-network gates, and sessions
Federation federation.peers, federation.membership_scope, federation.membership_file, federation.transport, federation.security.* bootstrap peer list, durable runtime admission, Event forwarding and federation security
Time sync time_sync.enabled, time_sync.nic, time_sync.role, time_sync.leader_host clock readiness and managed time-sync behavior
Control transport timed_exchange.* host-to-host timed exchange and local Control buffer limits
Core worker scheduling core_scheduling.policy, core_scheduling.priority, core_scheduling.cores scheduling for internal communication and fast data workers
Shared memory shm_manager.* event shared-memory pool sizing

The installed default keeps the bundled Web Console enabled on loopback port 18080; product API and WebSocket ports remain 8001. Authentication is disabled for this local setup profile, not configured with a shared default password. Before exposing a host beyond loopback, configure Web/API security and source-network policy. Existing override files may retain older network-facing settings; inspect the effective configuration after upgrades.

federation.peers seeds a Control only while no durable runtime membership record exists. Later file edits do not overwrite that record or reset its generations. Use the authenticated Runtime Federation Peers API to add, replace or remove live peers; saving generic configuration is not a second membership writer.

Runtime upgrades use the installer rather than independent service restarts. The installer stops declared dependent systemd units and application supervisors before Control and r2kernel-resourced, replaces the runtime and SDK, then waits for resource-service and Control readiness before restoring the original active units. --system-services skip preserves this coordination for an already registered prefix while skipping new service registration. Applications launched outside systemd need to be stopped separately. An incomplete replacement leaves the affected units stopped with a protected /run/r2kernel-upgrade recovery journal; retry the same-prefix installation to finish the upgrade.

Core Worker Scheduling

On Linux, internal Control transport, Event, and federation fast data workers default to SCHED_FIFO priority 99. Host status refresh, resource reconciliation, time-sync management, HTTP, and Web Console tasks remain on the normal executor.

core_scheduling:
  policy: fifo       # other, fifo, or rr
  priority: 99       # other requires 0; fifo/rr require 1..99
  cores: []          # preserve inherited affinity; optionally select allowed CPUs

Omitted worker settings use these platform defaults. An explicitly configured policy or priority is preserved; updating the runtime does not replace a saved priority with the new default.

Each communication worker applies and reads back its own scheduling policy, priority, and CPU affinity before accepting work. Startup logs include its thread ID and the verified settings. A denied or invalid request fails worker startup; it does not silently switch to other. Apply configuration changes by restarting the runtime. On a managed installation, edit these worker settings in the administrator-owned base configuration; the Console's user-editable overlay does not grant changes to the host scheduling policy.

The installed non-root Control service grants LimitRTPRIO=99, LimitMEMLOCK=64M and LimitNOFILE=65536. The first two let its workers select the configured FIFO/RR priority and lock their admitted working memory. An accept error on the HTTP and HTTPS listeners, the status TCP listener, the local Unix control socket, the Timed Exchange local control socket or the Event inline socket does not stop Control. After an error that is not about a single connection (for example, too many open files) the listener waits 1 s before it accepts again. The status TCP, local Unix control, Timed Exchange local control and Event inline listeners log accept errors at most once per 5 s. The federation listener is examined once per control tick. A failure of one queued connection (for example a peer that reset the connection before it was accepted) is a warning and does not end that tick's accepts; only a listener-level error (too many open files, or no buffer space or memory) ends them. A tick attempts at most 16 accepts, or one per configured peer if there are more, failed attempts included. Accept errors and closed pre-handshake connections are logged at most once per 5 s, each line with the count since the previous one (every warning still appears in that tick's federation report). Managed packages do not inherit that real-time limit: each package is bounded to its admitted CPU claim (see Resource Control and Real-Time Scheduling). The service's main and management workers start with SCHED_OTHER. A directly launched development runtime needs equivalent scheduling and memory-lock grants, or an explicit policy: other with priority: 0. Other supported platforms default to other and inherited affinity.

Real-time operation requires sufficient memory-lock permissions and the configured memory budget. Preparation and admission failures are explicit. Allow headroom for active connections and capacity changes.

timed_exchange:
  rt_memory_lock_enabled: true
  rt_memory_budget_bytes: 67108864  # 64MiB process admission limit
  rt_stack_prefault_bytes: 65536   # 64KiB per worker; maximum 256KiB

FIFO/RR requires memory locking. A lock failure, exhausted budget, or invalid stack range fails preparation explicitly. To opt out of RT locking, select core_scheduling: {policy: other, priority: 0}. Change these settings in the administrator-owned base configuration and restart Control. Increasing the budget also requires a sufficient service LimitMEMLOCK; changing the admission limit does not raise the OS limit.

These settings constrain runtime memory preparation, not every allocation in application callbacks or response construction. They do not establish a page-fault-free process or a worst-case transaction latency guarantee.

This setting does not select a policy for user subsystem processes. Declare those policies separately in package.yaml under resources.cpu. RT priority does not remove waits for shared locks or provider responses, and does not by itself establish a deadline guarantee.

Minimal Product Identity

Product metadata is safe to change first because it affects display and API metadata, not the native runtime hot path.

r2kernel config set product.name "Acme Robot Controller"
r2kernel config set product.vendor "Acme Robotics"
r2kernel config set product.support_url "https://support.example.com"

Product-facing clients can read these values through Host Control status and capability APIs. The Web Console Settings page exposes the same fields.

Host And Frontend Policy

The control backend serves REST APIs, WebSocket facade endpoints, and the system frontend using the configured hosts and ports. Console HTTP defaults to control.ui_port: 18080, while HTTPS defaults to control.management_https.port: 18443. A missing Console port uses these defaults. Explicit values are preserved, including legacy HTTP 8081, HTTPS 8443, and control.ui_port: 0, which shares control.api_port.

control:
  api_host: "127.0.0.1"
  api_port: 8001
  ui_port: 18080
  frontend:
    mode: "bundled"   # bundled, custom, or disabled

Use bundled for the R2Kernel Web Console. Use custom when a product should serve its own static operator UI from /. Use disabled for a headless host that exposes Host Control APIs without a system frontend.

For the detailed product UI policy, see Product Frontend Modes.

The managed Linux Console starts with HTTP. Settings → Security → Console connection selects HTTP or native HTTPS and either a generated device identity or a user-provided certificate/private-key PEM pair. Save, then apply saved settings to restart Control and reconnect. control.management_https stores the saved listener and protected material paths. A restricted root settings service owns those files; the ordinary service override cannot replace their paths. Console HTTP entry points redirect when HTTPS is active. Product/API HTTP ports remain independent. HTTP and HTTPS Console sessions have separate cookie names and session scopes. Product support URLs are optional metadata.

Console-origin /console/api/v1 management uses Console login/session policy. Canonical /api/v1 REST and WebSocket requests use the independent API policy and require an API key when API security is ON. Console cookies never authorize canonical API requests, even with ui_port: 0. Browser WebSocket clients cannot set arbitrary key headers; use the Console session endpoints for Console pages or a product-owned server adapter for canonical API integration, never URL keys.

control.web_terminal.enabled defaults false. Terminal follows the Console connection: HTTP/ws or HTTPS/wss. Settings → Terminal exposes ON/OFF and optional session limits. Applying Terminal changes closes sessions without restarting Control. Exact permitted origins, actual listener admission, and OS login checks still apply. control.web_terminal.allow_insecure_http is retained when reading older configurations but has no effect and is absent from the guided form.

Security Before Exposure

Fresh API/UI/WebSocket, registration UDP, legacy status TCP, federation data, and timed-exchange listener binds default to loopback. These defaults are not a sandbox for local users or packages and do not disable managed PTP/time-sync network traffic. Before binding a host to a reachable network, configure credentials, access policy, and the required network interfaces explicitly.

Registration UDP (control.udp_port) binds the same host as control.api_host. A datagram whose receive, reply or notification fails is logged (at most one line per 5 s per kind) and does not stop Control. A reply larger than 65,507 bytes is replaced by a short error that names the local Unix control socket, and a UDP error text longer than 256 bytes is replaced by a fixed message, so an error reply never quotes a long request value. Remote logical-clock time sync probes a leader's control.udp_port, so a multi-host logical clock needs that bind reachable.

r2kernel config set security.enabled true
r2kernel config set security.api.require_auth true
r2kernel config set security.network.allow_cidrs '["127.0.0.1/32", "::1/128", "192.0.2.0/24"]'

Store API tokens and web passwords in private files owned by the Control service user, or in service-managed environment variables, rather than inline YAML. See Web and API Security for the full pattern.

The 192.0.2.0/24 network is an example documentation range: replace it with your actual restricted management network. For remote deployment, select only the necessary binds: control.api_host, control.tcp_host, federation.bind_host, and timed_exchange.bind_host, plus a reachable control.advertise_host. The timed-exchange bind also selects the default outbound interface; setting peer addresses alone is insufficient. These binds and the advertised host are read at startup: inject an overlay address through the configuration before Control starts, and restart Control to move it. Peers and federation keys, by contrast, change at runtime through the peer and key rotation APIs.

timed_exchange.relay_enabled defaults to true. Set it to false to disable the remote inbound Control relay listener and its receive workers, then apply the settings to restart the runtime. Local Control and outbound clients for configured peers remain enabled. Other hosts cannot send Control requests to this host while its relay is off; this host can still send requests to peers whose relays are enabled.

Control tracks timing statistics for at most 4096 distinct Control timing identities. On connection lanes, an identity is created only for a request whose route Control accepted. That check accepts any topic name for operation endpoints (operation.start_typed/<name>) and for peers that have not published prepared codec metadata. On non-v5 paths, Control records timing before it looks up the target, so any request creates an identity. A local client can therefore fill the registry with distinct names. At the limit a new identity is not tracked; control_timing_identities_untracked counts these refusals, once per connection lane (again only after an identity was removed) and once per request on non-v5 paths, not refused requests or distinct identities. A request never evicts an identity: identities are removed when their target unregisters or is no longer a local or federated registration, and, while the registry is full, when they have had no request for control.subsystem_timeout. Identities of unregistered targets are removed at the next registry publication.

Enabled inbound Control workers wait for socket readiness while idle rather than continually polling empty peers. Incoming data, peer changes, and shutdown wake that wait; a partial frame retains its original deadline. This does not extend an exchange timeout or promise real-time qualification. Bounded active batches retain their scheduling fairness pause.

Web/API authentication covers HTTP and WebSocket routes, not all native ports. Use TLS termination for remote browser/API access. Require federation frame security and configured keys for remote federation, and restrict legacy TCP, UDP, and timed-exchange ports to trusted peers through firewall/VPN policy. VPN membership does not replace application-user authentication or isolate untrusted installed packages.

Local Control Memory Limits

Local Control v5 uses reusable shared memory for every application payload, regardless of payload size. timed_exchange.inline_payload_threshold is used only by comparison modes; it does not select the production local payload path. Host-to-host Control remains best-effort TCP.

Upgrade the runtime and all SDK-based subsystem processes together. Local transport version mismatches fail explicitly; an unsuccessful exchange is not automatically retried. Successful completion confirms that the response buffer can be reused. Existing SDK-owned-buffer APIs are unchanged.

Prepare a bounded local Control lane during initialization with explicit request and response capacities and a separate cold preparation budget. Preparation must reach the selected provider and reserve the required resources without calling the application handler. A connection or registration acknowledgement alone does not establish provider readiness. Once prepared, requests exceeding those capacities or using a changed route/binding require fresh preparation; the timed path does not silently reconnect or grow buffers. Preparation is not proof of 1 ms completion: route selection, payload processing, response handling, and safe buffer reclamation all count in the exchange budget. Retained failures and late completion remain errors; no automatic retry is implied.

Key under timed_exchange Default Meaning
shm_min_region_bytes 4096 minimum local shared-memory region size
shared_buffer_slot_size 16777216 maximum total size of one local region, including transport overhead
shm_max_channels 128 maximum active channels counted by the runtime's local Control transport
shm_max_owned_bytes 67108864 aggregate bytes for regions created by the runtime's local Control transport
shm_max_mapped_bytes 67108864 aggregate bytes for peer-owned regions mapped by that transport

Request and response capacity are independent. A production local lane is scoped to the selected endpoint, topic, bound source and exchange kind. One exchange may be in flight on that lane; concurrent or reentrant use of the same lane reports busy. Independent bound sources and interfaces have distinct lanes within aggregate transport limits. This does not promise that a provider callback or physical device can execute concurrently.

The configured region maximum is a cap, not an upfront reservation for every active channel. Treat the channel count as an aggregate transport limit; it is not guaranteed to match the number of logical interfaces one for one. Both byte budgets must accommodate the configured maximum region and leave headroom for concurrent use. Payload growth can temporarily require additional memory while capacity changes, so allow enough room to stay within the applicable budget.

The byte budgets apply across the local Control transport, not per logical interface. The created-region and peer-mapping budgets account for different resources and both must accommodate the workload. Payload growth and concurrent use need headroom. Limits fail explicitly; Control neither falls back to another transport nor automatically retries. Validate changes and restart the affected runtime and subsystem processes together. Event pool settings remain independent.

Package And Runtime State

Managed package state should stay inside the R2Kernel product prefix. Product installs use a writable package state location under the prefix so installed packages survive runtime replacement while remaining owned by the control service.

Check the active value before changing it.

r2kernel config get packages.install_dir

Relative paths resolve beside the active config.yaml. Prefer absolute paths for site-specific product deployments when ambiguity would be risky.

install_dir and its ancestors must not be symbolic links; symlinked install roots are not supported. To use a mounted volume, set the resolved directory. Control refuses a symlinked install root with a message that names the symlink, packages.install_dir, the active configuration file and the resolved directory to configure:

package install root must not have symlink ancestors: <ancestor> is a symlink to <target>. Set packages.install_dir in <config path> to the resolved directory <resolved directory> (r2kernel config set packages.install_dir <resolved directory>) and restart Control.

If the resolved directory cannot be computed, the message shows that error instead of a path.

To make existing package trees available without copying them into the managed install directory, add package directories or package roots to packages.additional_paths.

packages:
  install_dir: "<prefix>/var/lib/packages"
  additional_paths:
    - "/srv/robot-packages"
    - "../development/my-package"

An entry may point directly to a directory containing package.yaml, or to a root whose immediate child directories contain package.yaml. Relative entries resolve beside the active config.yaml. R2Kernel validates and exposes these external packages through Runtime, including their frontend and contract specs, but never copies or deletes their source directories. Remove an external package by removing its entry from additional_paths and applying the configuration.

Next Tools

After the configuration model is clear.

  1. Use CLI Tools for SSH, automation, service checks, package lifecycle, and runtime diagnostics.
  2. Use Web Console Manual for browser-based operation on a host.
  3. Use Time Sync Operations, Web and API Security, Resource Control, and Deployment Checks for production-readiness checks.
  4. Use Product Frontend Modes when a product should replace or disable the bundled Web Console.