Provisioning "Jetson Platform Services" to Nvidia Jetson devices

Pre-requisites

Hardware

  • Jetson Orin AGX devkit or
  • Jetson Orin NX 16GB or 8GB devkit (self built) with 128GB(min) NVMe drive or
  • Jetson Orin Nano 8GB devkit with 128GB(min) NVMe drive or
  • Partner (ODM) device with one of above

This tutorial was tested on the Nvidia Jetson Orin AGX devkit

Flash your Jetson

It is required to install at least the BSP included in the JetPack 6.0 GA or newer.

Follow the official Nvidia documentation based on your board.

Install Mender

Install Mender in your Jetson board by following Mender’s docs instructions.

Also, install mender-artifact in your workstation by following this guide.

Using Mender to deploy Jetson Platform Services (and using a demo app)

Creating the Mender Update Module

Create a file named jps-provision-mender-module with the following content:

#!/bin/bash

set -e

STATE="$1"
FILES="$2"

WORKDIR="/opt/workdir"
VERSION="1.1.0"

case "$STATE" in
    ArtifactInstall)
        # Installing DEB packages
        apt-get -qq update
        apt-get -qq -y install nvidia-jetson-services

        # Creating the WORKDIR, you can modify it above
        mkdir -p $WORKDIR

        # Downloading the resources from NGC
        wget -P $WORKDIR --quiet -O reference-workflow-and-resources_$VERSION.zip --content-disposition https://api.ngc.nvidia.com/v2/resources/nvidia/jps/reference-workflow-and-resources/versions/$VERSION/zip 
        unzip $WORKDIR/reference-workflow-and-resources_$VERSION.zip -d $WORKDIR
     
        # Set max power and clock speed 
        jetson_clocks
        nvpmodel -m 0

        # Maximize number of video streams processed by the system (for AI NVR)
        echo "Maximize number of video streams processed by the system (for AI NVR)" 1>&2
        sysctl -w net.core.rmem_default=2129920
        sysctl -w net.core.rmem_max=10000000

        # Setup VST Application
        echo "Setup VST" 1>&2
        tar -xvf $WORKDIR/ai_nvr-$VERSION.tar.gz -C $WORKDIR
        cp $WORKDIR/ai_nvr/config/ai-nvr-nginx.conf /opt/nvidia/jetson/services/ingress/config/
        cd $WORKDIR/ai_nvr
        # Uncomment just one line based on your board: 
        # Orin AGX (default in this example)
        docker compose -f compose_agx.yaml pull
        # Orin NX16
        #docker compose -f compose_nx16.yaml pull
        # Orin NX8
        #docker compose -f compose_nx8.yaml pull
        # Orin Nano
        #docker compose -f compose_nano.yaml pull

        # Increase the OS socket buffer sizes (for NVStreamer)
        echo "Increase the OS socket buffer sizes (for the Streamer)" 1>&2
        sysctl -w net.core.wmem_max=2000000
        sysctl -w net.core.rmem_max=2000000
        # Setup NVStreamer
        echo "Setup NVStreamer" 1>&2
        tar -xvf $WORKDIR/nvstreamer-$VERSION.tar.gz -C $WORKDIR
        # Start NVStreamer after reboot
        cd $WORKDIR/nvstreamer
        echo "Launch NVStreamer" 1>&2
        docker compose -f compose_nvstreamer.yaml pull
        ;;
    NeedsArtifactReboot)
        echo "Automatic"
        ;;
    ArtifactVerifyReboot)
        # Setup and start Services
        echo "Launch jetson's redis and ingress" 1>&2
        systemctl start jetson-redis
        systemctl start jetson-ingress
        systemctl start jetson-vst
        # Start NVStreamer after reboot
        cd $WORKDIR/nvstreamer
        echo "Launch NVStreamer" 1>&2
        docker compose -f compose_nvstreamer.yaml up -d
        # Start NVStreamer after reboot
        cd $WORKDIR/ai_nvr
        echo "Launch VST" 1>&2
        # Uncomment just one line based on your board: 
        # Orin AGX (default in this example)
        docker compose -f compose_agx.yaml up -d
        # Orin NX16
        #docker compose -f compose_nx16.yaml up -d
        # Orin NX8
        #docker compose -f compose_nx8.yaml up -d
        # Orin Nano
        #docker compose -f compose_nano.yaml up -d
        ;;
    ArtifactCommit)
        # Getting the IP Address
        echo "Getting the IP address for outputs" 1>&2
        ip_address=$(hostname -I | awk '{print $1}')
        echo "IP Address: ${ip_address}" 1>&2
        echo "Please open a browser in $ip_address:30080/vst for the VST application" 1>&2
        echo "Please open a browser in $ip_address:31000 for the Streamer" 1>&2
        echo "Ready, continue with Nvidia's tutorial to connect both apps" 1>&2
        ;;
    SupportsRollback)
        echo "Yes"
        ;;
    ArtifactRollback)
        echo "Removing nvidia-jetson-services package if installed" 1>&2
        if [ $(dpkg-query -W -f='${Status}' nvidia-jetson-services 2>/dev/null | grep -c "ok installed") -eq 1 ];
        then
            apt purge nvidia-jetson-services;
        fi
        if [ -d $WORKDIR/nvstreamer ]; then
            cd $WORKDIR/nvstreamer
            docker compose -f compose_nvstreamer.yaml down --remove-orphans
        fi
        if [ -d $WORKDIR/ai_nvr ]; then
            cd $WORKDIR/ai_nvr
            # Uncomment just one line based on your board: 
            # Orin AGX (default in this example)
            docker compose -f compose_agx.yaml down --remove-orphans
            # Orin NX16
            #docker compose -f compose_nx16.yaml down --remove-orphans
            # Orin NX8
            #docker compose -f compose_nx8.yaml down --remove-orphans
            # Orin Nano
            #docker compose -f compose_nano.yaml down --remove-orphans
        fi
        ;;
    Cleanup)
        rm -rf $WORKDIR
        ;;
esac
exit 0

Install the Update Module

Copy the Update Module from above to your Jetson by following this guide.

Create a Mender Artifact

Replace the device-type per the one set in the mender setup process on the Jetson during the “Install Mender” part above. Ideally follow Nvidia’s standards, for example, jetson-agx-orin-devkit for the Jetson AGX Orin DevKit.

Feel free to change the artifact-name as this is how this artifact will be named in the Mender ecosystem.

The type must match the name of the Update Module. In our example, we named it as jps-provision-mender-module.

Notice it will download the required files from NGC.

mender-artifact write module-image \
    --artifact-name "jps-installation" \
    --output-path "jps-installation.mender" \
    --device-type "jetson-agx-orin-devkit" \
    --type "jps-provision-mender-module"

This will generate a Mender’s artifact named jps-installation.mender that we can upload into our Mender Server and deploy into multiple Jetson devices from our fleet.

Verify your installation

After this artifact is deployed into a Jetson board, you should be able to open in your workstation’s browser the two webapps we installed: NV Streamer (in port 31000) and VST (in port 30080) and you should be able to follow this Nvidia’s tutorial for uploading a video into the NV Streamer and this one to import that video stream into VST.