Production Programming with Torizon
Introduction
This article will go over the recommended workflow to prepare your Torizon OS based product for production in the Torizon environment.
This includes details on the production programming of your software and the provisioning of your device to Torizon Cloud, so you can benefit from our secure update features.
Not all methods will be covered here, but the commonly recommended ones will. If you have a specific use case that does not fit into this guide feel free to contact Toradex to discuss it further.
If you are not using Torizon OS, please see our Production Programming for Linux article to learn the recommended methods outside Torizon.
This article complies with the Typographic Conventions for the Toradex Documentation.
Prerequisites
In order to perform production programming in Torizon, you should have:
- The Torizon OS images and/or application files readily available
- TorizonCore Builder installed on your host machine
- Toradex Easy Installer download in your host machine
If you need provisioning at scale:
- Commercial license for your Torizon Cloud account
Production Programming
Production programming refers to the at-scale methods and processes used to program multiple modules with your product’s unique software. It’s important to have a reliable and consistent method for this, as any issues at this stage will be scaled with the number of products you ship, affecting the production capacity and cost.
At this stage, the most important steps to consider are:
- How to create your master Torizon OS image, the initial image that will be used to flash your devices in production.
- How to install your image on the device in a practical and easily reproducible way.
Creating the image - TorizonCore Builder
Our TorizonCore Builder tool is the recommended way to customize a Torizon OS image to suit your product requirements. This tool allows easy customization of nearly all aspects of the OS, however for a more detailed look at its features please take a look at TorizonCore Builder Tool - Customizing Torizon OS Images.
For now, we’ll highlight the most important features of this tool that are relevant for production programming.
The build
command is how you will be producing your custom image once in production. The build command takes in a .yaml
file that acts as a script for TorizonCore Builder. This allows the creation of your custom image to be automated and reproducible.
The result will be a Torizon OS image that can be installed using Toradex Easy Installer.
Creating the OS image
Using the build
command you can simplify your production image components to 3 main components:
- The input Torizon OS image: This is the base image that your changes and customizations will be based on top off.
- The customized components: These can be things like device-trees, device-tree overlays, or container-related components. Basically, the things that will be used to customize the input image.
- The build command
.yaml
file itself: This is how you will configure TorizonCore Builder to apply your customizations to your input image.
These 3 types of components can be version-controlled using Git or other version-control tools. In this way you ensure that your product's Torizon OS image can be reliably reproduced or modified as it matures.
Afterward, let’s highlight some key features and customization options that are relevant to production programming:
- Set an image to be auto-installed upon detection by Toradex Easy Installer - our installation tool. This allows for unmanned programming of devices.
- Set an image to be auto-rebooted once the installation is complete. This can be important for some systems that need to boot into the installed image right after installation in order to perform any needed setup.
- Accept any licenses or EULAs that are present in the image. This is especially useful for NXP-based modules since many of these have NXP EULAs that must be explicitly accepted.
- Capture changes that you want to be reproduced in every device, such as update configuration, network configuration and many others.
Further details and usage on each of these can be found on TorizonCore Builder Tool “build" command.
Bundling the Application
To bundle your application containers to the image used for production programming, you will also be using the same yaml
configuration file used to customize your Torizon OS image. When you run the build
command to build your image, your application containers will automatically be bundled into the image. This is how you will be installing your applications in your custom image and having them run upon boot.
Preparing the Devices for Torizon Cloud
For using your device with our Torizon Cloud, you should add at-scale provisioning data to your image; this can be easily done by adding specific properties to your tcbuild.yaml
file, the same one you normally use to build your custom Torizon OS image. The details are described in Provisioning at Scale. Once the resulting image is installed on a device, it will be provisioned automatically to Torizon Cloud and will be ready for using our secure remote or offline update, devices monitoring, and new features to be released.
Serving the Custom Image on the LAN
TorizonCore Builder includes the capability to serve an Easy Installer image over LAN. It has a pre-configured Avahi Zeroconf service, so that Easy Installer automatically see it as an image source over the LAN.
Learn how to use it on TorizonCore Builder Tool - Commands Manual - images serve.
Installing the image - Toradex Easy Installer
The recommended way to flash your Torizon OS image is by using the Toradex Easy Installer tool. This is available on all Torizon OS-supported modules.
The most usual ways to accomplish production programming with Toradex Easy Installer are:
- Physical media (SD Card, USB stick): auto-install images plugging the physical media to the carrier board.
- LAN (Ethernet): Usage of unattended ethernet auto-install for devices that don’t have external media access available.
- The easiest way to do it is with TorizonCore Builder, as explained in the previous section Serving the custom image on the LAN.
- Alternatively, you can configure your own server, as described on Unattended flashing Over Ethernet.
For more information on the usage and details of Easy Installer please see the Detailed manual. Any details regarding Toradex Easy Installer that are specific to Torizon systems will be covered in this article.
Provisioning at Scale
This section is optional, and only applies to those making use of our Torizon Cloud.
To use provisioning at scale as documented below, requires at least TorizonCore version 5.7.0.
With Torizon OS based products there is also the option of provisioning your devices to our Torizon Cloud. By provisioning your device this allows it to connect to your specific account on our services website. This then enables your device to be updated in the future allowing ongoing software updates and maintenance. Being provisioned will also allow your device to leverage other services such as device monitoring and any other future feature we may add to our platform.
Getting Provisioning Data
The first step in the provisioning process is getting provisioning data that is specific to your account. Typically you will only have to run this step once since provisioning data can be reused multiple times.
Before we proceed you’ll need the credentials.zip
file for the account to which you want to provision devices. Since credentials access and other sensitive data are involved, this step should be run by your system admin or those with proper access to such information.
Next, let’s briefly cover the different types of provisioning data:
- Shared-Data: This type of provisioning data is used for provisioning a device for offline and online updates. This data is not security-sensitive. In our system, we distribute the data as a tarball that contains the data.
- Online-Data: This type of provisioning data is used only in provisioning for online updates. This data is security-sensitive and should be handled carefully. In our system we distribute the data as a base64 encoded string, making it easy to use in a CI pipeline or store in a secrets manager. Given the nature of this information avoid storing it in Git or other similar revision control systems.
A device that is provisioned for online updates is also capable of offline updates.
Now in order to get either provisioning data, TorizonCore Builder will be used. The platform provisioning-data
command can be used to fetch both types of provisioning data:
$ torizoncore-builder platform provisioning-data --credentials credentials.zip --shared-data shared-data.tar.gz --online-data DEFAULT
The command will then produce a tarball containing the shared-data and output the string that is the online-data. This data can then be stored for future provisioning use. For a detailed guide on the usage of this command please see the specific section in the commands manual
Installing Provisioning Data
Having obtained your provisioning data, you need to add it to a Torizon OS image that, when flashed to multiple devices, will allow each device to provision itself automatically. This is the way to achieve the "at scale" part of provisioning at scale.
Using Yocto Project/OpenEmbedded
When Building Torizon OS from Source With Yocto Project/OpenEmbedded, you need to execute the steps from the local.conf template.
Using TorizonCore Builder
To install the provisioning data using TorizonCore Builder, you will use the previously discussed build
command to produce Torizon OS images with provisioning data installed.
Providing the device with the provisioning data means that it will be able to validate updates. To get it registered in the Torizon Cloud, you will need to configure it for online updates.
Considering this scenario, make sure that you performed the proper configuration of the device for using online and/or offline updates and captured the changes to the image in the customization section of the file.
For example:
input:
easy-installer:
local: <INPUT_IMAGE>
customization:
<YOUR_CUSTOMIZATIONS>
output:
easy-installer:
local: <OUTPUT IMAGE>
provisioning:
mode: "online"
shared-data: <SHARED-DATA TARBALL>
online-data: <ONLINE-DATA STRING>
Recall that the online-data string is sensitive information. You’ll most likely want to make use of variable substitution, rather than inserting this string in plain text in your yaml
file.
For more details see the provisioning
property under the Output
section of the build
command’s yaml
file schema.
Alternatively, for quick tests outside of production, you can also use the stand-alone command images provision
in order to produce a provisioned image.
$ torizoncore-builder images provision --mode online --shared-data shared-data.tar.gz --online-data <your-well-kept-sensitive-string> <PATH TO INPUT IMAGE> <PATH TO WHERE OUTPUT IMAGE WILL BE PRODUCED>
As seen, the input for this command is the output of the previous platform provisioning-data command. The images provision
command will then output a Torizon OS image containing your provisioning information. This image can then be installed on a device using Toradex Easy Installer. For more details on the exact usage of this command refer to the TorizonCore builder commands manual.
Customizing the Provisioning Service
A device having online provisioning data will try to register itself to Torizon Cloud upon system startup; in case of errors preventing the registration, it will try again every 5 minutes (by default). This work is accomplished by a systemd service named "auto-provisioning" running on the device. The service only runs while the device is not registered to the cloud service yet.
Users wanting to register their devices to the cloud service before they leave factory should notice that the device will need to be rebooted to allow the execution of the auto-provisioning service. The easy-installer.autoreboot
field in the tcbuild.yaml
file (for users of the build
command of TorizonCore Builder) might be useful to achieve this.
Customizations to the service follow the normal procedures as with any other systemd service. Reasons for customizing the service would include limiting the amount of retries performed by the service or changing the delay between retries, to say a few. For example, to change the retry delay one could go to a running device and create a "systemd override" by running:
# systemctl edit auto-provisioning
In which case a new text editor would be spawned where one could enter (to change the delay to 1 minute):
[Service]
RestartSec=60
Once created you can capture the override using TorizonCore Builder into a "changes" directory which can then be fed into the build
command of the same tool.
Customizing the Device Name and ID
Before Torizon OS version 6.7.0-devel-202407 the device name is (randomly) generated by Torizon Cloud and the device ID is set to the hostname of the device. Starting with Torizon OS version 6.7.0-devel-202407 it is possible to customize the device name and ID used when registering the device to the cloud service. For this, one has to create a (Bash) script that will be sourced by the auto-provisioning
service handler; the service will look for the following scripts and source whichever is found first:
/etc/sota/auto-provisioning-overrides.sh
/usr/lib/sota/auto-provisioning-overrides.sh
The overrides script can define function get_device_name
and get_device_id
(both optional) which are responsible for generating the device name and ID, respectively.
The simplest way to create such an overrides script is going to a running device and executing:
# mkdir -p /etc/sota
# nano /etc/sota/auto-provisioning-overrides.sh
Then edit the overrides file; for example the following script will name the device my-device-<MAC-adress>
:
get_device_name() {
# Use MAC address of ethernet0 network device.
echo "my-device-$(cat /sys/class/net/ethernet0/address | tr -d ':')"
return 0
}
There are a few notes regarding these user-defined functions:
- Make sure to produce unique device names and IDs; for this, one could rely on the device's MAC address and/or serial number.
- Failures returned by the functions will prevent the device registration; so, avoid returning errors and try to always produce a valid name.
- Avoid taking too long to return from the functions since this also delays the execution of the auto-provisioning service (for example, if you need to perform operations on the network to generate the name, make sure you set appropriate timeouts for them); in the example given above, the script only depends on information readily available on a device which is the ideal situation.
Once the overrides script is created, one can capture the changes using TorizonCore Builder into a "changes" directory which can then be fed into the build
command of the same tool.
Provisioning Devices
Now that you have a Torizon OS image with provisioning data, that image can be installed into as many devices as needed, normally by means of Toradex Easy Installer.
Check Online Provisioning
If you've created your Torizon OS image with online provisioning data, the device will require an Internet connection after boot in order to complete the provisioning process. Specifically, it will need access to our Torizon Cloud domain.
To check the status of the service responsible for provisioning the device to Torizon Cloud one can execute the following command on a device:
# systemctl status auto-provisioning
or check the full logs with:
# journalctl --lines=all -f -u auto-provisioning
In case the service was executed and it succeeded to register the device to the cloud service, then a message such as "Device successfully provisioned" would appear in the logs. Another possibility is that the device was already provisioned on a previous boot, in which case the message would indicate that the service was skipped due to the presence of a key file, that is, the service being skipped in this case is also an indication of success.
In case of an error preventing the provisioning to succeed, the device will try again every 5 minutes (by default) and the process can be followed up through the logs.
One can also check if the device is able to communicate with the cloud service by looking at the aktualizr
logs:
# journalctl -f -u aktualizr\*
Check Offline Provisioning
In this case, you will not need an Internet connection to complete the provisioning process. All the information needed to check for trustworthy offline updates is received from the shared-data
.
The auto-provisioning service logs should display the message Auto-provisioning configuration file not found ...
.
The aktualizr logs should show the message Offline Updates are enabled
. Any warnings related to the online update process can be safely ignored.