Integration of Zchunk Delta Updates in SWUpdate within Yocto for NVIDIA Jetson Platforms
Integration of Zchunk Delta Updates in SWUpdate within Yocto for NVIDIA Jetson Platforms
This guide explains how to integrate zchunk-based delta updates into SWUpdate in a Yocto build for NVIDIA Jetson platforms, so a device can download only the changed chunks of an update artifact instead of downloading a full root filesystem image every time. This approach is useful when OTA bandwidth is expensive, update artifacts are large, and the target layout is designed to support safe updates. In a Jetson + Yocto workflow, the usual building blocks are Yocto, Extending meta-tegra for OTA Updates: The rr-nvidia-ota Layer, SWUpdate, zchunk, and a server that supports HTTP range requests.
What this guide covers
This page focuses on the practical integration path for teams building custom Jetson products with Yocto and looking for smaller OTA transfers. It covers the high-level architecture, the Yocto layers involved, the artifact flow, an example SWUpdate description, validation steps, and the most important operational caveats for production deployments.
Why use zchunk delta updates with SWUpdate?
A zchunk artifact is split into independently addressable chunks. This format compress can inspect the zchunk header, determine which chunks are already present locally, and download only the missing chunks from the server. SWUpdate documents this delta-update flow and explains that zchunk metadata can be used to identify which parts of an artifact must be fetched, while the target system reconstructs the final payload from the local base plus the downloaded chunks. This is especially relevant for embedded Linux systems with large root filesystem images and limited network budgets.
In practice, this means the update server still stores the full zchunk artifact, but the device may transfer far less data than the complete image when the old and new software versions are similar. The main benefit is reduced bandwidth usage. The main trade-off is more integration complexity and a stronger need for validation, rollback planning, and environment documentation.
Quick answer: when should you use this approach?
Use zchunk delta updates with SWUpdate on NVIDIA Jetson when all of the following are true:
- Your Yocto image artifacts are large enough that full OTA downloads are costly.
- Consecutive software releases share enough data that chunk reuse is meaningful.
- Your artifact hosting endpoint supports HTTP range requests.
- Your update design already addresses safety topics such as A/B partitions, rollback, signature verification, and power-loss handling.
If your product cannot tolerate recovery complexity, or if release-to-release changes are so large that chunk reuse is minimal, a full-image OTA workflow may be simpler and easier to validate. A simplified data flow is shown below:
Yocto build host
|
| 1. Build rootfs / image artifact
v
New image artifact (for example, a rootfs tarball or filesystem image)
|
| 2. Convert artifact to .zck and extract header metadata as needed
v
zchunk artifact + header metadata
|
| 3. Package header / metadata into the SWU bundle
v
SWUpdate .swu package
|
| 4. Publish full zchunk artifact on HTTP server with Range support
v
Artifact server
|
| 5. Target inspects zchunk metadata, reuses local chunks, downloads missing chunks
v
Jetson target reconstructs payload and applies the update
Components and references
The integration usually involves the following components:
- Yocto build environment for the Jetson product.
- Extending meta-tegra for OTA Updates: The rr-nvidia-ota Layer or another OTA-oriented integration layer when applicable.
- The official meta-swupdate layer for building SWUpdate within Yocto.
- zchunk tooling for chunked artifact generation.
- A target update strategy compatible with your platform layout and rollback plan.
Primary references:
- SWUpdate Integration in Yocto with meta-tegra for NVIDIA Jetson Platforms
- SWUpdate delta update documentation
- meta-swupdate: building with Yocto
- meta-swupdate repository
- zchunk repository
- meta-tegra repository
- OpenEmbedded Layer Index: meta-tegra
- How to Use A/B Filesystem Redundancy and OTA with NVIDIA Jetpack
- RidgeRun Platform Security Manual/Getting Started/Over-the-Air
Tested environment
| Item | Value |
|---|---|
| Jetson module | NVIDIA Jetson AGX Orin Industrial and Jetson Orin NX |
| JetPack / L4T base | L4T r36.4.4 |
| Yocto release | scarthgap (Yocto 5.0) |
| meta-tegra branch / commit | scarthgap / 447c21467f65be2389f68a189b6871f13729d222 |
| meta-swupdate branch / commit | scarthgap / 81f4faa406e70dfa514e2f7642f97df33d3b84ae |
| SWUpdate version | swupdate_git.bb, PV = "2025.12+git${SRCPV}", SRCREV = "a3da115bb972d8a07bc360f62c6df53d2a894c7a" |
| zchunk version | 1.4.0 |
| Host OS | Ubuntu 24.04 |
Yocto integration prerequisites
At minimum, document the layers and packages required for the build. The exact names and configuration flags can vary by release, so the page should show the verified values used in the tested environment.
Required layers
In most Yocto-based integrations, the following layers are relevant:
- openembedded-core and your base BSP layers
- meta-openembedded, because meta-swupdate depends on it
- meta-swupdate for SWUpdate recipes and SWU generation
- meta-tegra for Jetson platform support
Example bblayers.conf excerpt
BBLAYERS += " \
${TOPDIR}/../layers/meta \
${TOPDIR}/../layers/meta-tegra \
${TOPDIR}/../layers/meta-oe \
${TOPDIR}/../layers/meta-python \
${TOPDIR}/../layers/meta-networking \
${TOPDIR}/../layers/meta-filesystems \
${TOPDIR}/../layers/meta-virtualization \
${TOPDIR}/../layers/meta-tegra-community \
${TOPDIR}/../layers/meta-tegra-support \
${TOPDIR}/../layers/meta-demo-ci \
${TOPDIR}/../layers/meta-tegrademo \
${TOPDIR}/../layers/meta-swupdate \
"
Requirements
Integration of SWUpdate
To add the delta update support using Zchunk, ensure that SWUpdate is integrated into the Yocto build, the following wiki provides instructions for integration:
Once SWUpdate is integrated into the build, it is important to verify that the machine layer configuration has the highest priority. This ensures that the changes required for delta update support are applied correctly.
In the following file, verify that:
<path-to-the-repository>/layers/<meta-custom-or-meta-tegra-demo-distro>/conf/layer.conf
Verify that the layer priority is set as follows:
BBFILE_COLLECTIONS += "tegrademo"
BBFILE_PATTERN_tegrademo = "^${LAYERDIR}/"
BBFILE_PRIORITY_tegrademo = "99"
Nginx
To test delta updates, it is necessary to host the .zck image file on a server. This allows verification of the correct behavior of SWUpdate when using this feature. For testing purposes, a local server can be set up on the PC.
To do this, install nginx:
sudo apt install nginx
Delta Update Support with Zchunk in SWUpdate
The tegra demo distro, as well as any meta-custom layer derived from this repository, already includes support for meta-swupdate and the required base configuration for delta updates. However, additional configuration is needed to enable the complete workflow for Zchunk-based delta updates.
Zchunk Requirements
Zchunk requires two files to generate and apply delta updates:
- A
.zckfile (compressed data with chunking) - A
.zckheaderfile, which contains metadata describing the changes between versions
The .zckheader file is used by SWUpdate to determine the differences and apply the delta update efficiently.
Generating Zchunk Artifacts for Delta Updates
To generate the required files, update the image recipe of the image you want to build. For example:
- Tegra demo distro:
<path-to-the-repository>/layers/meta-tegrademo/recipes-demo/images/demo-image-base.bb
- Custom layer:
<path-to-the-repository>/layers/meta-custom/recipes-custom/images/custom-image-base.bb
Add the following lines to the image recipe:
# Generate an ext4 rootfs plus the zchunk artifacts used by SWUpdate delta updates. IMAGE_CLASSES += "image_types_zchunk" IMAGE_FSTYPES += " ext4 ext4.zck ext4.zck.zckheader"
To enable delta updates, it is also necessary to configure the image recipe to use the correct output format for the artifact included inside the SWUpdate (.swu) bundle. This file format is essential for enabling the delta update mechanism.
Modify the following file:
<path-to-the-repository>/layers/<meta-custom-or-meta-tegra-demo-distro>/dynamic-layers/meta-swupdate/recipes-demo/images/swupdate-image-tegra.bb
Replace:
ROOTFS_FILENAME ?= "${SWUPDATE_CORE_IMAGE_NAME}-${MACHINE}.rootfs.tar.gz"
With:
# The .swu bundles the zchunk header artifact; the target uses it to compare
# against ROOTFS_DELTA_URL and download only the missing chunks from the .zck.
ROOTFS_FILENAME ?= "${SWUPDATE_CORE_IMAGE_NAME}-${MACHINE}.rootfs.ext4.zck.zckheader"
By default, the root filesystem is generated as a .tar.gz archive. However, this format is not suitable for Zchunk-based delta updates because it is a compressed archive that does not preserve a stable binary structure, making it impossible to perform efficient chunk-level comparisons between versions.
For delta updates, the output must use a format such as .ext4.zck, which supports chunking and allows SWUpdate to identify and transfer only the modified portions of the filesystem.
Configuring the URL for the Compressed RootFS Image
To reduce the size of the SWUpdate (.swu) bundle, the compressed root filesystem image is hosted on a server instead of being included directly in the bundle. This approach allows the .swu package to remain small by including only the .zck.header file, while the full compressed image is downloaded from the server during the update process. In the same file swupdate-image-tegra.bb:
# ROOTFS_DELTA_BASE_URL to the host reachable by the target, e.g.
ROOTFS_DELTA_BASE_URL = "http://<ip-of-the-pc>:8000"
ROOTFS_DELTA_URL ?= "${ROOTFS_DELTA_BASE_URL}/${SWUPDATE_CORE_IMAGE_NAME}-${MACHINE}.rootfs.ext4.zck"
In this setup, the image is hosted on a PC configured as a server (e.g., using nginx). Therefore, ROOTFS_DELTA_BASE_URL must be set to the IP address of that PC.
Ensure that both the target device and the host PC are connected to the same network (typically via Ethernet) so they share the same IP subnet. For example:
- PC: 192.168.100.45
- Target device: 192.168.100.47
And the server is properly configured and accessible on the specified port.
Add the Configuration for Delta Updates
To enable delta update support, you need to add the required SWUpdate configuration options for Zchunk and delta updates.
First, create a file named delta.cfg in the following path:
<path-to-the-repository>/layers/<meta-custom-or-meta-tegra-demo-distro>/dynamic-layers/meta-swupdate/recipes-support/swupdate/swupdate/delta.cfg
Add the following configuration options to the file:
CONFIG_DELTA=y CONFIG_ZSTD=y
These options enable delta update support and the required compression backend.
Next, add the delta.cfg file to the SRC_URI in the swupdate_%.bbappend file located at:
<path-to-the-repository>/layers/<meta-custom-or-meta-tegra-demo-distro>/dynamic-layers/meta-swupdate/recipes-support/swupdate/swupdate_%.bbappend
Update SRC_URI as follows:
SRC_URI += "\
file://systemd.cfg \
file://hash.cfg \
file://part-format.cfg \
file://archive.cfg \
file://disable-uboot.cfg \
file://delta.cfg \
"
By adding delta.cfg to SRC_URI, the file is included during the SWUpdate build process. This ensures that delta update support is enabled when SWUpdate is compiled.
Modifications in sw-description for Delta Updates
To enable delta update support, the sw-description file must be modified to use the delta update mechanism instead of the default full image installation.
File to modify:
<path-to-the-repository>/layers/<meta-custom-or-meta-tegra-demo-distro>/dynamic-layers/meta-swupdate/recipes-demo/images/swupdate-image-tegra/sw-description
Key Changes
1. Change the image type to delta
Replace:
type = "archive";
With:
type = "delta";
This tells SWUpdate to perform a delta update instead of installing a full root filesystem.
2. Remove partition formatting
In the original configuration, partitions are formatted before installing the image:
partitions: (
{
type = "diskformat";
device = "...";
properties: {
fstype = "ext4";
force = "true";
}
}
);
Remove this section for delta updates. Delta updates require the existing filesystem as a base for comparison, so formatting the partition would break the update process.
3. Replace archive-based installation with delta properties
Replace the archive configuration:
type = "archive"; filesystem = "ext4"; path = "/"; installed-directly = true; preserve-attributes = true; sha256 = "...";
With:
type = "delta";
properties: {
url = "@@ROOTFS_DELTA_URL@@";
chain = "raw";
source = "<active-partition>";
source-size = "detect";
}4. Configure delta-specific properties
Each delta image must include the following properties:
- url: Points to the .zck file hosted on the server
- chain: Defines how the update is applied (typically "raw")
- source: The currently active partition used as the base for delta computation
- source-size: Automatically detects the size of the source partition
Final sw-description for Delta Updates
After applying the required modifications, the complete sw-description file should look as follows:
software =
{
version = "@@DISTRO_VERSION@@";
@@MACHINE@@ = {
hardware-compatibility: [ "1.0" ]
system = {
slot_a : {
images: (
{
filename = "@@ROOTFS_FILENAME@@";
type = "delta";
device = "@@ROOTFS_DEVICE_PATH@@/APP_b";
properties: {
url = "@@ROOTFS_DELTA_URL@@";
chain = "raw";
source = "@@ROOTFS_DEVICE_PATH@@/APP";
source-size = "detect";
}
},
{
filename = "@@DEPLOY_KERNEL_IMAGE@@";
device = "@@ROOTFS_DEVICE_PATH@@/@@KERNEL_B_PARTNAME@@";
},
{
filename = "@@DTBFILE@@";
device = "@@ROOTFS_DEVICE_PATH@@/@@KERNEL_B_DTB_PARTNAME@@";
}
);
files: (
{
filename = "tegra-bl.cap";
path = "@@TEGRA_SWUPDATE_CAPSULE_INSTALL_PATH@@";
properties = {create-destination = "true";}
name = "tegra-bootloader-capsule"
version = "@@TEGRA_SWUPDATE_BOOTLOADER_VERSION@@"
install-if-different = @@TEGRA_SWUPDATE_BOOTLOADER_INSTALL_ONLY_IF_DIFFERENT@@
},
{
filename = "@@ESP_ARCHIVE@@"
type = "archive"
installed-directly = true
path = "/boot/efi"
name = "tegra-bootloader-capsule"
version = "@@TEGRA_SWUPDATE_BOOTLOADER_VERSION@@"
install-if-different = @@TEGRA_SWUPDATE_BOOTLOADER_INSTALL_ONLY_IF_DIFFERENT@@
}
);
scripts: (
{
filename = "tegra-swupdate-script.lua";
type = "lua"
sha256 = "$swupdate_get_sha256(tegra-swupdate-script.lua)";
}
);
};
slot_b : {
images: (
{
filename = "@@ROOTFS_FILENAME@@";
type = "delta";
device = "@@ROOTFS_DEVICE_PATH@@/APP";
properties: {
url = "@@ROOTFS_DELTA_URL@@";
chain = "raw";
source = "@@ROOTFS_DEVICE_PATH@@/APP_b";
source-size = "detect";
}
},
{
filename = "@@DEPLOY_KERNEL_IMAGE@@";
device = "@@ROOTFS_DEVICE_PATH@@/@@KERNEL_A_PARTNAME@@";
},
{
filename = "@@DTBFILE@@";
device = "@@ROOTFS_DEVICE_PATH@@/@@KERNEL_A_DTB_PARTNAME@@";
}
);
files: (
{
filename = "tegra-bl.cap";
path = "@@TEGRA_SWUPDATE_CAPSULE_INSTALL_PATH@@";
properties = {create-destination = "true";}
name = "tegra-bootloader-capsule"
version = "@@TEGRA_SWUPDATE_BOOTLOADER_VERSION@@"
install-if-different = @@TEGRA_SWUPDATE_BOOTLOADER_INSTALL_ONLY_IF_DIFFERENT@@
},
{
filename = "@@ESP_ARCHIVE@@"
type = "archive"
installed-directly = true
path = "/boot/efi"
name = "tegra-bootloader-capsule"
version = "@@TEGRA_SWUPDATE_BOOTLOADER_VERSION@@"
install-if-different = @@TEGRA_SWUPDATE_BOOTLOADER_INSTALL_ONLY_IF_DIFFERENT@@
}
);
scripts: (
{
filename = "tegra-swupdate-script.lua";
type = "lua"
sha256 = "$swupdate_get_sha256(tegra-swupdate-script.lua)";
}
);
};
};
}
}
Zchunk Chunk Size Tuning
By default, Zchunk generates relatively small chunks when creating .zck files. While this improves granularity for delta updates, it can also increase the time required to verify the root filesystem, since more chunks need to be processed.
To optimize this behavior, you can increase the chunk size. Larger chunks reduce the number of metadata entries and improve verification performance, at the cost of slightly less granularity in delta updates.
Why Use a Custom .bbclass
In Yocto, a .bbclass is used to encapsulate reusable build logic and configuration. Creating a custom class allows you to:
- Centralize Zchunk tuning parameters.
- Reuse the configuration across multiple images.
- Avoid modifying upstream classes (keeping your layer maintainable and clean).
Creating the Zchunk Tuning Class
Create the bbclass for Zchunk
Navigate to your layer:
cd <path-to-the-repository>/layers/<meta-custom-or-meta-tegra-demo-distro>/ mkdir classes-recipe
Create a file named:
classes-recipe/zchunk-tuning.bbclass
Add the following content:
# Override the default zchunk conversion to use larger chunk sizes for rootfs
# images, reducing metadata overhead and improving delta-update efficiency.
ZCK_CHUNK_MIN_SIZE ?= "16384"
ZCK_CHUNK_MAX_SIZE ?= "129024"
CONVERSION_CMD:zck = "zck --output ${IMAGE_NAME}.${type}.zck -u --chunk-hash-type sha256 --chunk-min ${ZCK_CHUNK_MIN_SIZE} --chunk-max ${ZCK_CHUNK_MAX_SIZE} ${IMAGE_NAME}.${type}"
Applying the Class to the Image
To enable this tuning, add the custom class to IMAGE_CLASSES in your image recipe.
- Tegra demo distro:
<path-to-the-repository>/layers/meta-tegrademo/recipes-demo/images/demo-image-base.bb
- Custom layer:
<path-to-the-repository>/layers/meta-custom/recipes-custom/images/custom-image-base.bb
Modify:
IMAGE_CLASSES += "image_types_zchunk zchunk-tuning"
Extending Zchunk to Support Custom Chunk Sizes
Once the custom .bbclass is added, it is necessary to extend Zchunk itself to support configurable chunk sizes. By default, Zchunk does not expose CLI options to control minimum and maximum chunk sizes, so a patch must be applied.
Navigate to your layer and create the required directory:
cd <path-to-the-repository>/layers/<meta-custom-or-meta-tegra-demo-distro>/ mkdir -p recipes-support/zchunk/
Create the following file:
recipes-support/zchunk/zchunk_%.bbappend
Add the following content:
SUMMARY = "zchunk CLI chunk-size tuning patch"
DESCRIPTION = "Applies a patch to zchunk that exposes minimum and \
maximum chunk size CLI options so Yocto image conversions can tune zchunk \
chunking behavior."
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += " file://0001-zck-add-chunk-min-max-cli-options.patch"
Create a directory to store the patch:
cd <path-to-the-repository>/layers/<meta-custom-or-meta-tegra-demo-distro>/recipes-support/zchunk/ mkdir zchunk
Create the patch file:
Note: This patch modifies upstream Zchunk behavior by exposing additional CLI options. As a result, it may need to be reviewed and maintained across Zchunk version updates to ensure compatibility.
0001-zck-add-chunk-min-max-cli-options.patch
Add the patch content
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: CarlosQG <carlos.quiros@ridgerun.com>
Date: Tue, 31 Mar 2026 09:00:00 -0600
Subject: [PATCH] zck: add chunk min/max CLI options
Expose chunk size bounds already supported by the zchunk library so
Yocto image conversions can tune chunking without patching upstream
classes or custom wrappers.
---
src/zck.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/src/zck.c b/src/zck.c
--- a/src/zck.c
+++ b/src/zck.c
@@ -31,6 +31,8 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
+#include <errno.h>
+#include <limits.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -57,6 +59,10 @@
"Set zstd compression dictionary to FILE"},
{"manual-chunk", 'm', 0, 0,
"Don't do any automatic chunking (implies -s)"},
+ {"chunk-min", 201, "SIZE", 0,
+ "Set minimum chunk size in bytes"},
+ {"chunk-max", 202, "SIZE", 0,
+ "Set maximum chunk size in bytes"},
{"chunk-hash-type", 'h', "HASH", 0,
"Set hash type to one of sha256, sha512, sha512_128"},
{"uncompressed", 'u', 0, 0,
@@ -74,6 +80,8 @@
zck_log_type log_level;
char *split_string;
bool manual_chunk;
+ long long chunk_min_size;
+ long long chunk_max_size;
char *output;
char *dict;
char *compression_format;
@@ -82,6 +90,25 @@
zck_hash chunk_hashtype;
};
+static error_t parse_chunk_size(long long *value, const char *arg, const char *name) {
+ char *endptr = NULL;
+ unsigned long long parsed = 0;
+
+ errno = 0;
+ parsed = strtoull(arg, &endptr, 10);
+ if(errno != 0 || endptr == arg || *endptr != '\0') {
+ LOG_ERROR("Invalid %s value: %s\n", name, arg);
+ return EINVAL;
+ }
+ if(parsed == 0 || parsed > INT_MAX) {
+ LOG_ERROR("%s value must be between 1 and %d bytes\n", name, INT_MAX);
+ return EINVAL;
+ }
+
+ *value = (long long) parsed;
+ return 0;
+}
+
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
struct arguments *arguments = state->input;
@@ -104,6 +131,14 @@
case 'm':
arguments->manual_chunk = true;
break;
+ case 201:
+ if(parse_chunk_size(&arguments->chunk_min_size, arg, "minimum chunk size") != 0)
+ return EINVAL;
+ break;
+ case 202:
+ if(parse_chunk_size(&arguments->chunk_max_size, arg, "maximum chunk size") != 0)
+ return EINVAL;
+ break;
case 'h':
if (!strcmp(arg, "sha256"))
arguments->chunk_hashtype = ZCK_HASH_SHA256;
@@ -277,6 +312,18 @@
LOG_ERROR("%s\n", zck_get_error(zck));
exit(1);
}
+ }
+ if(arguments.chunk_max_size > 0) {
+ if(!zck_set_ioption(zck, ZCK_CHUNK_MAX, arguments.chunk_max_size)) {
+ LOG_ERROR("%s\n", zck_get_error(zck));
+ exit(1);
+ }
+ }
+ if(arguments.chunk_min_size > 0) {
+ if(!zck_set_ioption(zck, ZCK_CHUNK_MIN, arguments.chunk_min_size)) {
+ LOG_ERROR("%s\n", zck_get_error(zck));
+ exit(1);
+ }
}
if(arguments.uncompressed) {
if(!zck_set_ioption(zck, ZCK_UNCOMP_HEADER, 1)) {
--
2.43.0
This step ensures that Zchunk supports the following new CLI options:
- --chunk-min: Defines the minimum chunk size
- --chunk-max: Defines the maximum chunk size
By default, these parameters are not exposed, which prevents fine-tuning of chunk behavior during image generation.
Overriding Chunk Size Parameters in local.conf
If you want to use other values in this parameter it can set in the local.conf which it in the next path:
<path-to-the-repository>/build/conf/local.conf
Add the following content:
# Bound zchunk's automatic chunking to reduce metadata and source-side hashing work. ZCK_CHUNK_MIN_SIZE = "32768" ZCK_CHUNK_MAX_SIZE = "262144"
Build the image with SWUpdate
To ensure to generate the swupdate bundle with the changes of the delta update and the image with the compress format it clean the demo-image-base and the swupdate:
- Tegra demo distro:
bitbake -c clean demo-image-base swupdate-image-tegra
- Custom layer:
bitbake -c clean custom-image-base swupdate-image-tegra
To generate an image that includes SWUpdate support, run:
bitbake swupdate-image-tegra
Host the PC as a server.
To test delta updates, the PC must be configured as a server to host the .zck image so the target board can download the required chunks during the update process.
1. Create a directory to host the image
sudo mkdir -p /tmp/zchunk
2. Copy the generated .zck file from the build.
sudo cp -av <path-to-the-repository>/build/tmp/deploy/images/<machine>/<image>-<machine>.rootfs-<timestamp>.ext4.zck /tmp/zchunk/
3. Create a symbolic link with the expected name
SWUpdate expects the file to have a specific name (without the timestamp), so create a symbolic link:
cd /tmp/zchunk/ sudo ln -sf <image>-<machine>.rootfs-<timestamp>.ext4.zck <image>-<machine>.rootfs.ext4.zck
4. Set the correct permissions
sudo chmod 755 /tmp/zchunk sudo chmod 644 /tmp/zchunk/*.zck
This ensures the server can properly access and serve the files without permission issues.
5. Create the nginx configuration file
nano /tmp/swupdate.conf
Add the following content:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
server {
listen 8000;
server_name _;
root /tmp/zchunk;
location / {
autoindex on;
default_type application/octet-stream;
add_header Accept-Ranges bytes;
}
}
}
6. Run nginx with the custom configuration
sudo nginx -c /tmp/swupdate.conf
The server hosts the .zck file and serves it over HTTP on port 8000. The Accept-Ranges header is required to enable partial downloads, which are used by zchunk to retrieve only the necessary chunks during delta updates. It is also important to ensure that the PC firewall allows incoming connections on port 8000, so the target board can successfully access and download the required data.
Flash the Image
Once the build process is complete and the local server is configured, you can proceed to flash the generated image onto the target board. For JetPack 6, it is recommended to follow the JetPack 6 Integration – Flashing Jetson Platform wiki page.
This step programs the board with the image that includes SWUpdate support. Once the flashing process is complete, verify that SWUpdate is correctly included and available on the deployed image:
root@tegra-demo-distro:~# which swupdate /usr/bin/swupdate
Deploy and test
Once the image has been verified on the board, return to the build environment. In the deploy directory for the target machine, you will find the generated .swu file at:
cd <path-to-build-directory>/build/tmp/deploy/images/<machine>
The .swu file is named according to the target machine, following this format:
swupdate-image-tegra-<machine>.rootfs-<timestamp>.swu
Transfer the generated .swu file to the target board using scp. For example:
scp swupdate-image-tegra-<machine>.rootfs-<timestamp>.swu <user>@<ip-of-the-board>:/tmp/
Once is complete transfer to the board, run the update with:
cd /tmp/ swupdate -i /tmp/swupdate-image-tegra-<machine>.rootfs-<timestamp>.swu
After running the update file, reboot the board to apply the update. After the reboot process, verify the following:
- The root partition should change
- The nvbootctrl dump-slots-info output should show boot from the alternate boot slot with Capsule update status:1.
root@tegra-demo-distro:~# nvbootctrl dump-slots-info Current version: 36.4.4 Capsule update status: 1 Current bootloader slot: B Active bootloader slot: B num_slots: 2 slot: 0, status: normal slot: 1, status: normal
Troubleshooting
The target downloads the full artifact instead of only changed chunks
Common causes include:
- releases are too different for meaningful chunk reuse
- chunking parameters changed between versions
- the wrong base artifact is present on the device
- the target cannot reuse local data as expected
- the artifact host does not support range requests correctly
SWUpdate cannot apply the delta package
Common causes include:
- handler configuration mismatch
- incorrect properties in
sw-description - wrong target partition path
- missing dependencies in the Yocto image
- mismatch between the SWUpdate version and the packaging method
Range requests work in curl but not in the device workflow
Check for:
- proxy or CDN behavior
- authentication redirects
- headers stripped by a reverse proxy
- device-side certificate or TLS problems
Summary
zchunk delta updates in SWUpdate can reduce OTA transfer size for Yocto-based NVIDIA Jetson products when the system has a good base artifact for chunk reuse, the server supports range requests, and the update layout is validated for safety. The strongest version of this page is not just a generic procedure: it clearly documents the exact Yocto layers, software versions, target layout, SWUpdate description, hosted artifact flow, measured bandwidth savings, and Jetson validation results.
FAQ
- What problem does zchunk solve in SWUpdate?
- zchunk helps reduce OTA download size by allowing the target to reuse unchanged chunks from an existing artifact and fetch only the missing chunks required to reconstruct the new payload.
- Do I need a special server to host the update artifact?
- You do not necessarily need a proprietary OTA server, but the hosting endpoint should reliably support HTTP range requests so the device can fetch only the byte ranges it needs from the zchunk artifact.
- Is this approach always better than full-image OTA updates?
- No. It is most useful when consecutive releases are similar enough for chunk reuse to be significant. Full-image updates can still be easier to validate and support in some products.
- What should be benchmarked on Jetson?
- At minimum, benchmark transferred bytes, update time, CPU load during reconstruction, storage overhead, and rollback behavior under controlled network conditions.
- What should be documented for reproducibility?
- Document the Jetson module, carrier board, JetPack or L4T release, Yocto release, meta-tegra and meta-swupdate branches, SWUpdate version, zchunk version, and host OS used for the build and validation.
Related pages
- Yocto
- RidgeRun Yocto Developer Guide
- Extending meta-tegra for OTA Updates: The rr-nvidia-ota Layer
- SWUpdate Integration in Yocto with meta-tegra for NVIDIA Jetson Platforms
- How to Use A/B Filesystem Redundancy and OTA with NVIDIA Jetpack
- RidgeRun Platform Security Manual/Getting Started/Over-the-Air
- JetPack OTA Updates: Tips and Tricks
Contact Us
Need help integrating OTA updates into a Jetson Yocto product, validating an A/B update design, or measuring the real bandwidth savings of a delta-update workflow? Contact RidgeRun through the official support and inquiry channel:
References
- SWUpdate Integration in Yocto with meta-tegra for NVIDIA Jetson Platforms
- SWUpdate overview
- SWUpdate delta update documentation
- meta-swupdate: building with Yocto
- meta-swupdate repository
- zchunk repository
- meta-tegra repository
- OpenEmbedded Layer Index: meta-tegra
For direct inquiries, please refer to the contact information available on our Contact page. Alternatively, you may complete and submit the form provided at the same link. We will respond to your request at our earliest opportunity.
Links to RidgeRun Resources and RidgeRun Artificial Intelligence Solutions can be found in the footer below.