How can I quickly copy a system from one TX2 NX to another TX2 NX?

Quick question for NVIDIA (maybe @WayneWWW or @DaveYYY): Is there a temp file or some simple configuration which can revert the clone’s idea that first boot account setup is complete? I ask because if he is removing an account, and not adding a new one, this matters.

There isn’t much you can do except manually removing those. rsync is probably the tool you are interested in, but it isn’t always simple. Do realize though that if you have a raw clone, then rsync works with the raw clone as well when it is loopback mounted. I will try to describe some ways to use the tool and some related concepts, but it would still take experimentation and a bit of work to get it figured out. The nice part is that once you know the rsync command you can script it.

To start with, files related to the user which might matter to you are:

  • /etc/passwd
  • /etc/passwd-
  • /etc/group
  • /etc/group-
  • /etc/gshadow
  • /etc/gshadow-
  • /etc/shadow
  • /etc/shadow-

If you have ssh keys, then you might have further complication from “/etc/ssh/” content. For example, the particular computer has an ssh ID which is being copied. Furthermore, in rare cases, udev might make an adjustment based on an exact network MAC address; this is unlikely, but you might end up with a rule in “/etc/apt/rules.d/” which no longer works because the MAC address of the networking differs on the new unit.

A further complication is that if you use a clone, then it skips first boot account setup because it thinks the account is present, but you’re removing that account. Simply removing an account might not be useful unless you are also adding another account or resetting the part which triggers first boot account setup. I’m hoping someone from NVIDIA can comment on resetting a temp file to trigger first boot setup. This is why I asked at the top of this comment about first boot setup reset.

Instead of an exact procedure, I will start with what rsync can do. There is an ability to copy any content, including device special files, symbolic link, and directory structure. There is also an ability for rsync to exclude particular files or content. Always keep in mind that before you run an rsync command you can add the--dry-runoption to see what would happen without it actually happening. It’s a great tool option.

Another option I will show is “--info=progress2,stats2”. This is purely for some feedback to the user that something is happening. The --dry-run might not be very useful without the verbosity of this option.

rsync can copy over the network via ssh tunnel. So you can copy between a running Jetson and a host PC if you desire. The host PC can loopback mount raw clones. So you can rsync between clones on the same host, or between two separate machines, including with clones as targets or just directories to contain content. When you flash normally, it creates “Linux_for_Tegra/bootloader/system.img.raw”, and then copies it to “bootloader/system.img”. You can flash using the raw image too, it just has to be renamed “system.img”. You can also create a sparse image from a raw image via the “bootloader/mksparse” utility if you use a NULL “0” filler byte option (see ./mksparse --help). Every raw image and every filesystem on every host is interchangeable via the use of rsync, loopback mounts, and clones. It is up to you to find which combination is most useful.

I will also add another equivalence which most people don’t think to use. During a normal flash the “Linux_for_Tegra/rootfs/” content is nearly an exact match to the content being flashed. I say “nearly” because the options to the flash will edit some of the “rootfs/boot/” content, e.g., the extlinux.conf, and probably device tree which is used. Other than that, the entire content is the “rootfs/” content. You can loopback mount a clone on “Linux_for_Tegra/rootfs/”, and it will, while mounted, change what is to be flashed without destroying what is under that mount. Just umount the loopback clone, and the old content magically (it’s space magic!) reappear. You will alter your clone though, but only “/boot” content. You could copy a clone, and do this with the copy. But that’s a lot of disk space and a lot of time (it might take hours to copy a really big clone).

Clones alter nothing, and as you figured, it leaves account names and passwords. You can use rsync to copy everything except those files I mentioned. You could do the inverse, and use rsync to copy only those files onto the loopback mounted clone. You could use rsync to copy everything, and then use rsync to copy everything again, but editing only the changed files (this is fairly efficient under rsync, it can use checksums to determine if two files are unchanged). For this latter, as an example, you could copy the entire clone with rsync. Then rsync just the files I named above to the clone; if the file named differs, it overwrites the one that was there. You could even rsync your clone into “Linux_for_Tegra/rootfs/”, and then rsync new password files which are original (e.g., you could “mv” the “rootfs/” to a new location, create a new rootfs/ with rsync of the clone, and then rsync the old backup of just those files which are account related.

So which work flow do you want to use? Here are some rsync and loopback mount examples…

Compare these two command…the exact command is not important, but notice that the destination or source can be local, or remote over ssh (for all commands with rsync I am assuming you use sudo, or drop into a root shell with sudo -s; the regular user name I am using is “someone”):

rsync -avczrx --dry-run --info=progress2,stats2 --numeric-ids -e 'ssh' --delete-before / root@hostpc:/home/someone/Downloads/rootfs/

# Or...
rsync -avczrx --dry-run --info=progress2,stats2 --numeric-ids -e 'ssh' --delete-before root@hostpc:/home/someone/Downloads/rootfs/ /

The first command uses the local directory “/” as a source, and “/home/someone/Downloads/rootfs/” on destination. The second command reverses this, and will overwrite the local system’s “/” with the ssh content on the local system. The source and destinations were reversed, but only the remote end uses the “name@somewhere.com:/a/path” notation. Both use “--dry-run” for safety and prevents actual copy or overwrite, but the messages on the terminal still run as if this is happening.

The --numeric-ids is important whenever you are copying across two different computers. User and group names don’t really exist, they are merely aliases for a numeric ID. If a system does not know that ID, then it will translate to be owned by someone like root. You do not want that, and on the remote system, if a user is not in common on both, then you want it to stick to the original numeric ID. Then, when restoring, presumably the numeric ID will match the original system during restore to that system. Only user root is allowed to copy via numeric ID.

You could leave out the ssh part, and copy between two subdirectories on the local machine:

rsync -avczrx --dry-run --info=progress2,stats2 --numeric-ids --delete-before ~someone/somewhere/Linux_for_Tegra/clone/* ~someone/somewhere/Linux_for_Tegra/rootfs/

This latter does not use ssh, and because we are using sudo, I used notation “~someone/” instead of just “~/”. This latter command, if you have a clone loopback mounted on “~someone/somewhere/Linux_for_Tegra/clone”, then the clone content is available there, and the clone will now update the “Linux_for_Tegra/rootfs/”. Loopback mounted clones are just directory trees mount at some point.

One could mount the “bootloader/system.img.raw” like this:

cd ~/nvidia/nvidia_sdk/JetPack...version.../Linux_for_Tegra/
mkdir clone
sudo mount -o loop ./previous_clone.img.raw ./clone
ls ./clone/
sudo mv ./rootfs/ original_rootfs
sudo rsync -avczrx --dry-run --info=progress2,stats2 --numeric-ids --delete-before ./clone/* ./rootfs/

You now have the original rootfs backup, plus the clone is what is in “rootfs/”. You could now choose to overwrite the clone in “rootfs/” with just the login files I named above, restoring the original users which did not include your clone’s user accounts (I’m splitting a very long command line with backspaces to escape newlines):

sudo rsync -avczrx --dry-run --info=progress2,stats2 --numeric-ids --delete-before \
   ./original_rootfs \
    ./original_rootfs/etc/passwd \
    ./original_rootfs/etc/passwd- \
    ./original_rootfs/etc/group \
    ./original_rootfs/etc/group- \
    ./original_rootfs/etc/gshadow \
    ./original_rootfs/etc/gshadow- \
    ./original_rootfs/etc/shadow \
    ./original_rootfs/etc/shadow- \
   ./rootfs/

That command will update just those files. Note that rsync can have many sources listed, but one destination. If you performed that above command, and now have “Linux_for_Tegra/rootfs/” content which is basically your clone with users replaced by the original content which did not have that custom user setup, the only thing which will get flashed is your adjust clone. The flash will replace kernel and device tree and extlinux.conf, perhaps others, into the rootfs/ prior to creating this image, but otherwise it is an exact match. You could log a regular flash just to see what gets used where:

sudo ./flash.sh jetson-tx2 mmcblkp1 2>&1 | tee log_flash.txt

As long as you have backed up the original “rootfs/”, and save a copy of the raw clone, you’re fairly safe to experiment. The part which I have not included (because I don’t know which files are involved) is the part I’ve asked NVIDIA to comment on: How to reset the first boot setup so the clone will think it is first boot.

You can always experiment with --dry-run --info=progress2,stats2, and find out what works. You can use ssh or local content.

If you are interested in knowing how to enable root over ssh, but only for private keys and not passwords (it’d “just work” without asking for password because it would be using keys, and refusing passwords so ssh is safe), just ask. Having key-based ssh to root on the Jetson is useful (I don’t add the Jetson ability to get to root on my host PC for security reasons; only my host can access root over ssh on Jetsons, and the Jetson sees only the public key).