JetPack 4.6 Boot From Encrypted External NVMe Using Initrd Flashing Tool

Hello, we’re attempting to flash JetPack 4.6 using the new initrd flashing tool with the goal of booting from an encrypted NVMe drive.

We’ve utilized some of the scripts found in the JetsonHacks “bootFromExternalStorage” GitHub Repo to prepare the host system and download the necessary BSP, rootfs, and Secureboot packages.

  • install_dependencies.shto install flash script dependencies

  • to download BSP and rootfs

Then, referencing Workflow 10 in README_initrd_flash.txt in which the internal and external images are generated separately, and then flashed together…

Workflow 10
Workflow 10: Generate images for internal device and external device seperately
then flash

The flashing tool supports a three-step process: "to generate images for an
internal device, then generate them for an external device, then flash.
This is enabled by using the "append" option. Four examples below show how it

Example 1: Generate a normal root filesystem configuration for the internal device
, then generate an encrypted root filesystem for the external device, then flash

First step: Put the device into recovery mode, then generate a normal root
filesystem for the internal device:
$ sudo ./tools/kernel_flash/ --no-flash jetson-xavier internal

Second step: Put the device into recovery mode, then generate an encrypted
filesystem for the external device:
$ sudo ROOTFS_ENC=1 ./tools/kernel_flash/ --no-flash \
            --external-device nvme0n1p1 \
            -S 8GiB -c ./tools/kernel_flash/flash_l4t_nvme_rootfs_enc.xml \
            --external-only --append jetson-xavier external

Third step: Put the device into recovery mode, then flash both images:
$ sudo ./tools/kernel_flash/ --flash-only

…we came up with a shell script to assist with the process:
UDISKS2_ACTIVE=$(sudo systemctl is-active udisks2.service)

trap cleanup 1 2 3 6


  if [[ ${UDISKS2_ACTIVE} == 'active' ]] ; then
    echo "enabling usb mass storage devices"
    sudo systemctl start udisks2.service

function flash_jetson
  echo "disabling usb mass storage devices"
  sudo systemctl stop udisks2.service
  read -p "Press enter to generate internal image..."
  sudo ./tools/kernel_flash/ --no-flash jetson-agx-xavier-devkit internal
  read -p "Press enter to generate external encrypted image..."
  sudo ROOTFS_ENC=1 ./tools/kernel_flash/ --no-flash \
            --external-device nvme0n1p1 \
            -S 8GiB -c ./tools/kernel_flash/flash_l4t_nvme_rootfs_enc.xml \
            --external-only --append jetson-agx-xavier-devkit external
  read -p "Press enter to flash both images..."
  sudo ./tools/kernel_flash/ --flash-only



During the “external” image generation, we noticed an error message that seems relevant to our final issue:

install: cannot stat '/home/<user>/bootFromExternalStorage/R32.6.1/Linux_for_Tegra/rootfs/usr/sbin/nvluks-srv-app': No such file or directory

Between steps, we reboot the device back into recovery mode, as specified in “Workflow 10”.

Finally, after the script is run, we see the attached display come on and are greeted with the following error message, and an endless boot loop:

My question is, do we need to do something else in order for the NVMe to be able to decrypt upon boot? Or are we missing anything in general? Maybe we’re going about this wrong and it’s more complex than expected. Any insight is greatly appreciated! Thanks!

1 Like

hello jalufka,

there should be an “luks-srv-app” binary, the CA tool of passphrase generation for un-locking the encrypted device.
could you please confirm you’ve moving to the latest JetPack release version. please execute with SDKManager for confirmation.

it’s new feature of Disk encryption of external media supported to protect data at rest for Jetson AGX Xavier series, Jetson Xavier NX and Jetson TX2.
here’s developer guide for your reference, Disk Encryption Implementation in Jetson Linux.


I went ahead and attempted the process again, with fresh downloads of R32.6.1, the L4T Driver Package - BSP, and the Sample Root File System.

Confirmed that nvluks-srv-app is present in /R32.6.1/Linux_for_Tegra/rootfs/usr/sbin.

This time the process was successful. I did take an additional step of creating a default user with the script, so I wonder if that had anything to do with the successful outcome.

I have one more question regarding the encryption key that is used.
Using the example workflow specified in the original post, I never created any keys, so during the image generation/flashing, a zero filled SBK key was used, according to the logs.

If I wanted to generate a non-zero key, how could I go about doing so, and how would I utilize that key using initrd?

Thanks so much for the response!

hello jalufka,

it’s by default using all zero keys. you may fuse the target to add the keys.
note, program the fuse is non-reversible.
here’s an FYI,
PKC for sign: if PKC is burned, then the KEYFILE users provide is for signing the images.
SBK for encryption: if SBK is burned, then the SBKFILE users provide is for encrypting the images.
KEKs for encryption keys:they are keys to encrypt your keys. KEK0, KEK1, KEK2 are 128-bit key files; KEK256 is 256-bit key file. please use the commands, --KEK* to determine which key encryption key you’re going to fused.

you may access Jetson Linux | NVIDIA Developer and check [Tools] session for Jetson Platform Fuse Burning and Secure Boot Documentation and Tools.

please access tutorials page for the Jetson Security and Secure Boot, this training video gives an overview of security features for the Jetson product family and explains in detailed steps the secure boot process, fusing, and deployment aspects.
you may also see developer guide, Jetson security for more details.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.