OTA System Updates
Nexigon provides ready-made OTA update integrations for Rugix that implement the full update lifecycle described in the System Updates guide. These integrations are standalone scripts that compose Nexigon's primitives — properties, events, and repositories — to handle A/B system updates, boot group management, rollback detection, and version verification.
Two packaging options are available depending on your build system:
- Rugix Bakery: The
nexigon-rugixrepository provides ready-made Rugix recipes. - Yocto: The
meta-nexigonrepository provides Yocto layers, includingmeta-nexigon-rugixfor Rugix-based systems andmeta-nexigon-raucfor RAUC-based systems.
Setup with Rugix Bakery
Add the Nexigon repository to your rugix-bakery.toml:
[repositories]
nexigon = { git = "https://github.com/nexigon/nexigon-rugix.git", branch = "v0.2" }
Then add the nexigon/nexigon-rugix-ota recipe to your layer alongside the agent recipes:
recipes = [
# ...
"nexigon/nexigon-agent",
"nexigon/nexigon-agent-config",
"nexigon/nexigon-rugix-ota",
"nexigon/nexigon-rugix-watchdog",
]
The nexigon-rugix-watchdog recipe provides a safety net: if the system has not been committed within a timeout (default: 30 minutes), it triggers a reboot to roll back to the previous version.
The OTA recipe reads its configuration from the .env file in your project directory:
NEXIGON_HUB_URL="https://eu.nexigon.cloud"
NEXIGON_TOKEN="deployment_..."
NEXIGON_REPOSITORY="my-repo"
NEXIGON_PACKAGE="my-package"
It supports the following parameters:
| Parameter | Default | Description |
|---|---|---|
interval | 4h | How often to check for updates |
tag | stable | Default version tag to track |
use_bundle_hash | false | Use hash-based bundle verification instead of signatures |
The Nexigon template for Rugix Bakery provides a complete project setup with OTA updates, release scripts, and CI integration included.
Setup with Yocto
Add the meta-nexigon-rugix layer to your build. The layer depends on meta-nexigon-core, which provides the Nexigon Agent recipes.
Include the OTA recipe in your image:
IMAGE_INSTALL:append = " nexigon-rugix-ota"
The OTA configuration is baked into the image through BitBake variables. See the Kas example configurations for reference setups with both Rugix and RAUC.
For RAUC-based systems, use meta-nexigon-rauc and nexigon-rauc-ota instead. The RAUC integration follows the same architecture — the same properties, events, and repository primitives — with RAUC-specific bundle handling.
How It Works
The OTA integration runs as a systemd timer that triggers a check on boot and periodically thereafter. On each cycle, the script:
- Reads configuration. Checks
dev.nexigon.ota.configfor per-device overrides. If no override is set, falls back to the defaults baked into the image. - Checks boot state. If the active boot group differs from the default, the script commits the system — confirming that the previous update booted successfully. If the current version does not match the expected target, it records a rollback failure.
- Resolves the target version. Queries version info from the configured repository path to determine the target version.
- Compares versions. If the target version matches the installed version, there is nothing to do.
- Installs the update. Downloads the Rugix bundle and installs it via
rugix-ctrl update install. - Reboots. Reboots into the new version via
rugix-ctrl system reboot --spare.
Every state transition is published through the dev.nexigon.ota.status property and emitted as a structured event under the ota category. This gives you real-time status in the Nexigon UI and a full audit trail in the event log.
The full update script is about 200 lines of Bash. You can read it, understand it, and modify it to fit your requirements.
Configuration
The OTA configuration identifies where to look for updates. It consists of a path that points to a version path in a Nexigon repository:
{ "path": "my-repo/my-package/stable" }
The path follows the format <repository>/<package>/<version-tag>. The version tag is typically a floating tag like stable or canary that you reassign as you promote releases.
Defaults are baked into the image during build. For Rugix Bakery, the .env variables NEXIGON_REPOSITORY and NEXIGON_PACKAGE are combined with the tag recipe parameter (default: stable) into a default path.
Per-device overrides are set through the dev.nexigon.ota.config device property — either via the Nexigon UI's "Deploy Update" dialog or the CLI. When the property is removed, the device reverts to its baked-in defaults.
Bundle Verification
Rugix Ctrl verifies bundles before installation. Two verification modes are supported:
- Cryptographic signature (default): The bundle must have an embedded signature. This is the recommended setting for production deployments.
- Hash-based verification: The script reads the bundle hash from the asset metadata (
rugix.bundleHash) and passes it torugix-ctrlfor verification. Enable this with theuse_bundle_hashrecipe parameter.
Release Workflow
The Nexigon template for Rugix Bakery provides scripts for a complete release workflow:
./scripts/prepare-release.sh # Generate version, create in Hub
./scripts/build-release.sh customized-efi-amd64 # Build with pinned version
./scripts/upload-release.sh # Upload artifacts with metadata
The prepare-release.sh script generates a version identifier (e.g., build-20260401120000-abc1234), creates the version in the Nexigon repository, and writes a .release-env file that pins the version for subsequent steps. This ensures the version baked into the image matches the version uploaded to the repository.
Asset Metadata
The upload script attaches metadata to bundle assets:
{
"rugix": {
"bundleHash": "sha256:..."
},
"relations": {
"sbom": ["customized-efi-amd64.spdx.json"]
}
}
rugix.bundleHash: Used for hash-based verification when signature-based verification is not configured.relations.sbom: Links the bundle to its SBOM for traceability in the UI.
CI Integration
The template includes a GitHub Actions workflow that runs the same scripts. The prepare-release job creates the version and uploads .release-env as a GitHub Actions artifact. Parallel build jobs download it, build each system variant, and upload the results.