jetson nano cloning and deployment of the image to other devices

Hypothesis 1.
As long as substitute of cards tend to work in a way card A of jetson nano A, be installed to jetson B will work as well as vice versa design - the dd will do for deploying an image of working jetson A to Jetson B. And they both will run simultaneously without conflicts.
If not - then jetflash can be used in a similar way to the situation with Xavier

Copying the SD card should be a simple way to clone the device. You would want to restore it to another SD card of identical size (note that cards can have a slightly different capacity / sectors even if they say they are the same on the packaging - e.g. not all 64GB cards are the same).

If you use dd you may want to compress the image when storing it on disk as it probably will contain lots of zero’s.

Thank you for following up!
Doesn’t it cause collisions if just to take sdcard of one jetson nano [with already running OS] and populate it to a number of other jetsons nano in the same network and run them concurrently?
Thanks

If you want to squash the image before, you an look into squashfs resize2fs and a script on first boot to call it. This way it will work on a SD card only slightly bigger than the used space. You also probably want to re-run anything else in the stock nano first boot script (it self deletes, so you will have to look in the image or on a freshly flashed sdcard that has never been booted).

The reason you want to do that is to make sure some other things are reset as well, like host ssh keys. You don’t want to export those with your image or every flash of your image will have the same host keys. They could lead to supply chain attacks among other things.

Please have a look at raspbian’s first boot script and/or Nano’s before attempting. It’s very easy to get this particular thing wrong while everything seems fine.

1 Like

In my opinion, if the issue with default values [ serials etc ] takes place on multiplication of the same disk image among multiple devices - it will be addressed the same manner as it could be done with flash.sh flashing method for Xavier that resets defaults upon flashing.
I can not test the approach as I have accessible just one jetson nano device, but may be folks who used to clone among multiple devices will share their experience

I had a chance to look at the first boot scripts. There are a bunch of them in /etc/systemd/ (nvfb.sh etc…) nvresizefs is what resizes the squashed filesystem partition to the size of the drive. This is why when you initially flash a jetson image on sdcard and examine the paritition table you will see it’s not using the whole drive. These set of scripts set up all that so you can flash a given image to an sdcard of any size (above a minimum).

An (incomplete) list of things you don’t want to accidentally include with your image:

  • any added users/groups except system users.
  • any configuration specific to your network/enviornmnet (wifi passwords, user passwords)
  • any files from non-system users and groups.
  • any ssh keys for the system or any users (see above point)

And probably a lot of things I can’t think of right now. It’s not impossible to do right. It’s just easy to make mistakes. I am pretty sure nvidia has a guide if you read their documentation, but I can’t recall the link at the moment. If I find it later, I will post the link here.

From reading their scripts, the procedure may be as easy as creating a file in /etc/nv/nvfirstboot after cleaning up the above and squashing the filesystem, but I haven’t read them all.

for example:

#/etc/systemd/nvfb.sh looks like:

if [ ! -e /etc/nv/nvfirstboot ]; then
        exit 0
fi

if [ -f "/usr/share/applications/ubuntu-amazon-default.desktop" ]; then
        echo "Hidden=true" >> /usr/share/applications/ubuntu-amazon-default.desktop
fi

# Generate SSH host keys if they are not present under /etc/ssh/
if [ -e "/lib/systemd/system/ssh.service" ]; then
        dpkg-reconfigure --frontend=noninteractive openssh-server
fi

rm -rf /etc/nv/nvfirstboot

#/etc/systemd/resizefs.sh deletes itself on first boot after doing it’s business sucessfully:

set -e

function cleanup()
{
        # Delete nvresizefs.sh, nvresizefs.service and its symlink
        rm "/etc/systemd/nvresizefs.sh"
        rm "/etc/systemd/system/nvresizefs.service"
        rm "/etc/systemd/system/multi-user.target.wants/nvresizefs.service"
}

if [ -e "/proc/device-tree/model" ]; then
        model="$(tr -d '\0' < /proc/device-tree/model)"
fi

if [ "${model}" != "jetson-nano" ]; then
        cleanup
        exit 0
fi

# Move backup GPT header to end of disk
sgdisk --move-second-header /dev/mmcblk0

# Get root partition name i.e partition No. 1
partition_name="$(sgdisk -i 1 /dev/mmcblk0 | \
        grep "Partition name" | cut -d\' -f2)"

partition_type="$(sgdisk -i 1 /dev/mmcblk0 | \
        grep "Partition GUID code:" | cut -d' ' -f4)"

partition_uuid="$(sgdisk -i 1 /dev/mmcblk0 | \
        grep "Partition unique GUID:" | cut -d' ' -f4)"

# Get start sector of the root partition
start_sector="$(cat /sys/block/mmcblk0/mmcblk0p1/start)"

# Delete and re-create the root partition
# This will resize the root partition.
sgdisk -d 1 -n 1:"${start_sector}":0 -c 1:"${partition_name}" \
        -t 1:"${partition_type}" -u 1:"${partition_uuid}" /dev/mmcblk0

# Inform kernel and OS about change in partitin table and root
# partition size
partprobe /dev/mmcblk0

# Resize filesystem on root partition to consume all un-allocated
# space on disk
resize2fs /dev/mmcblk0p1

# Clean up
cleanup

I hope I didn’t scare him/her off. I only know this stuff from making mistakes myself on Pi. Come back and I’ll help you clone your image if your still reading. We’ll figure out the details. I haven’t done it on Nano yet.

Hi Mdegans,
Thank you for your extended response, However, as I have mentioned, it is rather a theoretical investigation due to the testing environment limitations.
My assumption is that if raw clone of the entire sdcard will have issues like e.g. network conflicts, then the same method that is provided below will probably work:

dd if=/dev/mmcblk0p1 of=testimage.raw
./mksparse -v --fillpattern=0 ~/testimage.raw system.img
sudo ./flash.sh -r jetson-nano mmcblk0p1

However, that will rather take one partition [ mmcblk0p1 ] rather than full sd card image to dd from.
Squash fs should help compressing zero space as I understand. I did not work with it. However it is probably not required at this testing phase, but handy to have the 64 gb image compressed, indeed via shortening of the zero space.

Hi Andrey,

What you suggested will certainly work, the problem is that raw cloning the root partition with dd unmodified will not set the system up in a first boot state again.

The hostnames will all be the same. The ssh host keys don’t get regenerated, and if you reuse the image in that state, or redistribute it, all of those systems are going to be vulnerable by default. Lots of things need to be reset and thankfully, there are already scripts in place to do all much of that.

If you want to make a backup to restore to the same device, it’s perfectly fine to dd and just compress the image with whatever, but if you want to send the image around and reflash freely (to smaller cards), at a minimum the root partition of the image has to be shrunk before and resized on extraction with a script like nvidia’s.

Re squashfs: I misspoke before. I had confused squashfs with resize2fs which resizes partitions.

we used mksparse for the size reduce.
As per linuxdev : “The “backup.img” is a “sparse” version of this. It reduces size by a kind of “poor man’s compression” to leave out empty space. The “raw” image is the exact byte size of the partition, the “sparse” image is smaller by an amount approximately equal to the unused space. Sparse images cannot be loopback mounted, nor can they be edited. Open source tools for working with sparse images cannot work with this version of a sparse image, and so far the only way I know of for using this is to rename it as “system.img””

However, as I understand, the command above that starts with

./flash.sh -r

does the trick with resetting to defaults values and ssh keys in a way they will not reoccur

I’m about to head out the door and don’t have time to comment at length, but are you saying ./flash.sh -r resets the image to a first boot state before it flashes? Documetnation or link to script itself (will be on mobile soon).

I haven’t used flash.sh to flash primarily becuase of problems people seem to have with it. Instead I usually use gnome-disks which is probably using something like dd behind the scenes or Etcher if on Windows. I haven’t used mksparse before. I will take a look a the manpage later. Thank you for that!

yes, that is statistical results from experimenting with it that predict such outcome.
However, flash.sh you may find at host PC and there is a documentation that defines it that is available for download or online

I will do when I arrive back at my host PC (I cannot find the listed option online). Thank you!

I’m upgrading from 32GB to 64GB sdcard and I’d like to use currently state of my sdcard. In other others, “cloning” and still be able to extend partition size from 32 to 64GB on my new card.

Is it even possible?

Yes. Clone the smaller card to the larger card and run resize2fs on the last partition. It’s easiest to do this from an Ubuntu PC with an SD card reader but it should work on the nano itself. Gnome-disks (windows key, “disks”) will let you resize partitions on the sd card visually iirc. Other tools might also.

Hi guys, I did this in practice (as I have two Jetson Nanos).
I renamed both the username and hostname for the second device,
so now I have:

freya@vanaheim
heimdall@bifrost

i also regenerated the host ssh keys.

However, they both still use the same MAC address.
Additionally, they also report the same hardware MAC.
Does anybody know how to fix this?

Mac addresse for physical interfaces are unique to the nic unless you do some tricks with a bridge to report another one. Now if you have two physical Jetson Nanos reporting the same mac address for eth0, that shouldn’t happen.

What it sounds like you are reporting seems normal.

What do you mean by “seems normal”?

i tried

macchanger --show eth0

which tells me the same physical mac address on both devices.

Aha. You are using a mac changer utility. I am unfamiliar with it. I have only done it by manually creating a bridge. I suspect that is what it does. You should be able to use macchanger to set your mac to any address you want, random being probably best.