App Enable an Embedded SystemFollow article
App enabling an embedded Linux system with Ubuntu Core allows it to benefit from transactional updates, increased security and access to a “snap” application ecosystem.
In this post we take a look at snap packaging and Ubuntu Core, before loading the latter onto the tiny and yet formidable Intel Joule , exploring the system and installing Node-RED from the app store, then finally building an example application for use with an attached LimeSDR.
Note that Ubuntu Core can also be installed on Raspberry Pi and Intel NUC, amongst other hardware platforms.
Snaps and Snappy Ubuntu Core
Device software continues to become ever more complex as it moves beyond simpler “bare metal” applications or perhaps a minimal embedded O/S plus server processes, to applications that might integrate advanced capabilities via multiple frameworks each with many of their own dependencies.
Snaps address this complexity by packaging application software together with all their dependencies. Which might sound wasteful — since if you have two applications installed that use the same library, there will be two copies of that library on the system — however, it means that it doesn’t matter if those applications require different versions of a dependency. Furthermore, snaps are securely containerised in their own read-only filesystem, with segregated data stores.
The high degree of separation not only between snaps, but between snaps and the underlying Linux operating system, establishes a solid foundation for device security and stability. With the provision of clearly defined plug and slot interfaces to allow integration between snaps where required.
Fragment of the configuration file for the limesdr-server snap
In the above example we can see GitHub repositories for the application and dependencies specified, along with details of the build mechanism, configuration options and build order.
Snaps are described as “universal Linux packages” and while they are supported on the “classic” desktop Ubuntu, Debian, Yocto Project, Fedora and other Linux distributions, we will use the minimalist Ubuntu Core that was designed with embedded and IoT etc. devices in mind.
Ubuntu Core extends the snap philosophy to the O/S, with support for transactional updates and strict separation between kernel, device drivers, wider operating system and applications.
The device will need to be linked to an Ubuntu Single Sign-On (SSO) account and so if you do not already have one, it will be necessary to sign up.
Snappy Ubuntu Core is not provided as a self-hosted installer for the Intel Joule at present and so to load this we write out a classic Ubuntu desktop live/installation image, before booting from it and then using the command line to extract an Ubuntu Core filesystem to the internal MMC storage.
Note that if you are using Ubuntu to write out the live/installer image, this must be done using Startup Disk Creator and not unetbootin, since using the latter will not result in bootable device. Full instructions for use with Ubuntu, Windows and Mac OS X are available.
Initially some time was lost to USB flash drives not being recognised by the Intel Joule at boot, possibly due to the USB hub being used or some other incompatibility. So it is worth noting that it’s also possible to boot the live/installer image from a Micro SD card in the expansion board.
We booted from Micro SD and then had the Snappy Ubuntu Core image on a USB drive. Note here that the SD was enumerated as /dev/mmcblk0 and so the internal storage in the Joule became /dev/mmcblk1, with the command to extract the Core filesystem amended accordingly.
Upon restarting we could see that Ubuntu Core was booted from the Joule’s internal storage.
Following which we were prompted to configure the network and to enter the e-mail address of the Ubuntu SSO account that this device should be associated with.
With the device on the network we could now log in using the Ubuntu SSO ID and the IP address revealed to us via the attached monitor after it had been provisioned.
After logging in via SSH, in order to see what default snaps are installed we can enter:
$ snap list
From this point we could install more snaps via the command line, or alternatively we can create an access token that will allow us to use a slightly friendlier web interface.
If we point a web browser at the device IP, with https prefix and a port suffice of 4201, we are greeted by the Access Control page of the Snapweb application.
To generate a token for logging into the web interface we need to enter at the command line:
$ sudo snapweb.generate-token
Once logged in we can again list the installed snaps. We can also search for and install snaps, such as one that will give us the excellent tool for wiring the IoT, Node-RED.
One click later we can go back to the terminal and use ps to confirm that Node-RED is running.
If we then point a browser at the device and port 1880 we are greeted by the familiar editor.
At this point we could start creating new Node-RED flows (applications).
Classic Ubuntu as a snap
It is possible to actually install the classic Ubuntu operating system as a snap and use this, amongst other things, to enable development on the target device itself. All that is required is to enter:
snap install classic
$ sudo classic
Following which we enter a chroot environment and examining the contents of the /etc/os-release file shows us that this is Ubuntu 16.04.02.
However, it does look as though at the time of writing there may be some issues with the current release of the classic snap, since running commands to install packages resulted in signature checking errors. As such an example snap was built on a desktop system running classic Ubuntu.
Building snaps couldn’t be simpler and is driven by the snapcraft software. This can be installed, along with snapd — software that is also required to run snaps on Classic Ubuntu — with:
$ sudo apt-get install snapcraft snapd
Including snapd means that you can test the snap out on a desktop system first, before then copying it across to the target device running Snappy Ubuntu Core and installing it on this.
There are a selection of example snaps for the LimeSDR USB 3.0 software-defined radio (SDR) platform available on GitHub. The repository was cloned and the limesdr-server snap built. This enables a LimeSDR board to be accessed transparently over the network.
$ cd snapcraft-sandbox/limesdr-server
Resulting in the main application software plus all its dependencies being cloned from GitHub, built and then packaged as a fully self-contained application.
This could then be installed with:
$ sudo snap install --force-dangerous --devmode soapysdr-server_0.5.3.0_amd64.snap
The --force-dangerous option being required since instead of being delivered via an app store, the snap is being installed from an untrusted source, the filesystem. The --devmode option is a temporary workaround that enables the snap to get access to hardware peripherals (support is to be added for hotplugging peripherals and securely managing access to them).
For details of how to get started creating your own snaps, see the Snapcraft documentation.
Custom stores, device images and more
Ubuntu Core Advanced production model
We’ve only just scratched the surface of what’s possible with snaps and Ubuntu Core, with as yet unexplored features including creating custom Ubuntu Core images that integrate vendor support for particular hardware, along with custom “brand” app stores that device images are linked to.
For details of how to build Ubuntu Core support for new devices, integrating custom stacks, setting up brand stores, production models and more, see the Ubuntu Core documentation.