System Configuration
This page provides an in-depth guide to configuring Rugix Ctrl for users who require more fine-grained control.
If you are using Rugix Bakery with a generic or specific target, Rugix Ctrl will recognize the system configuration automatically. You do not need to configure Rugix Ctrl in any way, unless this default configuration does not fit your needs.
Rugix Ctrl's system configuration is managed through the system configuration file /etc/rugix/system.toml
.
Throughout this documentation, root device refers to the parent block device of the block device mounted at /
or Rugix Ctrl's system partition mount point /run/rugix/mounts/system
, with the latter taking priority if present.
A manual configuration is still experimental. We may introduce breaking changes to the configuration format in minor versions. Note that this only means that you may have to migrate your configuration more frequently, not that your system will become unstable or break out of the sudden (assuming that you test updates properly).
Config and Data Partitions
The config partition and data partition serve as core storage elements for a device. We expect most setups to have both partitions, regardless of other aspects of the configuration, such as non-A/B update schemes. The config partition, usually the first on a device, holds critical settings like bootloader configurations and optional device-specific parameters. Meanwhile, the data partition retains persistent data, including user and system state, which is preserved across updates.
The config and data partition are configured in the config-partition
and data-partition
sections of the system configuration file, respectively.
The partitions can be specified either via the device
setting, which points to a specific block device, or via the partition
setting, which identifies a root device partition by its number.
Example configuration:
#:schema https://raw.githubusercontent.com/silitics/rugix/refs/tags/v0.8.0/schemas/rugix-ctrl-system.schema.json
[config-partition]
# The config partition is `/dev/sda1`.
device = "/dev/sda1"
[data-partition]
# The 7th partition of the root device is the data partition.
partition = 7
Setting disabled = true
allows the config and data partitions to be disabled individually.
The config partition is required for most bootloader integrations and for bootstrapping, while the data partition is required for state management.
If you use the state management feature, Rugix Ctrl will mount the partitions automatically to the following directories:
/run/rugix/mounts/config
: Config partition (usually read-only)./run/rugix/mounts/data
: Data partition (read-write).
In addition, it will mount the system partition at /run/rugix/mounts/system
(read-only).
If you do not use the state management feature, then Rugix Ctrl will not mount the partitions automatically.
In that case, you are responsible for mounting them (if they are not disabled) and you can specify their path via the path
setting.
By default, Rugix Ctrl will assume that the first partition on the root device is the config partition and that the sixth (GPT) or seventh (MBR) partition is the data partition, depending on the type of partition table it finds on the root device.
Update Slots
Rugix Ctrl's OTA update mechanism uses slots to flexibly handle different OTA scenarios and requirements.1 Typically, a slot corresponds to a device partition where updates can be applied. Each slot has a name and one of the following types:
block
: The slot is a block device.file
: The slot is a regular file (usually on the data partition).custom
: The slot has a custom update handler.
Block Slots: A Typical A/B Setup
Here is an example configuration for a typical A/B setup with four slots. The block device of a block
slot can be specified either explicitly via the device
setting or by a root device partition number via the partition
setting.
#:schema https://raw.githubusercontent.com/silitics/rugix/refs/tags/v0.8.0/schemas/rugix-ctrl-system.schema.json
[slots.boot-a]
type = "block"
device = "/dev/sda2"
immutable = true
[slots.boot-b]
type = "block"
device = "/dev/sda3"
immutable = true
[slots.system-a]
type = "block"
partition = 4
immutable = true
[slots.system-b]
type = "block"
partition = 5
immutable = true
The immutable
option is used to specify that the contents of the slot will only change with updates via Rugix Ctrl.
File Slots
File slots require a path
setting specifying an absolute path to a file.
Note that if a file
slot points to a path that is not persisted through reboots, then the contents of the slot will be lost when rebooting.
Thus, file
slots would typically point to files on the data partition, in the state directory, or are paired with a state management configuration persisting the respective files.
As with block
slots, file
slots also have an immutable
option.
If you want to update a directory, use a custom slot with a Tar archive as a payload that you can then extract.2
Custom Slots
Custom slots allow you to implement your own update logic that receives an arbitrary update payload as a stream on stdin.
This requires a handler
setting specifying an arbitrary command to install the update payload.
Here is an example to extract a Tar archive to a specific directory:
[slots.app-data]
handler = ["tar", "xf", "-", "-C", "/run/rugix/mounts/data/app/my-app-data"]
Note that custom slots are incompatible with block deduplication of the update payload (see Update Bundles).
Boot Groups
Slots are grouped into boot groups, which are sets of related slots into which the system can boot via a bootloader integration. Each boot group has a name and a slot mapping that defines aliases for slot names.
Example configuration for boot groups based on the A/B configuration given above:
[boot-groups.a]
slots = { boot = "boot-a", system = "system-a" }
[boot-groups.b]
slots = { boot = "boot-b", system = "system-b" }
An update bundle can carry updates for multiple slots, identified by their name or boot group alias.
Updates are installed to a designated boot group where the aliases are used to identify slots.
For the example given above, if an update includes boot
and system
slots, they will be installed to the appropriate A or B partitions based on the selected boot group.
Boot groups are also used to prevent updates of active slots, where an active slot is one referenced by the currently booted boot group.
Updates can be explicitly installed to a particular boot group using the --boot-group
parameter.
Without that parameter and if there are only two boot groups, Rugix Ctrl will automatically use the inactive boot group.
Boot Flow
Bootloader integrations are referred to as boot flows. Multiple boot flows may exist for the same bootloader, allowing Rugix Ctrl to adapt to different environments and serve as a drop-in replacement for other OTA solutions.
Boot flows are configured via the boot-flow
section, with the type
setting indicating the boot flow type.
Currently, Rugix supports the following boot flow types:
u-boot
: Uses an U-Boot environment file to switch between partitions (A/B setups only).grub-efi
: Uses a Grub environment file to switch between partitions (A/B setups only).tryboot
: Uses Raspberry Pi'stryboot
Mechanism (A/B setups only).custom
: Flexible integration based on an external script/program.
For further details on boot flows, we refer to the Boot Flows section.
Configuration Reference
For reference, here is the complete schema for system configuration files:
You will find the most recent version of this schema on GitHub.
Footnotes
-
There are two reasons why there are no native directory slots: First, we want to keep things simple within Rugix Ctrl and directory slots can trivially be implemented with custom handlers. Second, in contrast to directories, files are more directly usable for adaptive delta updates by computing an index over them. That's why we support them natively. ↩