Extracting a “golden” image from the current state of the OS

In many applications, it’s beneficial to prepare the operating system with pre-installed packages and specific configurations. To enable reproducibility, flashing to other devices, and sharing, creating a size-optimized replica is essential. This section explores creating such a “golden” image by extracting the current operating system state.

Considerations

Creating an image with basic tools like dd can result in a large, inefficient image file. This is because the filesystem is often much larger than necessary. This large size limits installations on devices with smaller storage capacity. This guide aims to create an optimized, minimal copy of the OS state.

The generation and validation of the golden image must be performed carefully to avoid issues.

Prerequisites

  • A USB flash drive with sufficient storage (8 GB is usually enough; check disk utilization with df -h).

  • A Linux-based PC or VM (this guide assumes Ubuntu 22.04) with administrative privileges. These operations should be adaptable to other OSs, but this guide won’t cover all cases.

  • A gateway with the desired OS state and console access.

  • Administrative privileges on the device.

  • An OS with the cl-deploy utility installed (check with which cl-deploy).

Known Limitations

If you have multiple kernels, verify the boot order after the procedure. Disabling unused kernels and checking the GRUB configuration is recommended.

Warning

  • Thoroughly test each image before production use.

  • Use a reliable USB flash drive. Poor-quality devices can cause data corruption.

  • The USB flash drive’s contents will be erased. Back up any important data.

Steps

  1. Plug a sufficiently large USB flash drive into the device (use the fastest USB interface). Zeroing out the drive’s contents is recommended but not mandatory.

  2. Log in as root

$ sudo su
  1. Use lsblk to identify the USB drive. Typically, mmcblk* devices are internal eMMC. On Debian-based gateways, the USB drive (if only one is connected) usually appears as sda

$ lsblk
...
  1. Run cl-deploy to copy the filesystem

$ cl-deploy
  1. Select the destination device using the Spacebar and press Enter (after highlighting OK)

cl-deploy: Destination device selection screen
  1. Confirm data destruction on the destination device by pressing Enter (after highlighting Yes)

cl-deploy: Destination device data destruction confirmation screen
  1. After copying, cl-deploy prompts for a reboot. Press Enter (after highlighting No)

cl-deploy: Reboot prompt
  1. Shut down the system

$ shutdown now
  1. Unplug the USB flash drive.

  2. Proceed to image extraction (unoptimized or optimized).

Extracting an Unoptimized Image

This can also be done on Windows (using Win32DiskImager) or macOS (using dd).

  1. Connect the USB flash drive to your Linux PC or VM. If using a VM, pass through the USB drive and enable port forwarding for port 22.

  2. Create a working directory

$ mkdir image && cd image
  1. Use lsblk to identify the USB drive (e.g., /dev/sdb)

$ lsblk
...
  1. Use dd to create an image replica (ensure sufficient disk space)

$ sudo dd if=/dev/sdb of=image.img bs=1M status=progress conv=fsync
  1. image.img is the unoptimized image. Note its large size.

  2. Safely unmount and eject the USB flash drive.

Extracting an Optimized Image

  1. Connect the USB flash drive (see unoptimized instructions).

  2. Create a working directory (see unoptimized instructions).

  3. Install gparted

$ sudo apt install -y gparted
  1. Identify the USB drive with lsblk (see unoptimized instructions).

  2. Start gparted

$ sudo gparted /dev/sdb
  1. Unmount all partitions in gparted.

  2. Resize the rootfs partition, minimizing used space

GParted: Partition layout before resize GParted: Partition resize dialog GParted: Partition layout after resize
  1. Close gparted.

  2. Determine the last block and block size using fdisk

$ sudo fdisk -l /dev/sdb
...
  1. Calculate the total block count (including GPT sectors).

  2. Use dd with the correct block size and count:

    $ sudo dd if=/dev/sdb of=image.img bs=512 count=6645793 status=progress conv=fsync
    
  3. Restore the GPT table using gdisk

$ sudo gdisk image.img
... (gdisk commands)
  1. image.img is now the optimized image.

Preparing the Image for Sharing

  1. Rename the image using a standard convention

$ mv image.img cthingsco-gwlight-debian-bullseye-base-20221226.img
  1. Calculate and store the SHA-256 checksum

$ sha256sum cthingsco-gwlight-debian-bullseye-base-20221226.img
...
  1. Install zip

$ sudo apt install -y zip
  1. Compress the image

$ zip -9 cthingsco-gwlight-debian-bullseye-base-20221226.zip cthingsco-gwlight-debian-bullseye-base-20221226.img
  1. The zip file is ready. Validate the image thoroughly before production use.