NEPI Engine – Source-Code Access, Build, and Installation Instructions
NEPI Engine software is available in source-code format, downloadable pre-built system images for select hardware platforms, and pre-installed hardware solutions from both Numurus and its edge-compute hardware partners. This document provides instructions for building NEPI Engine entirely from source. Use cases that would influence a source-code build over one of the alternative options include:
- Users may prefer complete control over system bring-up
- Users may be developing a NEPI solution on a hardware platform not currently supported by one of the other options.
NOTE: The installation guide “Pre-Built Image Download and Installation” includes valuable details on the NEPI file system architecture you may find helpful. The document is available at:
These instructions supplement the instructions found in the README.md file in the NEPI Engine nepi_rootfs_tools source-code repository (top level directory). Refer to that README.md for additional technical details on preparing the NEPI Engine Init root file system on a new device.
NOTE: This section assumes you already have access to the source-code for each of these software components is available in the NEPI Engine GitHub repo. To request access to NEPI Engine source-code repositories, visit:
NOTE: The following sections assume you have set up a NEPI ssh key on your PC and successfully connected to your NEPI device with an SSH connected terminal as described in NEPI Engine – Accessing the NEPI File System tutorial available at:
Preparing Init rootfs
Typically, the Init rootfs is based on a reference filesystem provided by the hardware manufacturer, stripped down to bare essentials with (temporary) internet access. From that point, the reference filesystem is converted to a NEPI Init rootfs by deploying and running the
script from the nepi_rootfs_tools Git repository. At present, the setup_nepi_init_rootfs.sh script assumes a modern Debian-based system with access to the APT package management tool and system init system, though porting to other distributions with robust package management and init system should not pose too difficult an exercise.
Inspecting and Editing Init rootfs
During the course of normal operation, the Init rootfs works with a number of files. It can be helpful to inspect and edit these files at times.
– Specifies device and mountpoint definitions for Main A/B partitions
– Specifies max failed boot count before automatic switchover to Inactive rootfs
– Specifies current Active and Inactive rootfs
– Intended to be edited by the user during new system bring-up
– Persistent file to allow Init rootfs to determine through consecutive failed boot cycles when the max failed boot count has been reached
– Should be treated as read-only in most instances, though users may find it helpful to edit this file (single numeric text value) as part of testing/debugging
– Main script to execute the Init rootfs tasks
– Should be treated as read-only in most instances. Editing this file is an advanced user operation and should only be undertaken if absolutely necessary for a particular use case (e.g., porting to a reference rootfs without systemd init system).
– Stores the stdout and stderr console output from the last boot-time execution of nepi_rootfs_ab_handling.sh
– Useful for debugging
At times it may be helpful to access these files or the Init rootfs at large, which is typically obscured by standard A/B rootfs hand-over. There are two standard ways to accomplish that:
1) If A and B partitions are on external media (e.g., SD card, SSD), the media can be removed prior to powering up the system, in which case the system will suspend in the Init rootfs (and increment the nepi_boot_failure_count.txt file). At that point, the Init rootfs can be treated as a standard Linux rootfs.
2) After booting into the Active rootfs, the Init rootfs may be mounted to a temporary mountpoint (e.g., /mnt/tmp) and then users may interact directly with files via that mountpoint or for a more native experience, can chroot to that mountpoint.
Typically rootfs A and B are based on the same reference rootfs as the Init rootfs, provided by the hardware manufacturer, and then extended to a Main NEPI rootfs by running one of the specific setup_nepi_rootfs scripts from the nepi_rootfs_tools repos (or creating/editing one of these scripts to suit your needs).
A typical complete system setup sequence is as follows:
1) Prepare the device with the Init rootfs as described in previous sections.
2) Partition the desired Main rootfs internal or external media to contain two EXT4 formatted partitions
a) ROOTFS_A: 32GB, ROOTFS_B: 32GB, (Optional) DATA: Remaining space on media
b) Partition can be done with media attached to device or attached to a host PC (running Linux or Linux VM). For on-device, standard Linux command-line tools like fdisk are useful, for host-side it may be preferable to use a graphical tool like gparted.
3) Copy the reference design (typically a system.img raw binary file) to both A and B partitions
a) Linux dd command-line tool is useful for this, as in
sudo dd if=./system.img of=/dev/nvme0n1 bs=64M status=progress
where the reference image is assumed to be ./system.img and ROOTFS_A device is at /dev/nvme0n1. Adjust these values as necessary for your particular application
4) Update the Init rootfs nepi_rootfs_ab_custom_env.sh file to call out A and B dev identifiers and reboot to boot into the Active Main rootfs (still just the default reference design). Log in as specified by the reference design provider.
5) Deploy and run the specific setup_nepi_<device_type>_rootfs.sh script (including all additional resources – typically best to copy over the entire nepi_rootfs_tools top-level folder using sftp or equivalent). This script may take a long time to execute. Pay attention to console output to check for errors or issues and fix these manually or update the script and rerun.
6) Deploy and build NEPI-specific source code according to separate NEPI open source documentation (Git repo READMEs, etc.)
NOTE: See the section “Customizing NEPI Engine” of this document for details on building and deploying NEPI Engine source code to your device.
7) Reboot to come up in a full working NEPI system.
8) Manually swap Active and Inactive rootfs (e.g., using the NEPI RUI Admin/Software page) and reboot to come up in the other rootfs (still just the default reference design).
9) Repeat steps 5 and 6 to convert this newly Active rootfs into a full working NEPI system.
There are alternative methods to achieve the same basic ends. For example, it is possible to locally mount the reference design on a development host (with hardware emulation support a la QEMU) and perform steps 5 and 6 from a chroot environment to create the full NEPI system image prior to deploying it to the device. A future revision of this document may outline that process in greater detail.
In addition to the three rootfs partitions previously discussed, NEPI optionally provides a separate “User Partition” to satisfy the following needs:
– Large file storage (beyond what could be stored directly in the Main rootfs partitions)
– Easy networked filesystem access (Windows, Linux, Mac supported)
– Persistence through updates – not overwritten by full system rootfs image updates.
This partition may reside on any available embedded or external storage device. It is typical to construct it from whatever space remains on the storage media that holds the A and B rootfs partitions, but this is not strictly necessary. It may be entirely separate physical storage media.
The Active Main rootfs must be configured to know how to mount and where to find the user partition. This definition exists in two places on the rootfs:
a) Actually a symbolic link to a file in /opt/nepi/config. Most often this is setup automatically by the specific setup_nepi_<device_type>_rootfs.sh script.
a) “nepi_storage_device” is the operative parameter
The User Partition must contain the fixed NEPI User Partition subdirectory structure and permissions. NEPI software will automatically construct these subdirectories if they don’t already exist during boot-up, so typically this requires no user setup.