Zelta/Documentation

Buildroot Integration

Integrate Zelta OTA updates into your Buildroot-based Linux system.

Overview

Buildroot provides a simple way to generate embedded Linux systems. This guide covers integrating the Zelta SDK as a Buildroot package.

Package Structure

Create the Zelta package directory:

mkdir -p package/zelta

Package Files

Config.in

package/zelta/Config.in:

config BR2_PACKAGE_ZELTA
    bool "zelta"
    select BR2_PACKAGE_LIBCURL
    select BR2_PACKAGE_OPENSSL
    help
      Zelta OTA Update SDK and client for embedded Linux.
      
      https://github.com/didavie/Zelta

if BR2_PACKAGE_ZELTA

config BR2_PACKAGE_ZELTA_CLIENT
    bool "zelta-client"
    default y
    help
      Install the Zelta update client daemon.

config BR2_PACKAGE_ZELTA_USE_MBEDTLS
    bool "Use mbedTLS instead of OpenSSL"
    select BR2_PACKAGE_MBEDTLS
    help
      Use mbedTLS for cryptographic operations.
      Recommended for resource-constrained devices.

endif

zelta.mk

package/zelta/zelta.mk:

################################################################################
#
# zeltasoft - OTA Update SDK
#
################################################################################

ZELTA_VERSION = 1.0.0
ZELTA_SITE = $(call github,didavie,Zelta,v$(ZELTA_VERSION))
ZELTA_LICENSE = MIT
ZELTA_LICENSE_FILES = LICENSE
ZELTA_INSTALL_STAGING = YES

ZELTA_DEPENDENCIES = libcurl

ifeq ($(BR2_PACKAGE_ZELTA_USE_MBEDTLS),y)
ZELTA_DEPENDENCIES += mbedtls
ZELTA_CONF_OPTS += -DZELTA_USE_MBEDTLS=ON
else
ZELTA_DEPENDENCIES += openssl
ZELTA_CONF_OPTS += -DZELTA_USE_OPENSSL=ON
endif

ZELTA_SUBDIR = embedded

$(eval $(cmake-package))

# Install configuration file
define ZELTA_INSTALL_CONFIG
    $(INSTALL) -D -m 0600 $(ZELTA_PKGDIR)/zelta.conf \
        $(TARGET_DIR)/etc/zelta/zelta.conf
endef

ZELTA_POST_INSTALL_TARGET_HOOKS += ZELTA_INSTALL_CONFIG

# Install systemd service if enabled
ifeq ($(BR2_INIT_SYSTEMD),y)
define ZELTA_INSTALL_SYSTEMD
    $(INSTALL) -D -m 0644 $(ZELTA_PKGDIR)/zelta-client.service \
        $(TARGET_DIR)/usr/lib/systemd/system/zelta-client.service
endef
ZELTA_POST_INSTALL_TARGET_HOOKS += ZELTA_INSTALL_SYSTEMD
endif

# Install init.d script for sysvinit
ifeq ($(BR2_INIT_SYSV),y)
define ZELTA_INSTALL_INIT_SYSV
    $(INSTALL) -D -m 0755 $(ZELTA_PKGDIR)/S99zelta \
        $(TARGET_DIR)/etc/init.d/S99zelta
endef
ZELTA_POST_INSTALL_TARGET_HOOKS += ZELTA_INSTALL_INIT_SYSV
endif

Default Configuration

package/zelta/zelta.conf:

# Zelta OTA Configuration
[server]
url = https://api.zeltasoft.com
api_key = CONFIGURE_ME

[device]
product_id = CONFIGURE_ME
# Hardware ID will be auto-detected from /etc/machine-id

[update]
check_interval = 3600
auto_apply = false
reboot_after_update = true

[paths]
download_dir = /var/lib/zelta/downloads
state_file = /var/lib/zelta/state.json
firmware_path = /var/lib/zelta/firmware.bin

[logging]
level = info
syslog = true

Systemd Service

package/zelta/zelta-client.service:

[Unit]
Description=ZeltaSoft OTA Update Client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/zelta-client --daemon
Restart=on-failure
RestartSec=30

[Install]
WantedBy=multi-user.target

SysVinit Script

package/zelta/S99zelta:

#!/bin/sh

DAEMON=/usr/bin/zelta-client
PIDFILE=/var/run/zelta.pid

case "$1" in
    start)
        printf "Starting Zelta: "
        start-stop-daemon -S -q -b -m -p $PIDFILE --exec $DAEMON -- --daemon
        [ $? = 0 ] && echo "OK" || echo "FAIL"
        ;;
    stop)
        printf "Stopping Zelta: "
        start-stop-daemon -K -q -p $PIDFILE
        [ $? = 0 ] && echo "OK" || echo "FAIL"
        rm -f $PIDFILE
        ;;
    restart|reload)
        $0 stop
        $0 start
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac

Enable the Package

Add to package/Config.in:

menu "OTA Updates"
    source "package/zelta/Config.in"
endmenu

Configure Buildroot

make menuconfig

Navigate to:

  • Target packages → OTA Updates → zelta

Or add to your defconfig:

BR2_PACKAGE_ZELTA=y
BR2_PACKAGE_ZELTA_CLIENT=y

Custom Configuration

External Tree

For project-specific configuration, use an external tree:

mkdir -p my_external/package/zelta

my_external/package/zelta/zelta.mk (append):

# Override configuration with project-specific values
define ZELTA_INSTALL_PROJECT_CONFIG
    $(INSTALL) -D -m 0600 $(BR2_EXTERNAL_MY_PROJECT_PATH)/configs/zelta.conf \
        $(TARGET_DIR)/etc/zelta/zelta.conf
endef
ZELTA_POST_INSTALL_TARGET_HOOKS += ZELTA_INSTALL_PROJECT_CONFIG

Post-Build Script

board/myboard/post-build.sh:

#!/bin/bash
# Customize Zelta configuration per-device

TARGET_DIR=$1
ZELTA_CONF="$TARGET_DIR/etc/zelta/zelta.conf"

# Set product ID from environment or default
PRODUCT_ID=${ZELTA_PRODUCT_ID:-"default-product"}
sed -i "s/product_id = CONFIGURE_ME/product_id = $PRODUCT_ID/" "$ZELTA_CONF"

# Generate unique device ID
if [ ! -f "$TARGET_DIR/etc/machine-id" ]; then
    cat /proc/sys/kernel/random/uuid | tr -d '-' > "$TARGET_DIR/etc/machine-id"
fi

Filesystem Overlay

Use a rootfs overlay for static configuration:

board/myboard/rootfs_overlay/
├── etc/
│   └── zelta/
│       └── zelta.conf
└── var/
    └── lib/
        └── zelta/
            └── .keep

Build

make zelta-rebuild  # Rebuild just Zelta
make               # Full build

Testing

Boot your image and verify:

# Check installation
ls -la /usr/bin/zelta-client
ls -la /etc/zelta/zelta.conf

# Start manually
zelta-client --check-now

# Check logs
cat /var/log/messages | grep zelta

Size Optimization

For minimal footprint:

# In zelta.mk
ZELTA_CONF_OPTS += \
    -DZELTA_MINIMAL=ON \
    -DZELTA_NO_JSON_PRETTY=ON \
    -DZELTA_STATIC_ALLOC=ON

Typical sizes:

  • libzelta.a: ~45 KB
  • zelta-client: ~120 KB (with curl linked)

Integration with RAUC

If using RAUC for A/B updates:

package/zelta/zelta-rauc.mk:

# RAUC integration
ifeq ($(BR2_PACKAGE_RAUC),y)
ZELTA_DEPENDENCIES += rauc
ZELTA_CONF_OPTS += -DZELTA_RAUC_INTEGRATION=ON

define ZELTA_INSTALL_RAUC_HANDLER
    $(INSTALL) -D -m 0755 $(ZELTA_PKGDIR)/zelta-rauc-handler.sh \
        $(TARGET_DIR)/usr/lib/rauc/zelta-handler.sh
endef
ZELTA_POST_INSTALL_TARGET_HOOKS += ZELTA_INSTALL_RAUC_HANDLER
endif

Integration with SWUpdate

For SWUpdate-based systems:

ifeq ($(BR2_PACKAGE_SWUPDATE),y)
ZELTA_DEPENDENCIES += swupdate
ZELTA_CONF_OPTS += -DZELTA_SWUPDATE_INTEGRATION=ON
endif

Troubleshooting

Package Not Found

# Regenerate package list
make menuconfig
# Search for zelta

Build Errors

# Check build log
make zelta-rebuild V=1

# Enter build directory
make zelta-dirclean
make zelta-extract
cd output/build/zelta-*/

Runtime Errors

# Check library dependencies
ldd /usr/bin/zelta-client

# Test curl connectivity
curl -v https://api.zeltasoft.com/health

Next Steps