Quick Start Guide with Yocto

Flash a prebuilt OE4T demo-image-full Yocto image (JetPack 7.2) to Jetson AGX Thor, AGX Orin, or Orin Nano. No BitBake build required.

Quick Start Guide with Yocto

The standard way to set up a Jetson is the JetPack flow: you flash Jetson Linux (Ubuntu) from an ISO USB stick, following the Quick Start Guide for your developer kit. JetPack delivers NVIDIA’s complete, validated software stack and is an excellent choice for both development and production.

The Yocto Project is an alternative option for teams who prefer to build their own Linux image with the OpenEmbedded build system, choosing exactly which packages are included, integrating the OS build into CI, and reproducing the same image from source on every build. It uses the same Jetson Linux (L4T) and JetPack components under the hood. This guide shows how to get started with the Yocto path on Jetson.

Beginning with JetPack 7.2 (Jetson Linux R39.2), Yocto is an officially supported path on Jetson, developed together with the community OpenEmbedded for Tegra (OE4T) project. The Jetson Yocto recipes live in two OE4T repositories:

You don’t have to build anything to try it. In this guide you’ll download a prebuilt demo-image-full image and flash it to your Jetson. demo-image-full is a desktop (Sato/X11) image that already includes nvidia-docker and the Multimedia API samples, a good way to see what a Yocto-based Jetson image looks like. It comes from the OE4T tegra-demo-distro wrynose branch.

📘 Where to get the images

Prebuilt Yocto images are published on the JetPack SDK downloads page. Under Yocto Images, use the button for your device: Yocto for Jetson AGX Thor, Yocto for Jetson AGX Orin, or Yocto for Jetson Orin Nano. If you’d rather build the image yourself, jump to Build your own Yocto image.

Supported images

Download the demo-image-full tegraflash tarball for your target. Use the tarball whose MACHINE name matches your hardware. Do not use a tarball built for a different Jetson module or carrier.

HardwareOE4T MACHINETarball nameRootfs target
Jetson AGX Thor devkitjetson-agx-thor-devkitdemo-image-full-jetson-agx-thor-devkit.rootfs.tegraflash-tar.zstNVMe (nvme0n1p1)
Jetson AGX Orin devkit (64 GB)p3737-0000-p3701-0005demo-image-full-p3737-0000-p3701-0005.rootfs.tegraflash-tar.zstinternal eMMC (mmcblk0p1)
Jetson Orin Nano (NVMe)jetson-orin-nano-devkit-nvmedemo-image-full-jetson-orin-nano-devkit-nvme.rootfs.tegraflash-tar.zstNVMe (nvme0n1p1)

⚠️ Install the NVMe drive first (NVMe targets)

For the two NVMe targets (AGX Thor and Orin Nano), install the NVMe drive in the Jetson before putting the device into recovery mode. The flash script writes the root filesystem to the storage target described by the MACHINE configuration.

Why Yocto?

The Yocto Project is not a Linux distribution by itself. It is a build framework that produces a distribution tailored to your hardware, package set, and update model. Teams reach for Yocto on Jetson when they need tight control over the OS image that ships in a product: a minimized package set, reproducible builds in CI, Secure Boot, OTA updates, package feeds, and long-term maintenance. For this getting-started guide, you simply consume a prebuilt image, so no build framework knowledge is required.

💡 Just want to run AI workloads?

If you’re not specifically interested in Yocto and just want to get models running quickly, the standard JetPack flow in Getting Started with Jetson is the easier path.

The end-to-end flow for this guide is short:

What’s in demo-image-full?

The tegrademo distro from OE4T ships several reference image recipes. demo-image-full is the most complete one:

ImageContents
demo-image-baseBasic image, no graphics
demo-image-eglDRM/EGL graphics, no window manager
demo-image-satoX11 image with the Sato UI
demo-image-westonWayland with the Weston compositor
demo-image-fullSato UI plus nvidia-docker and Multimedia API samples

Prerequisites

Host machine

Use a native x86-64 Ubuntu 24.04 host. Avoid flashing from a virtual machine, container, WSL environment, or through an external USB hub. The low-level USB recovery protocol is sensitive to host USB behavior.

Install the host packages needed by the OE4T flash scripts:

sudo apt update
sudo apt install \
  bash \
  bmap-tools \
  cpp \
  device-tree-compiler \
  gdisk \
  libxml2-utils \
  python3 \
  tar \
  udisks2 \
  usbutils \
  zstd

If you want to monitor a serial console, also install a serial terminal and add your user to the dialout group (log out and back in afterward):

sudo apt install picocom
sudo usermod -aG dialout "$USER"

Prepare the desktop host

On an Ubuntu 24.04 desktop host, disable automatic mounting of removable media before flashing. The Orin flashing flow exposes storage over USB, and desktop automount can interfere with it:

gsettings set org.gnome.desktop.media-handling automount false
gsettings set org.gnome.desktop.media-handling automount-open false

Verify that both commands print false:

gsettings get org.gnome.desktop.media-handling automount
gsettings get org.gnome.desktop.media-handling automount-open

📘 Notes

If gsettings is unavailable (a non-desktop host), this automount step does not apply. If the host has the tlp power-management package installed, remove it and reboot the host before flashing: sudo apt remove tlp && sudo reboot.

Step 1: Download the image for your device

From the JetPack downloads page (JetPack 7.2 / Jetson Linux R39.2), under Yocto Images, click the button for your device: Yocto for Jetson AGX Thor, Yocto for Jetson AGX Orin, or Yocto for Jetson Orin Nano. Download the .tegraflash-tar.zst package whose MACHINE matches your hardware (see the Supported images table). Save it to ~/Downloads and leave the filename unchanged.

Step 2: Unpack the flash tarball

Set MACHINE to your target, then unpack the tarball into a fresh directory. Use the value from the table that matches your hardware:

export MACHINE="jetson-agx-thor-devkit"
export MACHINE="p3737-0000-p3701-0005"
export MACHINE="jetson-orin-nano-devkit-nvme"

Then unpack:

mkdir -p ~/jetson-flash
cd ~/jetson-flash
tar xf ~/Downloads/demo-image-full-${MACHINE}.rootfs.tegraflash-tar.zst

💡 Tip

Use a fresh empty directory if you unpack more than one target so the contents don’t mix.

Step 3: Put the Jetson in Recovery Mode

Connect the host to the Jetson’s recovery USB port before running the flash script. The exact port differs per developer kit. The Diagram links open the official Hardware Layout page with annotated photos of the USB port, RECOVERY/RESET buttons, and recovery header.

Developer kitRecovery USB portDiagram
Jetson AGX Thor devkitUSB-C port with Force-Recovery functionality (5a, next to the HDMI connector); use the other USB-C port (5b) for powerHardware Layout
Jetson AGX Orin devkit (64 GB)USB Type-C port next to the 40-pin headerHardware Layout
Jetson Orin Nano devkitUSB-C port (mark 4)Hardware Layout

Enter Force Recovery Mode using the sequence for your developer kit:

For kits with RECOVERY and RESET buttons (Thor AGX devkit, Orin AGX devkit):

  1. Power the Jetson carrier board.
  2. Hold the RECOVERY (Force Recovery) button.
  3. Press and release RESET.
  4. Release the RECOVERY button.

For the Jetson Orin Nano developer kit, use the recovery pins on the J14 button header (located below the Jetson module):

  1. Power off the developer kit and disconnect power.
  2. Place a jumper across pin 9 (GND) and pin 10 (FORCE_RECOVERY) of the J14 header.
  3. Reconnect power (or press the power button).
  4. Wait a couple of seconds, then remove the jumper.

See Orin Nano Developer Kit: Force Recovery Mode for the official steps.

Confirm the host can see an NVIDIA recovery-mode USB device:

lsusb -d 0955:

The output should include an APX device, which indicates the Jetson is in recovery mode.

⚠️ APX vs Tegra On-Platform Operator

A Tegra On-Platform Operator device is the USB serial support interface, not the recovery-mode device used for flashing. If APX is missing, check the cable, the recovery USB port, and the recovery-mode button/pin sequence.

Step 4: Flash the image

From the directory where you unpacked the tarball, run:

sudo ./initrd-flash

The script detects the Jetson in recovery mode, prepares the flash content, and writes the image. By default it flashes both the boot firmware and the configured root filesystem target for the selected MACHINE.

📘 If you see could not retrieve board information

If the flash fails early with an error like:

Found Jetson device in recovery mode at USB 3-1
ERR: could not retrieve board information

Power-cycle the developer kit (unplug power, plug it back in), re-enter Force Recovery Mode from power-off, confirm APX appears in lsusb -d 0955:, and run sudo ./initrd-flash again.

⏳ Don’t disconnect during flashing

Flashing can take several minutes, particularly the final step that writes the QSPI flash. Keep the USB cable connected and the board powered until it completes. The script writes a host log named log.initrd-flash.YYYY-MM-DD-HH.MM.SS; for Orin targets, device-side logs may also be collected into a device-logs-YYYY-MM-DD-HH.MM.SS directory.

When flashing completes, bring the device up:

TargetNext step
Thor AGX devkitPower cycle or reset the Jetson.
Orin AGX devkit (64 GB)The script waits for final device status. Reboot or power cycle if it does not boot automatically.
Orin Nano (NVMe)The script waits for final device status. Reboot or power cycle if it does not boot automatically.

On boot you’ll reach a login prompt. Log in as root (the demo image has no password set by default).

⚠️ Change the default login

The tegrademo image is a reference / demo image with passwordless root for convenience. Before using it or any derivative beyond evaluation, set passwords, remove debug tweaks, and review the security configuration.

Step 5: Verify the JetPack stack

Once booted, confirm the JetPack components bundled in demo-image-full are present. Run these on the device (over serial or SSH):

Check the L4T / JetPack release:

cat /etc/nv_tegra_release

Verify Docker with the NVIDIA runtime:

docker info | grep -i runtime
docker run --rm --runtime nvidia hello-world

If these respond, your Yocto image is up and the JetPack stack is functional. You now have a Sato desktop running on your Jetson with containers and the multimedia samples ready to use.

Step 6: Set up persistent storage for Docker containers

Expand: set up persistent storage for Docker containers

The reference image uses an A/B root filesystem layout so the inactive slot remains available for system updates. As a result, the mounted root filesystem is intentionally smaller than the physical drive: approximately 25 GB on AGX Thor and 14 GB on AGX Orin or Orin Nano. Large container images and model caches can fill it quickly.

Before downloading AI containers, create a separate data partition from the unallocated space left after the A/B slots, mount it at /data, and place both Docker and containerd storage there. These instructions apply to a freshly flashed image with no container data to migrate.

📘 AGX Orin: use an external SSD for vLLM

The unused portion of the 64 GB AGX Orin eMMC provides approximately 28 GB after formatting. This is useful for smaller containers and model caches, but the current NVIDIA AI-IOT vLLM image expands beyond that capacity. For vLLM on AGX Orin, install an NVMe SSD or connect a USB SSD and use that device for /data instead of creating the eMMC data partition below.

⚠️ Confirm the free space before changing the partition table

The following procedure creates a partition only in currently unallocated space. Do not delete, resize, or format any existing A/B, EFI, recovery, or reserved partition. A later full-device flash may recreate the original partition table, so keep important data backed up.

First inspect the device and confirm that the expected unallocated region is present:

lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS
fdisk -l /dev/nvme0n1
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS
fdisk -l /dev/mmcblk0
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS
fdisk -l /dev/nvme0n1

Open the corresponding disk with fdisk:

fdisk /dev/nvme0n1
fdisk /dev/mmcblk0
fdisk /dev/nvme0n1

At the fdisk prompt, enter n to create a new partition, accept the default partition number, first sector, and last sector, then enter p to review the result. The new partition must occupy only the large free region after the second rootfs slot. Enter w only after confirming that none of the existing partitions changed.

Because the system disk is active, reboot so the kernel loads the updated partition table:

reboot

📘 The IP address may change after reboot

If the Jetson receives its address through DHCP, it may come back with a different IP address. If SSH no longer connects to the previous address, check the DHCP lease table on your router or network, or use the serial console and run ip -br address to find the new address.

After reconnecting, select the new partition. With the JetPack 7.2 reference layout, it is normally partition 13 on AGX Thor and partition 17 on AGX Orin or Orin Nano. AGX Orin uses eMMC, while Orin Nano uses NVMe. Confirm the actual partition with lsblk before continuing.

export DATA_PARTITION=/dev/nvme0n1p13
export DATA_PARTITION=/dev/mmcblk0p17
export DATA_PARTITION=/dev/nvme0n1p17

Format and mount only the newly created partition:

lsblk -f "$DATA_PARTITION"
mkfs.ext4 -L JETSON_DATA "$DATA_PARTITION"

mkdir -p /data
DATA_UUID=$(blkid -s UUID -o value "$DATA_PARTITION")
echo "UUID=$DATA_UUID /data ext4 defaults,nofail 0 2" >> /etc/fstab
mount -a

findmnt /data
df -hT /data

Docker 29 can keep image layers in containerd independently of Docker’s data-root, so redirect both locations. Preserve the NVIDIA runtime configuration in /etc/docker/daemon.json:

systemctl stop docker.socket docker containerd

mkdir -p /data/docker /data/containerd /etc/containerd
cp /etc/docker/daemon.json /etc/docker/daemon.json.before-data

cat > /etc/docker/daemon.json <<'EOF'
{
  "data-root": "/data/docker",
  "runtimes": {
    "nvidia": {
      "args": [],
      "path": "nvidia-container-runtime"
    }
  }
}
EOF

cat > /etc/containerd/config.toml <<'EOF'
version = 2
root = "/data/containerd"
state = "/run/containerd"
EOF

systemctl start containerd docker

Verify the persistent mount, Docker storage root, and NVIDIA runtime:

findmnt /data
docker info --format 'Docker root: {{.DockerRootDir}}'
docker info | grep -i runtime

The Docker root should report /data/docker, and nvidia should remain listed as an available runtime. If the system already contains images or containers that you need to retain, migrate them before changing these paths; see SSD + Docker Setup for the migration workflow.

Optional: Serial console

A serial console is not required, but it helps if flashing fails or the device does not boot. Connect at 115200 baud. The host device is commonly /dev/ttyACM0 for CDC-ACM, or /dev/ttyUSB0 for USB-to-TTL adapters:

picocom -b 115200 /dev/ttyACM0

Use Ctrl-A then Ctrl-X to exit picocom. Serial access differs per device:

HardwareSerial access
Thor AGX devkitUSB CDC-ACM serial from the USB-C port hidden under the lid above the rear ports
Orin AGX devkit (64 GB)USB CDC-ACM serial from the USB micro-B port
Orin Nano (NVMe)3.3 V TTL UART on the button header; use a USB-to-TTL serial adapter

Troubleshooting

  • lsusb -d 0955: shows no device: the Jetson is not in Force Recovery Mode, or the host is connected to the wrong USB port. Re-enter recovery mode from power-off and confirm the recovery USB port.
  • Flashing fails with a USB communication error: power cycle the Jetson, enter Force Recovery Mode from power-off, and rerun sudo ./initrd-flash. Also try a different high-quality USB cable and a direct host USB port (no hub).
  • The host desktop opens a file browser or mounts storage during flashing: recheck the GNOME automount settings above and close any file-manager windows that opened automatically.
  • Keep the logs: if the script fails, keep the generated log.initrd-flash.* file (and the device-logs-* directory for Orin targets) when reporting the issue.

Build your own Yocto image

The prebuilt demo-image-full is built from source on the OE4T tegra-demo-distro repository. To rebuild it yourself or customize it with your own layer and packages, follow the setup and build steps in the repository README: github.com/OE4T/tegra-demo-distro.

References & Next Steps

Run your first AI workload

With your Jetson booted and persistent container storage in place, you’re ready to run a containerized AI workload. When you pick an image, match it to your Jetson’s GPU family rather than just its CPU architecture or SBSA support: Thor and Orin are built on different GPU architectures, so their optimized containers are not interchangeable. Use the table below to choose the right image for your device.

WorkflowJetson AGX ThorJetson AGX Orin / Orin NX / Orin Nano
Live VLM WebUIghcr.io/nvidia-ai-iot/live-vlm-webui:latest-jetson-thorghcr.io/nvidia-ai-iot/live-vlm-webui:latest-jetson-orin
vLLMghcr.io/nvidia-ai-iot/vllm:latest-jetson-thorghcr.io/nvidia-ai-iot/vllm:latest-jetson-orin
Ollamaghcr.io/nvidia-ai-iot/ollama:r38.2.arm64-sbsa-cu130-24.04dustynv/ollama:r36.2.0

On your Yocto-based Jetson, always pick the container tag that matches your GPU family: latest-jetson-thor for Thor (SM110) and latest-jetson-orin for Orin (SM87). These are rolling tags, so the exact Jetson Linux and CUDA versions behind them change over time. On an Orin running the R39.2 / JetPack 7.2 Yocto image, keep using the Orin tag.

📘 Live VLM WebUI needs a model backend

Live VLM WebUI provides the browser interface and camera pipeline; it does not serve a model by itself. Connect it to Ollama, vLLM, SGLang, or another OpenAI-compatible local or cloud API. For a small local-storage setup, start with Ollama and a compact model.