NanoPi NEO2 - OpenWrt

Design Philosophy / Build process
Generic OpenWrt with mender app and u-boot - non mender load created (with mender if selected in config)
generic openwrt image post-processed to become mender image
post-processing: mender disk layout created, distribution specific config, files and apps added
reason: we use generic openwrt for multiple products, post processing differentiates
This (post processing) approach also makes if fairly easy to port to other OpenWrt architectures. Amlogic S912 (proprietary) also ported.
Mender, openwrt build host prerequisites
20-40GB free space for openwrt checkout, build
mkdir your_openwrt_build_dir; cd your_openwrt_build_dir (…/ from where git will place openwrt)
tar -zxvf openwrt-mender-v1.0.0.tar.gz
It is highly recommended to examine the various scripts prior to running them
Install Mender host build packages. If using Centos 7+, run else, determine how to install tools for your OS
Checkout required openwrt version, run: ./
Patch openwrt for mender, run: ./
cd openwrt
OpenWrt Configuration (make menuconfig, already done by, change after, if required)):
Target System: Allwinner A1x/A20/A3x
SubTarget: Allwinner A64
Target Profile: Nanopi NEO2 (H5) (may work with other H5 dreivitaves)
Target Images-> Boot Partition Size: 20M
Target Images-> Root partition size: 3650M (assumes 8GB Flash, Total Sectors: 15523840)
Advanced Configuration -> ToolChain Options->GCC Compiler Version->GCC 7.X (other versions may work, untested)
Advanced Configuration -> C Library Implementation: Use glibc (crucial)
Utilities->mender->selected as builtin ()
Utilities->jitter-rngd->selected as builtin (
) (entropy source, to avoid slow boot)
OpenWrt Mender Configuration (make menuconfig):
Utilities->mender->Configuration (alter to taste):
() ServerURL # Mender update server URL
() ServerCertificate # If used
(/dev/mmcblk0p2) RootfsPartA
(/dev/mmcblk0p3) RootfsPartB
(86400) UpdatePollIntervalSeconds
(86400) InventoryPollIntervalSeconds
(30) RetryPollIntervalSeconds
Mender Variables, MENDER_* Configuration, if defaults need to be changed.
Before running (set as defaults)
edit: Custom/package/boot/uboot-sunxi/files/config_mender_defines.h
cp Custom/package/boot/uboot-sunxi/files/config_mender_defines.h
After running (set before build)
edit: package/boot/uboot-sunxi/files/config_mender_defines.h
Build Openwrt (with above configuration)
make, get a jug of coffee
if, during build, configuration questions arise, answer defaults to all
Flash Openwrt-Mender
Change the following variables in to match your tastes / infrastructure:
BASE_NAME # What your distribution is called
DIST_DEST_DIR # Directory or cifs mount point of your package repository
MENDER_SERVER # URL of mender update server
MENDER_SERVER_UID # User ID for mender update server login
MENDER_SERVER_PASS # Password for mender update server login
TOTAL_SECTORS # Default SD sectors 15523840 for 8GB SD. Use fdisk to determine if different SD size
Place SD card in USB adapter, identify SD disk, IE; sde
To create image, flash SD and upload mender rootfs artifact:
./ disk
To only create image and upload mender rootfs artifact:

Full mender image (for distribution and flashing by other means):

Bill Ross

If this post was useful to you, please press like, or leave a thank you note to the contributor who put valuable time into this and made it available to you. It will be much appreciated!

1 Like

Thanks @rossbcan, any specific OpenWrt versions that this has been tested on?

Works on the particular version / $ARCH downloaded by above tarball scripts. For the proprietary Amlogic S912 port, openwrt trunk was no problem. Porting to any u-boot based $ARCH is relatively straightforward, with minor script and patch tweaks should versions change…

Hey @rossbcan could you explain why there is this hard dependency on glibc? I thought Mender worked well with musl?

This is such a cool toolset. Thank you very much for sharing.

My distribution had other dependencies on glibc. Called it a dependency to avoid verifying alternatives. Why not try with musl, share results? That is what opensource / sharing is all about. Netizens perfect / improve what is shared.


Please note that we have experienced some issues with musl in Yocto,

Though this could have been isolated to Yocto, and the type of flags it uses during build and in the end there was a viable workaround.

Hi @rossbcan,

Thanks for sharing all your work and documenting it so well.

I’m having a few issues creating and uploading the Mender Rootfs Artifact and am wondering if you came across anything similar in making the mender_flashdisk script.

Problem: Parsing issues in upload

Failing on: mender-cli artifacts upload --server $MENDER_SERVER -v $BASE_NAME-ext4-rootfs-$DATE.mender

On my build server I can create a mender rootfs artifact with the following command:

mender-artifact write rootfs-image -n $BASE_NAME-$DATE -t $BASE_NAME -f $ROOTFS_IMAGE -o $BASE_NAME-ext4-rootfs-$DATE.mender

(using -f instead of -u to specify the .img file as per

But whilst I can read the artifact generated fine with mender-artifact read and can login to my mender server with the mender-cli when i try the mender-artifact upload I get a failure response of “unexpected EOF” or “Cannot parse artifact file”.

Likewise if i try to manually upload the .mender rootfs file generated I receive a cannot parse failure.

Did you face any similar problems in mender-artifact creation/upload?

Many thanks

mender-cli artifacts upload --server $MENDER_SERVER -v $BASE_NAME-ext4-rootfs-$DATE.mender
do mender-cli --help. Think the API changed (-v?)
you also need to be root for

Thanks for suggestion. Seems its a problem with me using an old version of mender-server. :sweat_smile: